From decbd4b3e5b3a18b6e015c4df55d57fe7b56cc8a Mon Sep 17 00:00:00 2001 From: Alain Takoudjou <talino@tiolive.com> Date: Fri, 29 Jun 2012 18:03:42 +0200 Subject: [PATCH] Adding comments --- slapos/runner/gittools.py | 33 ++++++++ slapos/runner/utils.py | 165 +++++++++++++++++++++++++++++++++++++- slapos/runner/views.py | 11 +++ 3 files changed, 205 insertions(+), 4 deletions(-) diff --git a/slapos/runner/gittools.py b/slapos/runner/gittools.py index 65534a9..6e32586 100644 --- a/slapos/runner/gittools.py +++ b/slapos/runner/gittools.py @@ -23,6 +23,15 @@ class Popen(subprocess.Popen): self.stdin = None def cloneRepo(data): + """Clonne a repository + Args: + data: a dictionnary of parameters to use: + data['path'] is the path of the new project + data['repo'] is the url of the repository to be cloned + data['email'] is the user email + data['user'] is the name of the user + Returns: + a jsonify data""" workDir = data['path'] if not workDir: return jsonify(code=0, @@ -47,6 +56,11 @@ def cloneRepo(data): return jsonify(code=code, result=json) def gitStatus(project): + """Run git status and return status of specified project folder + Args: + project: path of the projet ti get status + Returns: + a parsed string that contains the result of git status""" code = 0 json = "" try: @@ -61,6 +75,12 @@ def gitStatus(project): return jsonify(code=code, result=json, branch=branch, dirty=isdirty) def switchBranch(project, name): + """Switch a git branch + Args: + project: directory of the local git repository + name: switch from current branch to `name` branch + Returns: + a jsonify data""" code = 0 json = "" try: @@ -78,6 +98,13 @@ def switchBranch(project, name): return jsonify(code=code, result=json) def addBranch(project, name, onlyCheckout=False): + """Add new git branch to the repository + Args: + project: directory of the local git repository + name: name of the new branch + onlyCheckout: if True then the branch `name` is created before checkout + Returns: + a jsonify data""" code = 0 json = "" try: @@ -93,6 +120,7 @@ def addBranch(project, name, onlyCheckout=False): return jsonify(code=code, result=json) def getDiff(project): + """Get git diff for the specified project directory""" result = "" try: repo = Repo(project) @@ -104,6 +132,10 @@ def getDiff(project): return result def gitPush(project, msg): + """Commit and Push changes for the specified repository + Args: + project: directory of the local repository + msg: commit message""" code = 0 json = "" undo_commit = False @@ -145,5 +177,6 @@ def gitPull(project): return jsonify(code=code, result=result) def safeResult(result): + """Parse string and remove credential of the user""" regex=re.compile("(https:\/\/)([\w\d\._-]+:[\w\d\._-]+)\@([\S]+\s)", re.VERBOSE) return regex.sub(r'\1\3', result) \ No newline at end of file diff --git a/slapos/runner/utils.py b/slapos/runner/utils.py index b1f10bd..e3f1303 100755 --- a/slapos/runner/utils.py +++ b/slapos/runner/utils.py @@ -41,6 +41,17 @@ def html_escape(text): return "".join(html_escape_table.get(c,c) for c in text) def checkLogin(config, login, pwd): + """ + User authentication method + + Args: + config: Slaprunner configuration. + login: username of the user. + pwd: password associate to username. + + Returns: + a list of user informations or False if authentication fail. + """ user = getSession(config) salt = "runner81" #to be changed current_pwd = hashlib.md5( salt + pwd ).hexdigest() @@ -49,6 +60,11 @@ def checkLogin(config, login, pwd): return False def getSession(config): + """ + Get the session data of current user. + Returns: + a list of user informations or False if fail to read data. + """ user_path = os.path.join(config['runner_workdir'], '.users') user = "" if os.path.exists(user_path): @@ -63,6 +79,17 @@ def getSession(config): return user def saveSession(config, session, account): + """ + Save account information for the current user + + Args: + config: Slaprunner configuration + session: Flask session + account: New session data to be save + + Returns: + True if all goes well or str (error message) if fail + """ user = os.path.join(config['runner_workdir'], '.users') backup = False try: @@ -88,6 +115,10 @@ def saveSession(config, session, account): return str(e) def updateProxy(config): + """ + Configure Slapos Node computer and partitions. + Send current Software Release to Slapproxy for compilation and deployment. + """ if not os.path.exists(config['instance_root']): os.mkdir(config['instance_root']) slap = slapos.slap.slap() @@ -141,6 +172,7 @@ def updateProxy(config): return True def readPid(file): + """Read process pid from file `file`""" if os.path.exists(file): data = open(file).read().strip() try: @@ -151,9 +183,17 @@ def readPid(file): def writePid(file, pid): + """Save process pid into a file `file`""" open(file, 'w').write(str(pid)) def updateInstanceParameter(config, software_type=None): + """ + Reconfigure Slapproxy to re-deploy current Software Instance with parameters. + + Args: + config: Slaprunner configuration. + software_type: reconfigure Software Instance with software type. + """ slap = slapos.slap.slap() slap.initializeConnection(config['master_url']) #Get current software release profile @@ -163,7 +203,7 @@ def updateInstanceParameter(config, software_type=None): profile = realpath(config, os.path.join(software_folder, config['software_profile'])) except: - return False + raise Exception("Software Release profile not found") #get instance parameter param_path = os.path.join(config['runner_workdir'], ".parameter.xml") xml_result = readParameters(param_path) @@ -175,6 +215,7 @@ def updateInstanceParameter(config, software_type=None): filter_kw=None, state=None, shared=False) def startProxy(config): + """Start Slapproxy server""" proxy_pid = os.path.join(config['runner_workdir'], 'proxy.pid') pid = readPid(proxy_pid) running = False @@ -193,6 +234,7 @@ def startProxy(config): def stopProxy(config): + """Stop Slapproxy server""" pid = readPid(os.path.join(config['runner_workdir'], 'proxy.pid')) if pid: try: @@ -202,10 +244,15 @@ def stopProxy(config): def removeProxyDb(config): + """Remove Slapproxy database, this is use to initialize proxy for example when + configuring new Software Release""" if os.path.exists(config['database_uri']): os.unlink(config['database_uri']) def isSoftwareRunning(config): + """ + Return True if slapgrid-sr is still running and false if slapgrid if not + """ slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-sr.pid') pid = readPid(slapgrid_pid) if pid: @@ -221,6 +268,10 @@ def isSoftwareRunning(config): def runSoftwareWithLock(config): + """ + Use Slapgrid to compile current Software Release and wait until + compilation is done + """ slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-sr.pid') if not isSoftwareRunning(config): if not os.path.exists(config['software_root']): @@ -262,6 +313,9 @@ def runSoftwareWithLock(config): def isInstanceRunning(config): + """ + Return True if slapgrid-cp is still running and false if slapgrid if not + """ slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid') pid = readPid(slapgrid_pid) if pid: @@ -276,6 +330,7 @@ def isInstanceRunning(config): return running def killRunningSlapgrid(config, ptype): + """Kill slapgrid process and all running children process""" slapgrid_pid = os.path.join(config['runner_workdir'], ptype) pid = readPid(slapgrid_pid) if pid: @@ -304,6 +359,10 @@ def pidppid(pid): return list(int(p) for p, pp in ppid if int(pp) == pid) def runInstanceWithLock(config): + """ + Use Slapgrid to deploy current Software Release and wait until + deployment is done. + """ slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid') if not isInstanceRunning(config): startProxy(config) @@ -317,13 +376,24 @@ def runInstanceWithLock(config): return True return False -def getProfilePath(peojectDir, profile): - if not os.path.exists(os.path.join(peojectDir, ".project")): +def getProfilePath(projectDir, profile): + """ + Return the path of the current Software Release `profile` + + Args: + projectDir: Slaprunner workspace location. + profile: file to search into the workspace. + + Returns: + String, path of current Software Release profile + """ + if not os.path.exists(os.path.join(projectDir, ".project")): return False - projectFolder = open(os.path.join(peojectDir, ".project")).read() + projectFolder = open(os.path.join(projectDir, ".project")).read() return os.path.join(projectFolder, profile) def getSlapStatus(config): + """Return all Slapos Partitions with associate informations""" slap = slapos.slap.slap() slap.initializeConnection(config['master_url']) partition_list = [] @@ -354,10 +424,12 @@ def runBuildoutAnnotate(config): return False def svcStopAll(config): + """Stop all Instance process on this computer""" return Popen([config['supervisor'], config['configuration_file_path'], 'shutdown']).communicate()[0] def removeInstanceRoot(config): + """Clean instance directory and stop all its running process""" if os.path.exists(config['instance_root']): svcStopAll(config) for root, dirs, files in os.walk(config['instance_root']): @@ -369,6 +441,7 @@ def removeInstanceRoot(config): shutil.rmtree(config['instance_root']) def getSvcStatus(config): + """Return all Softwares Instances process Informations""" result = Popen([config['supervisor'], config['configuration_file_path'], 'status']).communicate()[0] regex = "(^unix:.+\.socket)|(^error:).*$" @@ -382,15 +455,40 @@ def getSvcStatus(config): return supervisord def getSvcTailProcess(config, process): + """Get log for the specifie process + + Args: + config: Slaprunner configuration + process: process name. this value is pass to supervisord. + Returns: + a string that contains the log of the process. + """ return Popen([config['supervisor'], config['configuration_file_path'], "tail", process]).communicate()[0] def svcStartStopProcess(config, process, action): + """Send start or stop process command to supervisord + + Args: + config: Slaprunner configuration. + process: process to start or stop. + action: current state which is used to generate the new process state. + """ cmd = {"RESTART":"restart", "STOPPED":"start", "RUNNING":"stop", "EXITED":"start", "STOP":"stop"} return Popen([config['supervisor'], config['configuration_file_path'], cmd[action], process]).communicate()[0] def getFolderContent(config, folder): + """ + Read all file and folder into specified directory + + Args: + config: Slaprunner configuration. + folder: the directory to read. + + Returns: + Html formated string or error message when fail. + """ r=['<ul class="jqueryFileTree" style="display: none;">'] try: folder = str(folder) @@ -418,6 +516,16 @@ def getFolderContent(config, folder): return jsonify(result=''.join(r)) def getFolder(config, folder): + """ + Read list of folder for the specified directory + + Args: + config: Slaprunner configuration. + folder: the directory to read. + + Returns: + Html formated string or error message when fail. + """ r=['<ul class="jqueryFileTree" style="display: none;">'] try: folder = str(folder) @@ -442,6 +550,13 @@ def getFolder(config, folder): return jsonify(result=''.join(r)) def getProjectList(folder): + """Return the list of projet (folder) into the workspace + + Agrs: + folder: path of the workspace + Returns: + a list that contains each folder name. + """ project = [] project_list = sorted(os.listdir(folder), key=str.lower) for elt in project_list: @@ -449,6 +564,14 @@ def getProjectList(folder): return project def configNewSR(config, projectpath): + """Configure a Software Release as current Software Release + + Args: + config: slaprunner configuration + projectpath: path of the directory that contains the software realease to configure + Returns: + True if all is done well, otherwise return false. + """ folder = realpath(config, projectpath) if folder: if isInstanceRunning(config): @@ -465,6 +588,13 @@ def configNewSR(config, projectpath): return False def newSoftware(folder, config, session): + """ + Create a new Software Release folder with default profiles + + Args: + folder: directory of the new software release + config: slraprunner configuration + session: Flask session directory""" json = "" code = 0 runner_dir = config['runner_workdir'] @@ -498,12 +628,14 @@ def newSoftware(folder, config, session): return jsonify(code=code, result=json) def checkSoftwareFolder(path, config): + """Check id `path` is a valid Software Release folder""" realdir = realpath(config, path) if realdir and os.path.exists(os.path.join(realdir, config['software_profile'])): return jsonify(result=path) return jsonify(result="") def getProjectTitle(config): + """Generate the name of the current software Release (for slaprunner UI)""" conf = os.path.join(config['runner_workdir'], ".project") if os.path.exists(conf): project = open(conf, "r").read().split("/") @@ -512,6 +644,7 @@ def getProjectTitle(config): return "No Profile" def getSoftwareReleaseName(config): + """Get the name of the current Software Release""" sr_profile = os.path.join(config['runner_workdir'], ".project") if os.path.exists(sr_profile): project = open(sr_profile, "r").read().split("/") @@ -520,6 +653,12 @@ def getSoftwareReleaseName(config): return "No_name" def loadSoftwareData(runner_dir): + """Get All Compiled Softwares Releases name and directory + + Agrs: + runner_dir: base directory of slapos web runner. + Returns: + a dictionnary that contains all compiled Software Release with path""" import pickle file_path = os.path.join(runner_dir, '.softdata') if not os.path.exists(file_path): @@ -530,6 +669,12 @@ def loadSoftwareData(runner_dir): return data def writeSoftwareData(runner_dir, data): + """Save the list of compiled Software Release into a file + + Args: + runner_dir: base directory of slapos web runner. + data: dictionnary data about real name and directory of each software release + """ import pickle file_path = os.path.join(runner_dir, '.softdata') pkl_file = open(file_path, 'wb') @@ -538,6 +683,11 @@ def writeSoftwareData(runner_dir, data): pkl_file.close() def removeSoftwareByName(config, folderName): + """Remove all content of the specified software release + + Args: + config: slaprunner configuration + foldername: the name given to the software release""" if isSoftwareRunning(config) or isInstanceRunning(config): raise Exception("Software installation or instantiation in progress, cannot remove") path = os.path.join(config['software_root'], folderName) @@ -662,6 +812,13 @@ def realpath(config, path, check_exist=True): return False def readParameters(path): + """Read Instance parameters stored into a local file. + + Agrs: + path: path of the xml file that contains parameters + + Return: + a dictionnary of instance parameters.""" if os.path.exists(path): try: xmldoc = minidom.parse(path) diff --git a/slapos/runner/views.py b/slapos/runner/views.py index c853a08..f7d7912 100755 --- a/slapos/runner/views.py +++ b/slapos/runner/views.py @@ -77,6 +77,7 @@ def inspectSoftware(): return render_template('runResult.html', softwareRoot='software_root', softwares=loadSoftwareData(app.config['runner_workdir'])) +#remove content of compiled software release @app.route('/removeSoftware') def removeSoftware(): file_config = os.path.join(app.config['runner_workdir'], ".softdata") @@ -114,6 +115,7 @@ def editInstanceProfile(): return render_template('updateInstanceProfile.html', workDir='workspace', profile=profile, projectList=getProjectList(app.config['workspace'])) +# get status of all computer partitions and process state @app.route('/inspectInstance', methods=['GET']) def inspectInstance(): file_content = '' @@ -127,6 +129,7 @@ def inspectInstance(): file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config), supervisore=result, partition_amount=app.config['partition_amount']) +#Reload instance process ans returns new value to ajax @app.route('/supervisordStatus', methods=['GET']) def supervisordStatus(): result = getSvcStatus(app.config) @@ -253,6 +256,7 @@ def getProjectStatus(): else: return jsonify(code=0, result="Can not read folder: Permission Denied") +#view for current software release files @app.route("/editCurrentProject") def editCurrentProject(): project = os.path.join(app.config['runner_workdir'], ".project") @@ -262,6 +266,7 @@ def editCurrentProject(): projectList=getProjectList(app.config['workspace'])) return redirect(url_for('configRepo')) +#create file or directory @app.route("/createFile", methods=['POST']) def createFile(): path = realpath(app.config, request.form['file'], False) @@ -277,6 +282,7 @@ def createFile(): except Exception, e: return jsonify(code=0, result=str(e)) +#remove file or directory @app.route("/removeFile", methods=['POST']) def removeFile(): try: @@ -296,6 +302,7 @@ def removeSoftwareDir(): except Exception, e: return jsonify(code=0, result=str(e)) +#read file and return content to ajax @app.route("/getFileContent", methods=['POST']) def getFileContent(): file_path = realpath(app.config, request.form['file']) @@ -379,6 +386,7 @@ def getmd5sum(): else: return jsonify(code=0, result="Can not get md5sum for this file!") +#return informations about state of slapgrid process @app.route("/slapgridResult", methods=['POST']) def slapgridResult(): software_state = isSoftwareRunning(app.config) @@ -415,6 +423,7 @@ def getPath(): else: return jsonify(code=1, result=realfile) +#update instance parameter into a local xml file @app.route("/saveParameterXml", methods=['POST']) def saveParameterXml(): project = os.path.join(app.config['runner_workdir'], ".project") @@ -441,6 +450,7 @@ def saveParameterXml(): return jsonify(code=0, result="An error occurred while applying your settings!<br/>" + str(e)) return jsonify(code=1, result="") +#read instance parameters into the local xml file and return a dict @app.route("/getParameterXml/<request>", methods=['GET']) def getParameterXml(request): param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml") @@ -457,6 +467,7 @@ def getParameterXml(request): else: return jsonify(code=1, result=parameters) +#update user account data @app.route("/updateAccount", methods=['POST']) def updateAccount(): account = [] -- 2.30.9