views.py 21.2 KB
Newer Older
1 2
# -*- coding: utf-8 -*-

Łukasz Nowak's avatar
Łukasz Nowak committed
3
from flask import Flask, request, redirect, url_for, \
4
         render_template, g, flash, jsonify, session
5
from utils import *
Łukasz Nowak's avatar
Łukasz Nowak committed
6 7
import os
import shutil
8
import md5
9
from gittools import cloneRepo, gitStatus, switchBranch, addBranch, getDiff, \
10
     gitPush, gitPull
Alain Takoudjou's avatar
Alain Takoudjou committed
11
from flaskext.auth import Auth, AuthUser, login_required, logout
Łukasz Nowak's avatar
Łukasz Nowak committed
12 13

app = Flask(__name__)
14 15 16 17 18
auth = Auth(app, login_url_name='login')
auth.user_timeout = 0

def login_redirect(*args, **kwargs):
  return redirect(url_for('login'))
Łukasz Nowak's avatar
Łukasz Nowak committed
19

20
#Access Control: Only static files and login pages are allowed to guest
21 22
@app.before_request
def before_request():
23 24 25
  if not request.path.startswith('/static'):
    account = getSession(app.config)
    if account:
26 27
      user = AuthUser(username=account[0])
      user.set_and_encrypt_password(account[1], "123400ZYX")
28
      session['title'] = getProjectTitle(app.config)
29
      g.users = {account[0]: user}
30 31
    else:
      session['title'] = "No account is defined"
32 33
      if request.path != "/setAccount" and request.path != "/configAccount":
        return redirect(url_for('setAccount'))
34

Łukasz Nowak's avatar
Łukasz Nowak committed
35
# general views
36
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
37 38 39
def home():
  return render_template('index.html')

40 41 42 43
@app.route("/login")
def login():
  return render_template('login.html')

44 45 46 47
@app.route("/setAccount")
def setAccount():
  account = getSession(app.config)
  if not account:
48
    return render_template('account.html')
49 50 51 52 53 54 55
  return redirect(url_for('login'))

@login_required()
def myAccount():
  account = getSession(app.config)
  return render_template('account.html', username=account[0],
          email=account[2], name=account[3].decode('utf-8'))
56

57 58 59
@app.route("/dologout")
def dologout():
  user_data = logout()
60 61
  return redirect(url_for('login'))

62
@login_required()
63 64
def configRepo():
  public_key = open(app.config['public_key'], 'r').read()
65
  account = getSession(app.config)
66
  return render_template('cloneRepository.html', workDir='workspace',
67 68
            public_key=public_key, name=account[3].decode('utf-8'),
            email=account[2])
69

70 71
@app.route("/doLogin", methods=['POST'])
def doLogin():
72 73 74 75 76 77
  username = request.form['clogin']
  if username in g.users:
    # Authenticate and log in!
    if g.users[username].authenticate(request.form['cpwd']):
      return jsonify(code=1, result="")
  return jsonify(code=0, result="Login or password is incorrect, please check it!")
78

Łukasz Nowak's avatar
Łukasz Nowak committed
79
# software views
80
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
81
def editSoftwareProfile():
82
  profile = getProfilePath(app.config['runner_workdir'], app.config['software_profile'])
83 84
  if profile == "":
    flash('Error: can not open profile, please select your project first')
85 86
  return render_template('updateSoftwareProfile.html', workDir='workspace',
      profile=profile, projectList=getProjectList(app.config['workspace']))
Łukasz Nowak's avatar
Łukasz Nowak committed
87

88
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
89 90
def inspectSoftware():
  if not os.path.exists(app.config['software_root']):
91
    result = ""
Łukasz Nowak's avatar
Łukasz Nowak committed
92
  else:
93 94
    result = app.config['software_root']
  return render_template('runResult.html', softwareRoot='software_root',
95
                         softwares=loadSoftwareData(app.config['runner_workdir']))
Łukasz Nowak's avatar
Łukasz Nowak committed
96

Alain Takoudjou's avatar
Alain Takoudjou committed
97
#remove content of compiled software release
98
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
99
def removeSoftware():
100
  file_config = os.path.join(app.config['runner_workdir'], ".softdata")
Łukasz Nowak's avatar
Łukasz Nowak committed
101 102
  if isSoftwareRunning(app.config) or isInstanceRunning(app.config):
    flash('Software installation or instantiation in progress, cannot remove')
103
  elif os.path.exists(file_config):
Łukasz Nowak's avatar
Łukasz Nowak committed
104 105
    svcStopAll(app.config)
    shutil.rmtree(app.config['software_root'])
106
    os.remove(os.path.join(app.config['runner_workdir'], ".softdata"))
Łukasz Nowak's avatar
Łukasz Nowak committed
107 108 109
    flash('Software removed')
  return redirect(url_for('inspectSoftware'))

110
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
111 112
def runSoftwareProfile():
  if runSoftwareWithLock(app.config):
113
    return  jsonify(result = True)
Łukasz Nowak's avatar
Łukasz Nowak committed
114
  else:
115
    return  jsonify(result = False)
Łukasz Nowak's avatar
Łukasz Nowak committed
116

117
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
118 119
def viewSoftwareLog():
  if os.path.exists(app.config['software_log']):
120
    result = tail(open(app.config['software_log'], 'r'), lines=1500)
Łukasz Nowak's avatar
Łukasz Nowak committed
121 122
  else:
    result = 'Not found yet'
123 124
  return render_template('viewLog.html', type='software',
      result=result)
Łukasz Nowak's avatar
Łukasz Nowak committed
125 126

# instance views
127
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
128
def editInstanceProfile():
129
  profile = getProfilePath(app.config['runner_workdir'], app.config['instance_profile'])
130
  if profile == "":
131 132 133
    flash('Error: can not open instance profile for this Software Release')
  return render_template('updateInstanceProfile.html', workDir='workspace',
      profile=profile, projectList=getProjectList(app.config['workspace']))
Łukasz Nowak's avatar
Łukasz Nowak committed
134

Alain Takoudjou's avatar
Alain Takoudjou committed
135
# get status of all computer partitions and process state
136
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
137
def inspectInstance():
138 139
  file_content = ''
  result = ''
Łukasz Nowak's avatar
Łukasz Nowak committed
140
  if os.path.exists(app.config['instance_root']):
141
    file_content = 'instance_root'
142
    result = getSvcStatus(app.config)
143
    if len(result) == 0:
144
      result = []
Łukasz Nowak's avatar
Łukasz Nowak committed
145
  return render_template('instanceInspect.html',
146
      file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config),
147
      supervisore=result, partition_amount=app.config['partition_amount'])
Łukasz Nowak's avatar
Łukasz Nowak committed
148

Alain Takoudjou's avatar
Alain Takoudjou committed
149
#Reload instance process ans returns new value to ajax
150
@login_required()
151 152 153 154 155 156 157 158 159 160 161 162 163 164
def supervisordStatus():
  result = getSvcStatus(app.config)
  if not (result):
    return jsonify(code=0, result="")
  html = "<tr><th>Partition and Process name</th><th>Status</th><th>Process PID </th><th> UpTime</th><th></th></tr>"
  for item in result:
    html += "<tr>"
    html +="<td  class='first'><b><a href='" + url_for('tailProcess', process=item[0])+"'>"+item[0]+"</a></b></td>"
    html +="<td align='center'><a href='"+url_for('startStopProccess', process=item[0], action=item[1])+"'>"+item[1]+"</a></td>"
    html +="<td align='center'>"+item[3]+"</td><td>"+item[5]+"</td>"
    html +="<td align='center'><a href='"+url_for('startStopProccess', process=item[0], action='RESTART')+"'>Restart</a></td>"
    html +="</tr>"
  return jsonify(code=1, result=html)

165
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
166 167 168
def removeInstance():
  if isInstanceRunning(app.config):
    flash('Instantiation in progress, cannot remove')
169
  else:
170 171 172
    stopProxy(app.config)
    removeProxyDb(app.config)
    startProxy(app.config)
173
    removeInstanceRoot(app.config)
174 175 176
    param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
    if os.path.exists(param_path):
      os.remove(param_path)
Łukasz Nowak's avatar
Łukasz Nowak committed
177 178 179
    flash('Instance removed')
  return redirect(url_for('inspectInstance'))

180
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
181 182 183 184
def runInstanceProfile():
  if not os.path.exists(app.config['instance_root']):
    os.mkdir(app.config['instance_root'])
  if runInstanceWithLock(app.config):
185
    return  jsonify(result = True)
Łukasz Nowak's avatar
Łukasz Nowak committed
186
  else:
187
    return  jsonify(result = False)
Łukasz Nowak's avatar
Łukasz Nowak committed
188

189
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
190 191 192 193 194
def viewInstanceLog():
  if os.path.exists(app.config['instance_log']):
    result = open(app.config['instance_log'], 'r').read()
  else:
    result = 'Not found yet'
195 196
  return render_template('viewLog.html', type='instance',
      result=result)
Łukasz Nowak's avatar
Łukasz Nowak committed
197

198
@login_required()
Łukasz Nowak's avatar
Łukasz Nowak committed
199 200 201
def stopAllPartition():
  svcStopAll(app.config)
  return redirect(url_for('inspectInstance'))
202

203
@login_required(login_redirect)
204 205 206 207
def tailProcess(process):
  return render_template('processTail.html',
      process_log=getSvcTailProcess(app.config, process), process=process)

208
@login_required(login_redirect)
209 210 211 212
def startStopProccess(process, action):
  svcStartStopProcess(app.config, process, action)
  return redirect(url_for('inspectInstance'))

213
@login_required()
214 215 216 217 218 219 220 221
def viewBuildoudAnnotate():
  if os.path.exists(app.config['annotate_log']):
    result = open(app.config['annotate_log'], 'r').read()
  else:
    result = 'Not found yet'
  return render_template('viewLog.html', type='Instance',
      result=result, running=isInstanceRunning(app.config))

222
@login_required(login_redirect)
223
def openProject(method):
224 225
  return render_template('projectFolder.html', method=method,
                         workDir='workspace')
226

227
@login_required()
228
def cloneRepository():
229 230 231
  path = realpath(app.config, request.form['name'], False)
  data = {"repo":request.form['repo'], "user":request.form['user'],
          "email":request.form['email'], "path":path}
232
  return cloneRepo(data)
233

234
@login_required()
235
def readFolder():
236
  return getFolderContent(app.config, request.form['dir'])
237

238
@login_required()
239
def openFolder():
240
  return getFolder(app.config, request.form['dir'])
241

242
@login_required()
243
def createSoftware():
244
  return newSoftware(request.form['folder'], app.config, session)
245

246
@login_required()
247 248 249
def checkFolder():
  return checkSoftwareFolder(request.form['path'], app.config)

250
@login_required()
251 252
def setCurrentProject():
  if configNewSR(app.config, request.form['path']):
253 254 255
    session['title'] = getProjectTitle(app.config)
    return jsonify(code=1, result="")
  else:
256
    return jsonify(code=0, result=("Can not setup this Software Release"))
257

258
@login_required()
259
def manageProject():
260
  return render_template('manageProject.html', workDir='workspace',
261 262
                         project=getProjectList(app.config['workspace']))

263
@login_required()
264
def getProjectStatus():
265 266 267 268 269
  path = realpath(app.config, request.form['project'])
  if path:
    return gitStatus(path)
  else:
    return jsonify(code=0, result="Can not read folder: Permission Denied")
270

Alain Takoudjou's avatar
Alain Takoudjou committed
271
#view for current software release files
272
@login_required()
273
def editCurrentProject():
274 275
  project = os.path.join(app.config['runner_workdir'], ".project")
  if os.path.exists(project):
276 277 278
    return render_template('softwareFolder.html', workDir='workspace',
                           project=open(project).read(),
                           projectList=getProjectList(app.config['workspace']))
279 280
  return redirect(url_for('configRepo'))

Alain Takoudjou's avatar
Alain Takoudjou committed
281
#create file or directory
282
@login_required()
283
def createFile():
284 285 286 287
  path = realpath(app.config, request.form['file'], False)
  if not path:
    return jsonify(code=0, result="Error when creating your " + \
                   request.form['type'] + ": Permission Denied")
288 289
  try:
    if request.form['type'] == "file":
290
      f = open(path, 'w').write(" ")
291
    else:
292
      os.mkdir(path)
293 294 295 296
    return jsonify(code=1, result="")
  except Exception, e:
    return jsonify(code=0, result=str(e))

Alain Takoudjou's avatar
Alain Takoudjou committed
297
#remove file or directory
298
@login_required()
299 300 301 302 303 304 305 306 307
def removeFile():
  try:
    if request.form['type'] == "folder":
      shutil.rmtree(request.form['path'])
    else:
      os.remove(request.form['path'])
    return jsonify(code=1, result="")
  except Exception, e:
    return jsonify(code=0, result=str(e))
308

309
@login_required()
310
def removeSoftwareDir():
311 312 313 314 315
  try:
    data = removeSoftwareByName(app.config, request.form['name'])
    return jsonify(code=1, result=data)
  except Exception, e:
    return jsonify(code=0, result=str(e))
316

Alain Takoudjou's avatar
Alain Takoudjou committed
317
#read file and return content to ajax
318
@login_required()
319
def getFileContent():
320 321
  file_path = realpath(app.config, request.form['file'])
  if file_path:
322
    if not request.form.has_key('truncate'):
323
      return jsonify(code=1, result=open(file_path, 'r').read())
324
    else:
325
      content = tail(open(file_path, 'r'), int(request.form['truncate']))
326
      return jsonify(code=1, result=content)
327 328
  else:
    return jsonify(code=0, result="Error: No such file!")
329

330
@login_required()
331
def saveFileContent():
332 333
  file_path = realpath(app.config, request.form['file'])
  if file_path:
334
    open(file_path, 'w').write(request.form['content'].encode("utf-8"))
335 336
    return jsonify(code=1, result="")
  else:
337 338
    return jsonify(code=0, result="Error: No such file!")

339
@login_required()
340
def changeBranch():
341 342 343 344 345
  path = realpath(app.config, request.form['project'])
  if path:
    return switchBranch(path, request.form['name'])
  else:
    return jsonify(code=0, result="Can not read folder: Permission Denied")
346

347
@login_required()
348
def newBranch():
349 350 351 352 353 354 355 356
  path = realpath(app.config, request.form['project'])
  if path:
    if request.form['create'] == '1':
      return addBranch(path, request.form['name'])
    else:
      return addBranch(path, request.form['name'], True)
  else:
    return jsonify(code=0, result="Can not read folder: Permission Denied")
357

358
@login_required(login_redirect)
359 360 361 362 363
def getProjectDiff(project):
  path = os.path.join(app.config['workspace'], project)
  return render_template('projectDiff.html', project=project,
                           diff=getDiff(path))

364
@login_required()
365
def pushProjectFiles():
366 367 368 369 370
  path = realpath(app.config, request.form['project'])
  if path:
    return gitPush(path, request.form['msg'])
  else:
    return jsonify(code=0, result="Can not read folder: Permission Denied")
371

372
@login_required()
373
def pullProjectFiles():
374 375 376 377 378
  path = realpath(app.config, request.form['project'])
  if path:
    return gitPull(path)
  else:
    return jsonify(code=0, result="Can not read folder: Permission Denied")
379

380
@login_required()
381
def checkFileType():
382 383 384
  path = realpath(app.config, request.form['path'])
  if not path:
    return jsonify(code=0, result="Can not open file: Permission Denied!")
385 386 387
  if isText(path):
    return jsonify(code=1, result="text")
  else:
388
    return jsonify(code=0, result="Can not open a binary file, please select a text file!")
389

390
@login_required()
391
def getmd5sum():
392 393 394 395
  realfile = realpath(app.config, request.form['file'])
  if not realfile:
    return jsonify(code=0, result="Can not open file: Permission Denied!")
  md5 = md5sum(realfile)
396 397 398
  if md5:
    return jsonify(code=1, result=md5)
  else:
399 400
    return jsonify(code=0, result="Can not get md5sum for this file!")

Alain Takoudjou's avatar
Alain Takoudjou committed
401
#return informations about state of slapgrid process
402
@login_required()
403 404 405 406 407 408 409 410 411 412 413 414 415
def slapgridResult():
  software_state = isSoftwareRunning(app.config)
  instance_state = isInstanceRunning(app.config)
  log_result = {"content":"", "position":0}
  if request.form['log'] == "software"  or\
     request.form['log'] == "instance":
    log_file = request.form['log'] + "_log"
    if os.path.exists(app.config[log_file]):
      log_result = readFileFrom(open(app.config[log_file], 'r'),
                            int(request.form['position']))
  return  jsonify(software=software_state, instance=instance_state,
                  result=(instance_state or software_state), content=log_result)

416
@login_required()
417 418 419 420
def stopSlapgrid():
  result = killRunningSlapgrid(app.config, request.form['type'])
  return jsonify(result=result)

421
@login_required()
422 423 424 425 426 427 428 429 430 431 432 433 434 435
def getPath():
  files = request.form['file'].split('#')
  list = []
  for p in files:
    path = realpath(app.config, p)
    if not p:
      list = []
      break
    else:
      list.append(path)
  realfile = string.join(list, "#")
  if not realfile:
    return jsonify(code=0, result="Can not access to this file: Permission Denied!")
  else:
436 437
    return jsonify(code=1, result=realfile)

Alain Takoudjou's avatar
Alain Takoudjou committed
438
#update instance parameter into a local xml file
439
@login_required()
440
def saveParameterXml():
441 442 443
  project = os.path.join(app.config['runner_workdir'], ".project")
  if not os.path.exists(project):
    return jsonify(code=0, result="Please first open a Software Release")
444
  content = request.form['parameter'].encode("utf-8")
445
  param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
446 447 448 449 450 451 452
  try:
    f = open(param_path, 'w')
    f.write(content)
    f.close()
    result = readParameters(param_path)
  except Exception, e:
      result = str(e)
453 454 455
  software_type = None
  if(request.form['software_type']):
    software_type = request.form['software_type']
456
  if type(result) == type(''):
457
    return jsonify(code=0, result=result)
458
  else:
459
    try:
460 461 462
      updateInstanceParameter(app.config, software_type)
    except Exception, e:
      return jsonify(code=0, result="An error occurred while applying your settings!<br/>" + str(e))
463 464
    return jsonify(code=1, result="")

Alain Takoudjou's avatar
Alain Takoudjou committed
465
#read instance parameters into the local xml file and return a dict
466
@login_required()
467
def getParameterXml(request):
468
  param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
469 470 471 472 473 474 475 476 477 478
  if not os.path.exists(param_path):
    default = '<?xml version="1.0" encoding="utf-8"?>\n'
    default += '<instance>\n</instance>'
    return jsonify(code=1, result=default)
  if request == "xml":
    parameters = open(param_path, 'r').read()
  else:
    parameters = readParameters(param_path)
  if type(parameters) == type('') and request != "xml":
    return jsonify(code=0, result=parameters)
479
  else:
480 481 482
    return jsonify(code=1, result=parameters)

#update user account data
483
@login_required()
484 485 486 487 488 489 490
def updateAccount():
  account = []
  user = os.path.join(app.config['runner_workdir'], '.users')
  account.append(request.form['username'].strip())
  account.append(request.form['password'].strip())
  account.append(request.form['email'].strip())
  account.append(request.form['name'].strip())
491 492 493 494
  code = request.form['rcode'].strip()
  recovery_code = open(os.path.join(app.config['etc_dir'], ".rcode"), "r").read()
  if code != recovery_code:
    return jsonify(code=0, result="Your password recovery code is not valid!")
495
  result = saveSession(app.config, account)
496 497 498
  if type(result) == type(""):
    return jsonify(code=0, result=result)
  else:
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    return jsonify(code=1, result="")

#update user account data
@app.route("/configAccount", methods=['POST'])
def configAccount():
  last_account = getSession(app.config)
  if not last_account:
    account = []
    user = os.path.join(app.config['runner_workdir'], '.users')
    account.append(request.form['username'].strip())
    account.append(request.form['password'].strip())
    account.append(request.form['email'].strip())
    account.append(request.form['name'].strip())
    code = request.form['rcode'].strip()
    recovery_code = open(os.path.join(app.config['etc_dir'], ".rcode"), "r").read()
    if code != recovery_code:
      return jsonify(code=0, result="Your password recovery code is not valid!")
    result = saveSession(app.config, account)
    if type(result) == type(""):
      return jsonify(code=0, result=result)
    else:
      return jsonify(code=1, result="")
  return jsonify(code=0, result="Unable to respond to your request, permission denied.")

#Setup List of URLs
app.add_url_rule('/', 'home', home)
app.add_url_rule('/editSoftwareProfile', 'editSoftwareProfile', editSoftwareProfile)
app.add_url_rule('/inspectSoftware', 'inspectSoftware', inspectSoftware)
app.add_url_rule('/removeSoftware', 'removeSoftware', removeSoftware)
Alain Takoudjou's avatar
Alain Takoudjou committed
528 529
app.add_url_rule('/runSoftwareProfile', 'runSoftwareProfile', runSoftwareProfile, methods=['POST'])
app.add_url_rule('/viewSoftwareLog', 'viewSoftwareLog', viewSoftwareLog, methods=['GET'])
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
app.add_url_rule('/editInstanceProfile', 'editInstanceProfile', editInstanceProfile)
app.add_url_rule('/inspectInstance', 'inspectInstance', inspectInstance, methods=['GET'])
app.add_url_rule('/supervisordStatus', 'supervisordStatus', supervisordStatus, methods=['GET'])
app.add_url_rule('/runInstanceProfile', 'runInstanceProfile', runInstanceProfile, methods=['POST'])
app.add_url_rule('/removeInstance', 'removeInstance', removeInstance)
app.add_url_rule('/viewInstanceLog', 'viewInstanceLog', viewInstanceLog, methods=['GET'])
app.add_url_rule('/stopAllPartition', 'stopAllPartition', stopAllPartition, methods=['GET'])
app.add_url_rule('/tailProcess/name/<process>', 'tailProcess', tailProcess, methods=['GET'])
app.add_url_rule('/startStopProccess/name/<process>/cmd/<action>', 'startStopProccess', startStopProccess, methods=['GET'])
app.add_url_rule('/viewBuildoudAnnotate', 'viewBuildoudAnnotate', viewBuildoudAnnotate, methods=['GET'])
app.add_url_rule("/getParameterXml/<request>", 'getParameterXml', getParameterXml, methods=['GET'])
app.add_url_rule("/stopSlapgrid", 'stopSlapgrid', stopSlapgrid, methods=['POST'])
app.add_url_rule("/slapgridResult", 'slapgridResult', slapgridResult, methods=['POST'])
app.add_url_rule("/getmd5sum", 'getmd5sum', getmd5sum, methods=['POST'])
app.add_url_rule("/checkFileType", 'checkFileType', checkFileType, methods=['POST'])
app.add_url_rule("/pullProjectFiles", 'pullProjectFiles', pullProjectFiles, methods=['POST'])
app.add_url_rule("/pushProjectFiles", 'pushProjectFiles', pushProjectFiles, methods=['POST'])
app.add_url_rule("/getProjectDiff/<project>", 'getProjectDiff', getProjectDiff, methods=['GET'])
app.add_url_rule("/newBranch", 'newBranch', newBranch, methods=['POST'])
app.add_url_rule("/changeBranch", 'changeBranch', changeBranch, methods=['POST'])
app.add_url_rule("/saveFileContent", 'saveFileContent', saveFileContent, methods=['POST'])
app.add_url_rule("/removeSoftwareDir", 'removeSoftwareDir', removeSoftwareDir, methods=['POST'])
app.add_url_rule("/getFileContent", 'getFileContent', getFileContent, methods=['POST'])
app.add_url_rule("/removeFile", 'removeFile', removeFile, methods=['POST'])
app.add_url_rule("/createFile", 'createFile', createFile, methods=['POST'])
app.add_url_rule("/editCurrentProject", 'editCurrentProject', editCurrentProject)
app.add_url_rule("/getProjectStatus", 'getProjectStatus', getProjectStatus, methods=['POST'])
app.add_url_rule('/openProject/<method>', 'openProject', openProject, methods=['GET'])
app.add_url_rule("/manageProject", 'manageProject', manageProject, methods=['GET'])
app.add_url_rule("/setCurrentProject", 'setCurrentProject', setCurrentProject, methods=['POST'])
app.add_url_rule("/checkFolder", 'checkFolder', checkFolder, methods=['POST'])
app.add_url_rule('/createSoftware', 'createSoftware', createSoftware, methods=['POST'])
app.add_url_rule('/cloneRepository', 'cloneRepository', cloneRepository, methods=['POST'])
app.add_url_rule('/openFolder', 'openFolder', openFolder, methods=['POST'])
app.add_url_rule('/readFolder', 'readFolder', readFolder, methods=['POST'])
app.add_url_rule('/configRepo', 'configRepo', configRepo)
app.add_url_rule("/saveParameterXml", 'saveParameterXml', saveParameterXml, methods=['POST'])
app.add_url_rule("/getPath", 'getPath', getPath, methods=['POST'])
app.add_url_rule("/myAccount", 'myAccount', myAccount)
app.add_url_rule("/updateAccount", 'updateAccount', updateAccount, methods=['POST'])