Commit 5f34b3f6 authored by Marco Mariani's avatar Marco Mariani

some pep8 love

parent 17a77af3
...@@ -21,8 +21,7 @@ class Parser(OptionParser): ...@@ -21,8 +21,7 @@ class Parser(OptionParser):
""" """
Initialize all possible options. Initialize all possible options.
""" """
OptionParser.__init__(self, usage=usage, version=version, option_list = [
option_list=[
Option("-l", "--log_file", Option("-l", "--log_file",
help="The path to the log file used by the script.", help="The path to the log file used by the script.",
type=str), type=str),
...@@ -38,7 +37,10 @@ class Parser(OptionParser): ...@@ -38,7 +37,10 @@ class Parser(OptionParser):
default=False, default=False,
action="store_true", action="store_true",
help="Debug mode."), help="Debug mode."),
]) ]
OptionParser.__init__(self, usage=usage, version=version,
option_list=option_list)
def check_args(self): def check_args(self):
""" """
...@@ -50,6 +52,7 @@ class Parser(OptionParser): ...@@ -50,6 +52,7 @@ class Parser(OptionParser):
return options, args[0] return options, args[0]
class Config: class Config:
def __init__(self): def __init__(self):
self.configuration_file_path = None self.configuration_file_path = None
...@@ -125,6 +128,7 @@ def run(): ...@@ -125,6 +128,7 @@ def run():
sys.exit(return_code) sys.exit(return_code)
def serve(config): def serve(config):
from views import app from views import app
from werkzeug.contrib.fixers import ProxyFix from werkzeug.contrib.fixers import ProxyFix
...@@ -134,7 +138,7 @@ def serve(config): ...@@ -134,7 +138,7 @@ def serve(config):
app.config.update( app.config.update(
software_log=config.software_root.rstrip('/') + '.log', software_log=config.software_root.rstrip('/') + '.log',
instance_log=config.instance_root.rstrip('/') + '.log', instance_log=config.instance_root.rstrip('/') + '.log',
workspace = workdir, workspace=workdir,
software_link=software_link, software_link=software_link,
instance_profile='instance.cfg', instance_profile='instance.cfg',
software_profile='software.cfg', software_profile='software.cfg',
......
...@@ -11,4 +11,3 @@ def as_json(f): ...@@ -11,4 +11,3 @@ def as_json(f):
def inner(*args, **kwargs): def inner(*args, **kwargs):
return Response(json.dumps(f(*args, **kwargs)), mimetype='application/json') return Response(json.dumps(f(*args, **kwargs)), mimetype='application/json')
return inner return inner
...@@ -31,19 +31,19 @@ class FileBrowser(object): ...@@ -31,19 +31,19 @@ class FileBrowser(object):
html = 'var gsdirs = [], gsfiles = [];' html = 'var gsdirs = [], gsfiles = [];'
dir = urllib.unquote(dir) dir = urllib.unquote(dir)
# 'dir' is used below. XXX should not shadow a builtin name # XXX-Marco 'dir' and 'all' should not shadow builtin names
realdir = realpath(self.config, dir) realdir = realpath(self.config, dir)
if not realdir: if not realdir:
raise NameError('Could not load directory %s: Permission denied' % dir) raise NameError('Could not load directory %s: Permission denied' % dir)
ldir = sorted(os.listdir(realdir), key=str.lower) ldir = sorted(os.listdir(realdir), key=str.lower)
for f in ldir: for f in ldir:
if f.startswith('.') and not all: #do not display this file/folder if f.startswith('.') and not all: # do not display this file/folder
continue continue
ff = os.path.join(dir, f) ff = os.path.join(dir, f)
realfile = os.path.join(realdir, f) realfile = os.path.join(realdir, f)
mdate = datetime.datetime.fromtimestamp(os.path.getmtime(realfile) mdate = datetime.datetime.fromtimestamp(os.path.getmtime(realfile)
).strftime("%Y-%d-%m %I:%M") ).strftime("%Y-%d-%m %I:%M")
md5sum = md5.md5(realfile).hexdigest() md5sum = md5.md5(realfile).hexdigest()
if not os.path.isdir(realfile): if not os.path.isdir(realfile):
size = os.path.getsize(realfile) size = os.path.getsize(realfile)
...@@ -61,7 +61,6 @@ class FileBrowser(object): ...@@ -61,7 +61,6 @@ class FileBrowser(object):
ff + '", "0", "' + md5sum + '", "dir", "' + mdate + '"));' ff + '", "0", "' + md5sum + '", "dir", "' + mdate + '"));'
return html return html
def makeDirectory(self, dir, filename): def makeDirectory(self, dir, filename):
"""Create a directory""" """Create a directory"""
realdir = self._realdir(dir) realdir = self._realdir(dir)
...@@ -72,7 +71,6 @@ class FileBrowser(object): ...@@ -72,7 +71,6 @@ class FileBrowser(object):
else: else:
return '{result: \'0\'}' return '{result: \'0\'}'
def makeFile(self, dir, filename): def makeFile(self, dir, filename):
"""Create a file in a directory dir taken""" """Create a file in a directory dir taken"""
realdir = self._realdir(dir) realdir = self._realdir(dir)
...@@ -85,17 +83,19 @@ class FileBrowser(object): ...@@ -85,17 +83,19 @@ class FileBrowser(object):
def deleteItem(self, dir, files): def deleteItem(self, dir, files):
"""Delete a list of files or directories""" """Delete a list of files or directories"""
# XXX-Marco do not shadow 'dir'
realdir = self._realdir(dir) realdir = self._realdir(dir)
lfiles = urllib.unquote(files).split(',,,') lfiles = urllib.unquote(files).split(',,,')
try: try:
# XXX-Marco do not shadow 'file'
for file in lfiles: for file in lfiles:
file = os.path.join(realdir, file) file = os.path.join(realdir, file)
if not os.path.exists(file): if not os.path.exists(file):
continue #silent skip file.... continue # silent skip file....
details = file.split('/') details = file.split('/')
last = details[-1] last = details[-1]
if last and last.startswith('.'): if last and last.startswith('.'):
continue #cannot delete this file/directory, to prevent security continue # cannot delete this file/directory, to prevent security
if os.path.isdir(file): if os.path.isdir(file):
shutil.rmtree(file) shutil.rmtree(file)
else: else:
...@@ -109,6 +109,7 @@ class FileBrowser(object): ...@@ -109,6 +109,7 @@ class FileBrowser(object):
realdir = self._realdir(dir) realdir = self._realdir(dir)
lfiles = urllib.unquote(files).split(',,,') lfiles = urllib.unquote(files).split(',,,')
try: try:
# XXX-Marco do not shadow 'file'
for file in lfiles: for file in lfiles:
realfile = realpath(self.config, file) realfile = realpath(self.config, file)
if not realfile: if not realfile:
......
...@@ -29,7 +29,7 @@ def cloneRepo(data): ...@@ -29,7 +29,7 @@ def cloneRepo(data):
json = "" json = ""
try: try:
if os.path.exists(workDir) and len(os.listdir(workDir)) < 2: if os.path.exists(workDir) and len(os.listdir(workDir)) < 2:
shutil.rmtree(workDir) #delete useless files shutil.rmtree(workDir) # delete useless files
repo = Repo.clone_from(data["repo"], workDir) repo = Repo.clone_from(data["repo"], workDir)
config_writer = repo.config_writer() config_writer = repo.config_writer()
config_writer.add_section("user") config_writer.add_section("user")
...@@ -42,6 +42,7 @@ def cloneRepo(data): ...@@ -42,6 +42,7 @@ def cloneRepo(data):
json = safeResult(str(e)) json = safeResult(str(e))
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def gitStatus(project): def gitStatus(project):
"""Run git status and return status of specified project folder """Run git status and return status of specified project folder
Args: Args:
...@@ -61,6 +62,7 @@ def gitStatus(project): ...@@ -61,6 +62,7 @@ def gitStatus(project):
json = safeResult(str(e)) json = safeResult(str(e))
return jsonify(code=code, result=json, branch=branch, dirty=isdirty) return jsonify(code=code, result=json, branch=branch, dirty=isdirty)
def switchBranch(project, name): def switchBranch(project, name):
"""Switch a git branch """Switch a git branch
Args: Args:
...@@ -76,13 +78,14 @@ def switchBranch(project, name): ...@@ -76,13 +78,14 @@ def switchBranch(project, name):
if name == current_branch: if name == current_branch:
json = "This is already your active branch for this project" json = "This is already your active branch for this project"
else: else:
git = repo.git git = repo.git
git.checkout(name) git.checkout(name)
code = 1 code = 1
except Exception as e: except Exception as e:
json = safeResult(str(e)) json = safeResult(str(e))
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def addBranch(project, name, onlyCheckout=False): def addBranch(project, name, onlyCheckout=False):
"""Add new git branch to the repository """Add new git branch to the repository
Args: Args:
...@@ -95,7 +98,7 @@ def addBranch(project, name, onlyCheckout=False): ...@@ -95,7 +98,7 @@ def addBranch(project, name, onlyCheckout=False):
json = "" json = ""
try: try:
repo = Repo(project) repo = Repo(project)
git = repo.git git = repo.git
if not onlyCheckout: if not onlyCheckout:
git.checkout('-b', name) git.checkout('-b', name)
else: else:
...@@ -105,6 +108,7 @@ def addBranch(project, name, onlyCheckout=False): ...@@ -105,6 +108,7 @@ def addBranch(project, name, onlyCheckout=False):
json = safeResult(str(e)) json = safeResult(str(e))
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def getDiff(project): def getDiff(project):
"""Get git diff for the specified project directory""" """Get git diff for the specified project directory"""
result = "" result = ""
...@@ -117,6 +121,7 @@ def getDiff(project): ...@@ -117,6 +121,7 @@ def getDiff(project):
result = safeResult(str(e)) result = safeResult(str(e))
return result return result
def gitPush(project, msg): def gitPush(project, msg):
"""Commit and Push changes for the specified repository """Commit and Push changes for the specified repository
Args: Args:
...@@ -145,10 +150,11 @@ def gitPush(project, msg): ...@@ -145,10 +150,11 @@ def gitPush(project, msg):
code = 1 code = 1
except Exception as e: except Exception as e:
if undo_commit: if undo_commit:
git.reset("HEAD~") #undo previous commit git.reset("HEAD~") # undo previous commit
json = safeResult(str(e)) json = safeResult(str(e))
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def gitPull(project): def gitPull(project):
result = "" result = ""
code = 0 code = 0
...@@ -161,6 +167,7 @@ def gitPull(project): ...@@ -161,6 +167,7 @@ def gitPull(project):
result = safeResult(str(e)) result = safeResult(str(e))
return jsonify(code=code, result=result) return jsonify(code=code, result=result)
def safeResult(result): def safeResult(result):
"""Parse string and remove credential of the user""" """Parse string and remove credential of the user"""
regex = re.compile("(https:\/\/)([\w\d\._-]+:[\w\d\._-]+)\@([\S]+\s)", re.VERBOSE) regex = re.compile("(https:\/\/)([\w\d\._-]+:[\w\d\._-]+)\@([\S]+\s)", re.VERBOSE)
......
...@@ -18,6 +18,7 @@ from slapos.runner.process import killRunningProcess, isRunning ...@@ -18,6 +18,7 @@ from slapos.runner.process import killRunningProcess, isRunning
from slapos.runner import views from slapos.runner import views
import slapos.slap import slapos.slap
#Helpers #Helpers
def loadJson(response): def loadJson(response):
return json.loads(response.data) return json.loads(response.data)
...@@ -48,6 +49,7 @@ class Config: ...@@ -48,6 +49,7 @@ class Config:
if not getattr(self, key, None): if not getattr(self, key, None):
setattr(self, key, configuration_dict[key]) setattr(self, key, configuration_dict[key])
class SlaprunnerTestCase(unittest.TestCase): class SlaprunnerTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
...@@ -57,8 +59,8 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -57,8 +59,8 @@ class SlaprunnerTestCase(unittest.TestCase):
self.updateUser = ["newslapuser", "newslappwd", "slaprunner@nexedi.com", "SlapOS web runner"] self.updateUser = ["newslapuser", "newslappwd", "slaprunner@nexedi.com", "SlapOS web runner"]
self.rcode = "41bf2657" self.rcode = "41bf2657"
self.repo = 'http://git.erp5.org/repos/slapos.git' self.repo = 'http://git.erp5.org/repos/slapos.git'
self.software = "workspace/slapos/software/" #relative directory fo SR self.software = "workspace/slapos/software/" # relative directory fo SR
self.project = 'slapos' #Default project name self.project = 'slapos' # Default project name
self.template = 'template.cfg' self.template = 'template.cfg'
self.partitionPrefix = 'slappart' self.partitionPrefix = 'slappart'
self.slaposBuildout = "1.6.0-dev-SlapOS-010" self.slaposBuildout = "1.6.0-dev-SlapOS-010"
...@@ -77,7 +79,7 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -77,7 +79,7 @@ class SlaprunnerTestCase(unittest.TestCase):
views.app.config.update( views.app.config.update(
software_log=config.software_root.rstrip('/') + '.log', software_log=config.software_root.rstrip('/') + '.log',
instance_log=config.instance_root.rstrip('/') + '.log', instance_log=config.instance_root.rstrip('/') + '.log',
workspace = workdir, workspace=workdir,
software_link=software_link, software_link=software_link,
instance_profile='instance.cfg', instance_profile='instance.cfg',
software_profile='software.cfg', software_profile='software.cfg',
...@@ -117,20 +119,24 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -117,20 +119,24 @@ class SlaprunnerTestCase(unittest.TestCase):
def configAccount(self, username, password, email, name, rcode): def configAccount(self, username, password, email, name, rcode):
"""Helper for configAccount""" """Helper for configAccount"""
return self.app.post('/configAccount', data=dict( return self.app.post('/configAccount',
username=username, data=dict(
password=password, username=username,
email=email, password=password,
name=name, email=email,
rcode=rcode name=name,
), follow_redirects=True) rcode=rcode
),
follow_redirects=True)
def login(self, username, password): def login(self, username, password):
"""Helper for Login method""" """Helper for Login method"""
return self.app.post('/doLogin', data=dict( return self.app.post('/doLogin',
clogin=username, data=dict(
cpwd=password clogin=username,
), follow_redirects=True) cpwd=password
),
follow_redirects=True)
def setAccount(self): def setAccount(self):
"""Initialize user account and log user in""" """Initialize user account and log user in"""
...@@ -146,13 +152,15 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -146,13 +152,15 @@ class SlaprunnerTestCase(unittest.TestCase):
def updateAccount(self, newaccount, rcode): def updateAccount(self, newaccount, rcode):
"""Helper for update user account data""" """Helper for update user account data"""
return self.app.post('/updateAccount', data=dict( return self.app.post('/updateAccount',
username=newaccount[0], data=dict(
password=newaccount[1], username=newaccount[0],
email=newaccount[2], password=newaccount[1],
name=newaccount[3], email=newaccount[2],
rcode=rcode name=newaccount[3],
), follow_redirects=True) rcode=rcode
),
follow_redirects=True)
def getCurrentSR(self): def getCurrentSR(self):
return getProfilePath(self.app.config['etc_dir'], return getProfilePath(self.app.config['etc_dir'],
...@@ -189,14 +197,15 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -189,14 +197,15 @@ class SlaprunnerTestCase(unittest.TestCase):
"""Helper for setup compiled software release dir""" """Helper for setup compiled software release dir"""
self.setupProjectFolder(withSoftware=True) self.setupProjectFolder(withSoftware=True)
md5 = hashlib.md5(os.path.join(self.app.config['workspace'], md5 = hashlib.md5(os.path.join(self.app.config['workspace'],
"slapos/software/slaprunner-test", self.app.config['software_profile']) "slapos/software/slaprunner-test",
).hexdigest() self.app.config['software_profile'])
).hexdigest()
base = os.path.join(self.app.config['software_root'], md5) base = os.path.join(self.app.config['software_root'], md5)
template = os.path.join(base, self.template) template = os.path.join(base, self.template)
content = "[buildout]\n" content = "[buildout]\n"
content += "parts = \n create-file\n\n" content += "parts = \n create-file\n\n"
content += "eggs-directory = %s\n" % os.path.join(base, 'eggs') content += "eggs-directory = %s\n" % os.path.join(base, 'eggs')
content += "develop-eggs-directory = %s\n\n" % os.path.join(base, 'develop-eggs') content += "develop-eggs-directory = %s\n\n" % os.path.join(base, 'develop-eggs')
content += "[create-file]\nrecipe = plone.recipe.command\n" content += "[create-file]\nrecipe = plone.recipe.command\n"
content += "filename = ${buildout:directory}/etc\n" content += "filename = ${buildout:directory}/etc\n"
content += "command = mkdir ${:filename} && echo 'simple file' > ${:filename}/testfile\n" content += "command = mkdir ${:filename} && echo 'simple file' > ${:filename}/testfile\n"
...@@ -208,7 +217,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -208,7 +217,6 @@ class SlaprunnerTestCase(unittest.TestCase):
"""Kill slapproxy process""" """Kill slapproxy process"""
killRunningProcess('slapproxy', recursive=True) killRunningProcess('slapproxy', recursive=True)
#Begin test case here #Begin test case here
def test_wrong_login(self): def test_wrong_login(self):
"""Test Login user before create session. This should return error value""" """Test Login user before create session. This should return error value"""
...@@ -266,12 +274,16 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -266,12 +274,16 @@ class SlaprunnerTestCase(unittest.TestCase):
"""Start scenario 1 for deploying SR: Clone a project from git repository""" """Start scenario 1 for deploying SR: Clone a project from git repository"""
self.setAccount() self.setAccount()
folder = 'workspace/' + self.project folder = 'workspace/' + self.project
data = {"repo":self.repo, "user":'Slaprunner test', data = {
"email":'slaprunner@nexedi.com', "name":folder} 'repo': self.repo,
'user': 'Slaprunner test',
'email': 'slaprunner@nexedi.com',
'name': folder
}
response = loadJson(self.app.post('/cloneRepository', data=data, response = loadJson(self.app.post('/cloneRepository', data=data,
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
#Get realpath of create project # Get realpath of create project
path_data = dict(file=folder) path_data = dict(file=folder)
response = loadJson(self.app.post('/getPath', data=path_data, response = loadJson(self.app.post('/getPath', data=path_data,
follow_redirects=True)) follow_redirects=True))
...@@ -281,11 +293,13 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -281,11 +293,13 @@ class SlaprunnerTestCase(unittest.TestCase):
config = open(os.path.join(realFolder, '.git/config'), 'r').read() config = open(os.path.join(realFolder, '.git/config'), 'r').read()
assert "slaprunner@nexedi.com" in config and "Slaprunner test" in config assert "slaprunner@nexedi.com" in config and "Slaprunner test" in config
#Checkout to slaprunner branch, this supose that branch slaprunner exit #Checkout to slaprunner branch, this supose that branch slaprunner exit
response = loadJson(self.app.post('/newBranch', data=dict( response = loadJson(self.app.post('/newBranch',
project=folder, data=dict(
create='0', project=folder,
name='slaprunner'), create='0',
follow_redirects=True)) name='slaprunner'
),
follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
self.logout() self.logout()
...@@ -296,8 +310,8 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -296,8 +310,8 @@ class SlaprunnerTestCase(unittest.TestCase):
self.setupProjectFolder() self.setupProjectFolder()
newSoftware = os.path.join(self.software, 'slaprunner-test') newSoftware = os.path.join(self.software, 'slaprunner-test')
response = loadJson(self.app.post('/createSoftware', response = loadJson(self.app.post('/createSoftware',
data=dict(folder=newSoftware), data=dict(folder=newSoftware),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
currentSR = self.getCurrentSR() currentSR = self.getCurrentSR()
assert newSoftware in currentSR assert newSoftware in currentSR
...@@ -308,10 +322,10 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -308,10 +322,10 @@ class SlaprunnerTestCase(unittest.TestCase):
self.test_cloneProject() self.test_cloneProject()
#Login #Login
self.login(self.users[0], self.users[1]) self.login(self.users[0], self.users[1])
software = os.path.join(self.software, 'drupal') #Drupal SR must exist in SR folder software = os.path.join(self.software, 'drupal') # Drupal SR must exist in SR folder
response = loadJson(self.app.post('/setCurrentProject', response = loadJson(self.app.post('/setCurrentProject',
data=dict(path=software), data=dict(path=software),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
currentSR = self.getCurrentSR() currentSR = self.getCurrentSR()
assert software in currentSR assert software in currentSR
...@@ -340,15 +354,15 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -340,15 +354,15 @@ class SlaprunnerTestCase(unittest.TestCase):
softwareRelease += "filename = slapos.git\n" softwareRelease += "filename = slapos.git\n"
softwareRelease += "download-only = true\n" softwareRelease += "download-only = true\n"
response = loadJson(self.app.post('/saveFileContent', response = loadJson(self.app.post('/saveFileContent',
data=dict(file=newSoftware, data=dict(file=newSoftware,
content=softwareRelease), content=softwareRelease),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
#Compile software and wait until slapgrid it end #Compile software and wait until slapgrid it end
#this is supose to use curent SR #this is supose to use curent SR
response = loadJson(self.app.post('/runSoftwareProfile', response = loadJson(self.app.post('/runSoftwareProfile',
data=dict(), data=dict(),
follow_redirects=True)) follow_redirects=True))
self.assertTrue(response['result']) self.assertTrue(response['result'])
self.assertTrue(os.path.exists(self.app.config['software_root'])) self.assertTrue(os.path.exists(self.app.config['software_root']))
self.assertTrue(os.path.exists(self.app.config['software_log'])) self.assertTrue(os.path.exists(self.app.config['software_log']))
...@@ -369,8 +383,8 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -369,8 +383,8 @@ class SlaprunnerTestCase(unittest.TestCase):
#Set current projet and run Slapgrid-cp #Set current projet and run Slapgrid-cp
software = os.path.join(self.software, 'slaprunner-test') software = os.path.join(self.software, 'slaprunner-test')
response = loadJson(self.app.post('/setCurrentProject', response = loadJson(self.app.post('/setCurrentProject',
data=dict(path=software), data=dict(path=software),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
self.proxyStatus(True) self.proxyStatus(True)
#Send paramters for the instance #Send paramters for the instance
...@@ -380,9 +394,9 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -380,9 +394,9 @@ class SlaprunnerTestCase(unittest.TestCase):
parameterXml += '<parameter id="cacountry">France</parameter>\n</instance>' parameterXml += '<parameter id="cacountry">France</parameter>\n</instance>'
software_type = 'production' software_type = 'production'
response = loadJson(self.app.post('/saveParameterXml', response = loadJson(self.app.post('/saveParameterXml',
data=dict(parameter=parameterXml, data=dict(parameter=parameterXml,
software_type=software_type), software_type=software_type),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
slap = slapos.slap.slap() slap = slapos.slap.slap()
slap.initializeConnection(self.app.config['master_url']) slap.initializeConnection(self.app.config['master_url'])
...@@ -391,8 +405,8 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -391,8 +405,8 @@ class SlaprunnerTestCase(unittest.TestCase):
self.assertNotEqual(partitionList, []) self.assertNotEqual(partitionList, [])
#Assume that the requested partition is partition 0 #Assume that the requested partition is partition 0
slapParameterDict = partitionList[0].getInstanceParameterDict() slapParameterDict = partitionList[0].getInstanceParameterDict()
self.assertTrue(slapParameterDict.has_key('appname')) self.assertTrue('appname' in slapParameterDict)
self.assertTrue(slapParameterDict.has_key('cacountry')) self.assertTrue('cacountry' in slapParameterDict)
self.assertEqual(slapParameterDict['appname'], 'slaprunnerTest') self.assertEqual(slapParameterDict['appname'], 'slaprunnerTest')
self.assertEqual(slapParameterDict['cacountry'], 'France') self.assertEqual(slapParameterDict['cacountry'], 'France')
self.assertEqual(slapParameterDict['slap_software_type'], 'production') self.assertEqual(slapParameterDict['slap_software_type'], 'production')
...@@ -413,13 +427,13 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -413,13 +427,13 @@ class SlaprunnerTestCase(unittest.TestCase):
self.proxyStatus(False, sleep_time=1) self.proxyStatus(False, sleep_time=1)
#run Software profile #run Software profile
response = loadJson(self.app.post('/runSoftwareProfile', response = loadJson(self.app.post('/runSoftwareProfile',
data=dict(), data=dict(),
follow_redirects=True)) follow_redirects=True))
self.assertTrue(response['result']) self.assertTrue(response['result'])
#run instance profile #run instance profile
response = loadJson(self.app.post('/runInstanceProfile', response = loadJson(self.app.post('/runInstanceProfile',
data=dict(), data=dict(),
follow_redirects=True)) follow_redirects=True))
self.assertTrue(response['result']) self.assertTrue(response['result'])
#Check that all partitions has been created #Check that all partitions has been created
assert "create-file" in open(self.app.config['instance_log'], 'r').read() assert "create-file" in open(self.app.config['instance_log'], 'r').read()
...@@ -439,6 +453,7 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -439,6 +453,7 @@ class SlaprunnerTestCase(unittest.TestCase):
self.stopSlapproxy() self.stopSlapproxy()
self.logout() self.logout()
def main(): def main():
# Empty parser for now - so that erp5testnode is happy when doing --help # Empty parser for now - so that erp5testnode is happy when doing --help
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
......
...@@ -33,10 +33,12 @@ html_escape_table = { ...@@ -33,10 +33,12 @@ html_escape_table = {
"<": "&lt;", "<": "&lt;",
} }
def html_escape(text): def html_escape(text):
"""Produce entities within text.""" """Produce entities within text."""
return "".join(html_escape_table.get(c, c) for c in text) return "".join(html_escape_table.get(c, c) for c in text)
def getSession(config): def getSession(config):
""" """
Get the session data of current user. Get the session data of current user.
...@@ -53,6 +55,7 @@ def getSession(config): ...@@ -53,6 +55,7 @@ def getSession(config):
return False return False
return user return user
def saveSession(config, account): def saveSession(config, account):
""" """
Save account information for the current user Save account information for the current user
...@@ -74,7 +77,7 @@ def saveSession(config, account): ...@@ -74,7 +77,7 @@ def saveSession(config, account):
f = open(user, 'r') f = open(user, 'r')
#backup previous data #backup previous data
data = f.read() data = f.read()
open(user+'.back', 'w').write(data) open('%s.back' % user, 'w').write(data)
f.close() f.close()
backup = True backup = True
if not account[1]: if not account[1]:
...@@ -94,11 +97,12 @@ def saveSession(config, account): ...@@ -94,11 +97,12 @@ def saveSession(config, account):
try: try:
if backup: if backup:
os.remove(user) os.remove(user)
os.rename(user+'.back', user) os.rename('%s.back' % user, user)
except: except:
pass pass
return str(e) return str(e)
def getCurrentSoftwareReleaseProfile(config): def getCurrentSoftwareReleaseProfile(config):
""" """
Returns used Software Release profile as a string. Returns used Software Release profile as a string.
...@@ -111,6 +115,7 @@ def getCurrentSoftwareReleaseProfile(config): ...@@ -111,6 +115,7 @@ def getCurrentSoftwareReleaseProfile(config):
except: except:
return False return False
def requestInstance(config, software_type=None): def requestInstance(config, software_type=None):
""" """
Request the main instance of our environment Request the main instance of our environment
...@@ -131,7 +136,7 @@ def requestInstance(config, software_type=None): ...@@ -131,7 +136,7 @@ def requestInstance(config, software_type=None):
param_path = os.path.join(config['etc_dir'], ".parameter.xml") param_path = os.path.join(config['etc_dir'], ".parameter.xml")
xml_result = readParameters(param_path) xml_result = readParameters(param_path)
partition_parameter_kw = None partition_parameter_kw = None
if type(xml_result) != type('') and xml_result.has_key('instance'): if type(xml_result) != type('') and 'instance' in xml_result:
partition_parameter_kw = xml_result['instance'] partition_parameter_kw = xml_result['instance']
return slap.registerOpenOrder().request( return slap.registerOpenOrder().request(
...@@ -143,6 +148,7 @@ def requestInstance(config, software_type=None): ...@@ -143,6 +148,7 @@ def requestInstance(config, software_type=None):
state=None, state=None,
shared=False) shared=False)
def updateProxy(config): def updateProxy(config):
""" """
Configure Slapos Node computer and partitions. Configure Slapos Node computer and partitions.
...@@ -158,27 +164,33 @@ def updateProxy(config): ...@@ -158,27 +164,33 @@ def updateProxy(config):
computer = slap.registerComputer(config['computer_id']) computer = slap.registerComputer(config['computer_id'])
prefix = 'slappart' prefix = 'slappart'
slap_config = { slap_config = {
'address': config['ipv4_address'], 'address': config['ipv4_address'],
'instance_root': config['instance_root'], 'instance_root': config['instance_root'],
'netmask': '255.255.255.255', 'netmask': '255.255.255.255',
'partition_list': [], 'partition_list': [],
'reference': config['computer_id'], 'reference': config['computer_id'],
'software_root': config['software_root']} 'software_root': config['software_root']
}
for i in xrange(0, int(config['partition_amount'])): for i in xrange(0, int(config['partition_amount'])):
partition_reference = '%s%s' % (prefix, i) partition_reference = '%s%s' % (prefix, i)
partition_path = os.path.join(config['instance_root'], partition_reference) partition_path = os.path.join(config['instance_root'], partition_reference)
if not os.path.exists(partition_path): if not os.path.exists(partition_path):
os.mkdir(partition_path) os.mkdir(partition_path)
os.chmod(partition_path, 0750) os.chmod(partition_path, 0750)
slap_config['partition_list'].append({'address_list': [{'addr': config['ipv4_address'], slap_config['partition_list'].append({
'netmask': '255.255.255.255'}, 'address_list': [
{'addr': config['ipv6_address'], {
'netmask': 'ffff:ffff:ffff::'}, 'addr': config['ipv4_address'],
], 'netmask': '255.255.255.255'
'path': partition_path, }, {
'reference': partition_reference, 'addr': config['ipv6_address'],
'tap': {'name': partition_reference}, 'netmask': 'ffff:ffff:ffff::'
}) },
],
'path': partition_path,
'reference': partition_reference,
'tap': {'name': partition_reference}})
computer.updateConfiguration(xml_marshaller.xml_marshaller.dumps(slap_config)) computer.updateConfiguration(xml_marshaller.xml_marshaller.dumps(slap_config))
return True return True
...@@ -219,6 +231,7 @@ def removeProxyDb(config): ...@@ -219,6 +231,7 @@ def removeProxyDb(config):
if os.path.exists(config['database_uri']): if os.path.exists(config['database_uri']):
os.unlink(config['database_uri']) os.unlink(config['database_uri'])
def isSoftwareRunning(config=None): def isSoftwareRunning(config=None):
""" """
Return True if slapgrid-sr is still running and false if slapgrid if not Return True if slapgrid-sr is still running and false if slapgrid if not
...@@ -263,13 +276,14 @@ def config_SR_folder(config): ...@@ -263,13 +276,14 @@ def config_SR_folder(config):
"""Create a symbolik link for each folder in software folder. That allow """Create a symbolik link for each folder in software folder. That allow
user to customize software release folder""" user to customize software release folder"""
list = [] list = []
# XXX-Marco do not shadow 'list'
config_name = 'slaprunner.config' config_name = 'slaprunner.config'
for path in os.listdir(config['software_link']): for path in os.listdir(config['software_link']):
cfg_path = os.path.join(config['software_link'], path, config_name) cfg_path = os.path.join(config['software_link'], path, config_name)
if os.path.exists(cfg_path): if os.path.exists(cfg_path):
cfg = open(cfg_path, 'r').read().split("#") cfg = open(cfg_path, 'r').read().split("#")
if len(cfg) != 2: if len(cfg) != 2:
continue #there is a broken config file continue # there is a broken config file
list.append(cfg[1]) list.append(cfg[1])
folder_list = os.listdir(config['software_root']) folder_list = os.listdir(config['software_root'])
if len(folder_list) < 1: if len(folder_list) < 1:
...@@ -280,7 +294,7 @@ def config_SR_folder(config): ...@@ -280,7 +294,7 @@ def config_SR_folder(config):
name = projects[len(projects) - 2] name = projects[len(projects) - 2]
for folder in folder_list: for folder in folder_list:
if folder in list: if folder in list:
continue #this folder is already registered continue # this folder is already registered
else: else:
if not os.path.exists(os.path.join(config['software_link'], name)): if not os.path.exists(os.path.join(config['software_link'], name)):
destination = os.path.join(config['software_link'], name) destination = os.path.join(config['software_link'], name)
...@@ -292,9 +306,10 @@ def config_SR_folder(config): ...@@ -292,9 +306,10 @@ def config_SR_folder(config):
os.symlink(source, destination) os.symlink(source, destination)
#write config file #write config file
cf = open(cfg, 'w') cf = open(cfg, 'w')
cf.write(curent_project+"#"+folder) cf.write(curent_project + "#" + folder)
cf.close() cf.close()
def loadSoftwareRList(config): def loadSoftwareRList(config):
"""Return list (of dict) of Software Release from symbolik SR folder""" """Return list (of dict) of Software Release from symbolik SR folder"""
list = [] list = []
...@@ -304,10 +319,11 @@ def loadSoftwareRList(config): ...@@ -304,10 +319,11 @@ def loadSoftwareRList(config):
if os.path.exists(cfg_path): if os.path.exists(cfg_path):
cfg = open(cfg_path, 'r').read().split("#") cfg = open(cfg_path, 'r').read().split("#")
if len(cfg) != 2: if len(cfg) != 2:
continue #there is a broken config file continue # there is a broken config file
list.append(dict(md5=cfg[1], path=cfg[0], title=path)) list.append(dict(md5=cfg[1], path=cfg[0], title=path))
return list return list
def isInstanceRunning(config=None): def isInstanceRunning(config=None):
""" """
Return True if slapgrid-cp is still running and False otherwise Return True if slapgrid-cp is still running and False otherwise
...@@ -353,6 +369,7 @@ def getProfilePath(projectDir, profile): ...@@ -353,6 +369,7 @@ def getProfilePath(projectDir, profile):
projectFolder = open(os.path.join(projectDir, ".project")).read() projectFolder = open(os.path.join(projectDir, ".project")).read()
return os.path.join(projectFolder, profile) return os.path.join(projectFolder, profile)
def getSlapStatus(config): def getSlapStatus(config):
"""Return all Slapos Partitions with associate information""" """Return all Slapos Partitions with associate information"""
slap = slapos.slap.slap() slap = slapos.slap.slap()
...@@ -372,11 +389,13 @@ def getSlapStatus(config): ...@@ -372,11 +389,13 @@ def getSlapStatus(config):
partition_list.append((slappart_id, [])) partition_list.append((slappart_id, []))
return partition_list return partition_list
def svcStopAll(config): def svcStopAll(config):
"""Stop all Instance process on this computer""" """Stop all Instance process on this computer"""
return Popen([config['supervisor'], config['configuration_file_path'], return Popen([config['supervisor'], config['configuration_file_path'],
'shutdown']).communicate()[0] 'shutdown']).communicate()[0]
def removeInstanceRoot(config): def removeInstanceRoot(config):
"""Clean instance directory and stop all its running process""" """Clean instance directory and stop all its running process"""
if os.path.exists(config['instance_root']): if os.path.exists(config['instance_root']):
...@@ -384,11 +403,12 @@ def removeInstanceRoot(config): ...@@ -384,11 +403,12 @@ def removeInstanceRoot(config):
for root, dirs, _ in os.walk(config['instance_root']): for root, dirs, _ in os.walk(config['instance_root']):
for fname in dirs: for fname in dirs:
fullPath = os.path.join(root, fname) fullPath = os.path.join(root, fname)
if not os.access(fullPath, os.W_OK) : if not os.access(fullPath, os.W_OK):
# Some directories may be read-only, preventing to remove files in it # Some directories may be read-only, preventing to remove files in it
os.chmod(fullPath, 0744) os.chmod(fullPath, 0744)
shutil.rmtree(config['instance_root']) shutil.rmtree(config['instance_root'])
def getSvcStatus(config): def getSvcStatus(config):
"""Return all Softwares Instances process Information""" """Return all Softwares Instances process Information"""
result = Popen([config['supervisor'], config['configuration_file_path'], result = Popen([config['supervisor'], config['configuration_file_path'],
...@@ -397,10 +417,11 @@ def getSvcStatus(config): ...@@ -397,10 +417,11 @@ def getSvcStatus(config):
supervisord = [] supervisord = []
for item in result.split('\n'): for item in result.split('\n'):
if item.strip() != "": if item.strip() != "":
if re.search(regex, item, re.IGNORECASE) == None: if re.search(regex, item, re.IGNORECASE) is None:
supervisord.append(re.split('[\s,]+', item)) supervisord.append(re.split('[\s,]+', item))
return supervisord return supervisord
def getSvcTailProcess(config, process): def getSvcTailProcess(config, process):
"""Get log for the specifie process """Get log for the specifie process
...@@ -413,6 +434,7 @@ def getSvcTailProcess(config, process): ...@@ -413,6 +434,7 @@ def getSvcTailProcess(config, process):
return Popen([config['supervisor'], config['configuration_file_path'], return Popen([config['supervisor'], config['configuration_file_path'],
"tail", process]).communicate()[0] "tail", process]).communicate()[0]
def svcStartStopProcess(config, process, action): def svcStartStopProcess(config, process, action):
"""Send start or stop process command to supervisord """Send start or stop process command to supervisord
...@@ -421,10 +443,17 @@ def svcStartStopProcess(config, process, action): ...@@ -421,10 +443,17 @@ def svcStartStopProcess(config, process, action):
process: process to start or stop. process: process to start or stop.
action: current state which is used to generate the new process state. action: current state which is used to generate the new process state.
""" """
cmd = {"RESTART":"restart", "STOPPED":"start", "RUNNING":"stop", "EXITED":"start", "STOP":"stop"} cmd = {
'RESTART': 'restart',
'STOPPED': 'start',
'RUNNING': 'stop',
'EXITED': 'start',
'STOP': 'stop'
}
return Popen([config['supervisor'], config['configuration_file_path'], return Popen([config['supervisor'], config['configuration_file_path'],
cmd[action], process]).communicate()[0] cmd[action], process]).communicate()[0]
def getFolderContent(config, folder): def getFolderContent(config, folder):
""" """
Read all file and folder into specified directory Read all file and folder into specified directory
...@@ -449,13 +478,13 @@ def getFolderContent(config, folder): ...@@ -449,13 +478,13 @@ def getFolderContent(config, folder):
ldir = [] ldir = []
for f in ldir: for f in ldir:
if f.startswith('.'): #do not displays this file/folder if f.startswith('.'): # do not displays this file/folder
continue continue
ff = os.path.join(d, f) ff = os.path.join(d, f)
if os.path.isdir(os.path.join(realdir, f)): if os.path.isdir(os.path.join(realdir, f)):
r.append('<li class="directory collapsed"><a href="#%s" rel="%s/">%s</a></li>' % (ff, ff, f)) r.append('<li class="directory collapsed"><a href="#%s" rel="%s/">%s</a></li>' % (ff, ff, f))
else: else:
e = os.path.splitext(f)[1][1:] # get .ext and remove dot e = os.path.splitext(f)[1][1:] # get .ext and remove dot
r.append('<li class="file ext_%s"><a href="#%s" rel="%s">%s</a></li>' % (e, ff, ff, f)) r.append('<li class="file ext_%s"><a href="#%s" rel="%s">%s</a></li>' % (e, ff, ff, f))
r.append('</ul>') r.append('</ul>')
except Exception as e: except Exception as e:
...@@ -463,6 +492,7 @@ def getFolderContent(config, folder): ...@@ -463,6 +492,7 @@ def getFolderContent(config, folder):
r.append('</ul>') r.append('</ul>')
return jsonify(result=''.join(r)) return jsonify(result=''.join(r))
def getFolder(config, folder): def getFolder(config, folder):
""" """
Read list of folder for the specified directory Read list of folder for the specified directory
...@@ -486,7 +516,7 @@ def getFolder(config, folder): ...@@ -486,7 +516,7 @@ def getFolder(config, folder):
else: else:
ldir = sorted(os.listdir(realdir), key=str.lower) ldir = sorted(os.listdir(realdir), key=str.lower)
for f in ldir: for f in ldir:
if f.startswith('.'): #do not display this file/folder if f.startswith('.'): # do not display this file/folder
continue continue
ff = os.path.join(d, f) ff = os.path.join(d, f)
if os.path.isdir(os.path.join(realdir, f)): if os.path.isdir(os.path.join(realdir, f)):
...@@ -497,6 +527,7 @@ def getFolder(config, folder): ...@@ -497,6 +527,7 @@ def getFolder(config, folder):
r.append('</ul>') r.append('</ul>')
return jsonify(result=''.join(r)) return jsonify(result=''.join(r))
def getProjectList(folder): def getProjectList(folder):
"""Return the list of projet (folder) into the workspace """Return the list of projet (folder) into the workspace
...@@ -512,6 +543,7 @@ def getProjectList(folder): ...@@ -512,6 +543,7 @@ def getProjectList(folder):
project.append(elt) project.append(elt)
return project return project
def configNewSR(config, projectpath): def configNewSR(config, projectpath):
"""Configure a Software Release as current Software Release """Configure a Software Release as current Software Release
...@@ -539,6 +571,7 @@ def configNewSR(config, projectpath): ...@@ -539,6 +571,7 @@ def configNewSR(config, projectpath):
else: else:
return False return False
def newSoftware(folder, config, session): def newSoftware(folder, config, session):
""" """
Create a new Software Release folder with default profiles Create a new Software Release folder with default profiles
...@@ -582,6 +615,7 @@ def newSoftware(folder, config, session): ...@@ -582,6 +615,7 @@ def newSoftware(folder, config, session):
shutil.rmtree(folderPath) shutil.rmtree(folderPath)
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def checkSoftwareFolder(path, config): def checkSoftwareFolder(path, config):
"""Check id `path` is a valid Software Release folder""" """Check id `path` is a valid Software Release folder"""
realdir = realpath(config, path) realdir = realpath(config, path)
...@@ -589,6 +623,7 @@ def checkSoftwareFolder(path, config): ...@@ -589,6 +623,7 @@ def checkSoftwareFolder(path, config):
return jsonify(result=path) return jsonify(result=path)
return jsonify(result="") return jsonify(result="")
def getProjectTitle(config): def getProjectTitle(config):
"""Generate the name of the current software Release (for slaprunner UI)""" """Generate the name of the current software Release (for slaprunner UI)"""
conf = os.path.join(config['etc_dir'], ".project") conf = os.path.join(config['etc_dir'], ".project")
...@@ -598,6 +633,7 @@ def getProjectTitle(config): ...@@ -598,6 +633,7 @@ def getProjectTitle(config):
return '%s (%s)' % (software, '/'.join(project[:-2])) return '%s (%s)' % (software, '/'.join(project[:-2]))
return "No Profile" return "No Profile"
def getSoftwareReleaseName(config): def getSoftwareReleaseName(config):
"""Get the name of the current Software Release""" """Get the name of the current Software Release"""
sr_profile = os.path.join(config['etc_dir'], ".project") sr_profile = os.path.join(config['etc_dir'], ".project")
...@@ -607,6 +643,7 @@ def getSoftwareReleaseName(config): ...@@ -607,6 +643,7 @@ def getSoftwareReleaseName(config):
return software.replace(' ', '_') return software.replace(' ', '_')
return "No_name" return "No_name"
def removeSoftwareByName(config, md5, folderName): def removeSoftwareByName(config, md5, folderName):
"""Remove all content of the software release specified by md5 """Remove all content of the software release specified by md5
...@@ -622,12 +659,13 @@ def removeSoftwareByName(config, md5, folderName): ...@@ -622,12 +659,13 @@ def removeSoftwareByName(config, md5, folderName):
raise Exception("Cannot remove software Release: No such file or directory") raise Exception("Cannot remove software Release: No such file or directory")
if not os.path.exists(linkpath): if not os.path.exists(linkpath):
raise Exception("Cannot remove software Release: No such file or directory %s" % raise Exception("Cannot remove software Release: No such file or directory %s" %
('software_root/'+folderName)) ('software_root/' + folderName))
svcStopAll(config) svcStopAll(config)
os.unlink(linkpath) os.unlink(linkpath)
shutil.rmtree(path) shutil.rmtree(path)
return loadSoftwareRList(config) return loadSoftwareRList(config)
def tail(f, lines=20): def tail(f, lines=20):
""" """
Returns the last `lines` lines of file `f`. It is an implementation of tail -f n. Returns the last `lines` lines of file `f`. It is an implementation of tail -f n.
...@@ -655,6 +693,7 @@ def tail(f, lines=20): ...@@ -655,6 +693,7 @@ def tail(f, lines=20):
block -= 1 block -= 1
return '\n'.join(''.join(data).splitlines()[-lines:]) return '\n'.join(''.join(data).splitlines()[-lines:])
def readFileFrom(f, lastPosition, limit=20000): def readFileFrom(f, lastPosition, limit=20000):
""" """
Returns the last lines of file `f`, from position lastPosition. Returns the last lines of file `f`, from position lastPosition.
...@@ -663,22 +702,23 @@ def readFileFrom(f, lastPosition, limit=20000): ...@@ -663,22 +702,23 @@ def readFileFrom(f, lastPosition, limit=20000):
""" """
BUFSIZ = 1024 BUFSIZ = 1024
f.seek(0, 2) f.seek(0, 2)
# XXX-Marco do now shadow 'bytes'
bytes = f.tell() bytes = f.tell()
block = -1 block = -1
data = "" data = ""
length = bytes length = bytes
truncated = False #True if a part of log data has been truncated truncated = False # True if a part of log data has been truncated
if (lastPosition <= 0 and length > limit) or (length-lastPosition > limit): if (lastPosition <= 0 and length > limit) or (length - lastPosition > limit):
lastPosition = length - limit lastPosition = length - limit
truncated = True truncated = True
size = bytes - lastPosition size = bytes - lastPosition
while bytes > lastPosition: while bytes > lastPosition:
if abs(block*BUFSIZ) <= size: if abs(block * BUFSIZ) <= size:
# Seek back one whole BUFSIZ # Seek back one whole BUFSIZ
f.seek(block * BUFSIZ, 2) f.seek(block * BUFSIZ, 2)
data = f.read(BUFSIZ) + data data = f.read(BUFSIZ) + data
else: else:
margin = abs(block*BUFSIZ) - size margin = abs(block * BUFSIZ) - size
if length < BUFSIZ: if length < BUFSIZ:
f.seek(0, 0) f.seek(0, 0)
else: else:
...@@ -688,7 +728,12 @@ def readFileFrom(f, lastPosition, limit=20000): ...@@ -688,7 +728,12 @@ def readFileFrom(f, lastPosition, limit=20000):
bytes -= BUFSIZ bytes -= BUFSIZ
block -= 1 block -= 1
f.close() f.close()
return {"content":data, "position":length, "truncated":truncated} return {
'content': data,
'position': length,
'truncated': truncated
}
def isText(file): def isText(file):
"""Return True if the mimetype of file is Text""" """Return True if the mimetype of file is Text"""
...@@ -701,6 +746,7 @@ def isText(file): ...@@ -701,6 +746,7 @@ def isText(file):
except: except:
return False return False
def md5sum(file): def md5sum(file):
"""Compute md5sum of `file` and return hexdigest value""" """Compute md5sum of `file` and return hexdigest value"""
if os.path.isdir(file): if os.path.isdir(file):
...@@ -717,6 +763,7 @@ def md5sum(file): ...@@ -717,6 +763,7 @@ def md5sum(file):
except: except:
return False return False
def realpath(config, path, check_exist=True): def realpath(config, path, check_exist=True):
""" """
Get realpath of path or return False if user is not allowed to access to Get realpath of path or return False if user is not allowed to access to
...@@ -724,20 +771,25 @@ def realpath(config, path, check_exist=True): ...@@ -724,20 +771,25 @@ def realpath(config, path, check_exist=True):
""" """
split_path = path.split('/') split_path = path.split('/')
key = split_path[0] key = split_path[0]
allow_list = {'software_root':config['software_root'], 'instance_root': allow_list = {
config['instance_root'], 'workspace': config['workspace'], 'software_root': config['software_root'],
'software_link':config['software_link']} 'instance_root': config['instance_root'],
if allow_list.has_key(key): 'workspace': config['workspace'],
del split_path[0] 'software_link': config['software_link']
path = os.path.join(allow_list[key], *split_path) }
if check_exist: if key not in allow_list:
if os.path.exists(path): return False
return path
else: del split_path[0]
return False path = os.path.join(allow_list[key], *split_path)
else: if check_exist:
if os.path.exists(path):
return path return path
return False else:
return False
else:
return path
def readParameters(path): def readParameters(path):
"""Read Instance parameters stored into a local file. """Read Instance parameters stored into a local file.
...@@ -755,7 +807,7 @@ def readParameters(path): ...@@ -755,7 +807,7 @@ def readParameters(path):
sub_obj = {} sub_obj = {}
for subnode in elt.childNodes: for subnode in elt.childNodes:
if subnode.nodeType != subnode.TEXT_NODE: if subnode.nodeType != subnode.TEXT_NODE:
sub_obj[str(subnode.getAttribute('id'))] = subnode.childNodes[0].data #.decode('utf-8').decode('utf-8') sub_obj[str(subnode.getAttribute('id'))] = subnode.childNodes[0].data # .decode('utf-8').decode('utf-8')
obj[str(elt.tagName)] = sub_obj obj[str(elt.tagName)] = sub_obj
return obj return obj
except Exception, e: except Exception, e:
......
...@@ -41,9 +41,11 @@ file_request = FileBrowser(app.config) ...@@ -41,9 +41,11 @@ file_request = FileBrowser(app.config)
import logging import logging
logger = logging.getLogger('werkzeug') logger = logging.getLogger('werkzeug')
def login_redirect(*args, **kwargs): def login_redirect(*args, **kwargs):
return redirect(url_for('login')) return redirect(url_for('login'))
#Access Control: Only static files and login pages are allowed to guest #Access Control: Only static files and login pages are allowed to guest
@app.before_request @app.before_request
def before_request(): def before_request():
...@@ -67,15 +69,18 @@ def before_request(): ...@@ -67,15 +69,18 @@ def before_request():
def home(): def home():
return render_template('index.html') return render_template('index.html')
# general views # general views
@login_required() @login_required()
def browseWorkspace(): def browseWorkspace():
return render_template('workspace.html') return render_template('workspace.html')
@app.route("/login") @app.route("/login")
def login(): def login():
return render_template('login.html') return render_template('login.html')
@app.route("/setAccount") @app.route("/setAccount")
def setAccount(): def setAccount():
account = getSession(app.config) account = getSession(app.config)
...@@ -83,17 +88,20 @@ def setAccount(): ...@@ -83,17 +88,20 @@ def setAccount():
return render_template('account.html') return render_template('account.html')
return redirect(url_for('login')) return redirect(url_for('login'))
@login_required() @login_required()
def myAccount(): def myAccount():
account = getSession(app.config) account = getSession(app.config)
return render_template('account.html', username=account[0], return render_template('account.html', username=account[0],
email=account[2], name=account[3].decode('utf-8')) email=account[2], name=account[3].decode('utf-8'))
@app.route("/dologout") @app.route("/dologout")
def dologout(): def dologout():
_ = logout() _ = logout()
return redirect(url_for('login')) return redirect(url_for('login'))
@login_required() @login_required()
def configRepo(): def configRepo():
public_key = open(app.config['public_key'], 'r').read() public_key = open(app.config['public_key'], 'r').read()
...@@ -102,6 +110,7 @@ def configRepo(): ...@@ -102,6 +110,7 @@ def configRepo():
public_key=public_key, name=account[3].decode('utf-8'), public_key=public_key, name=account[3].decode('utf-8'),
email=account[2]) email=account[2])
@app.route("/doLogin", methods=['POST']) @app.route("/doLogin", methods=['POST'])
def doLogin(): def doLogin():
username = request.form['clogin'] username = request.form['clogin']
...@@ -111,6 +120,7 @@ def doLogin(): ...@@ -111,6 +120,7 @@ def doLogin():
return jsonify(code=1, result="") return jsonify(code=1, result="")
return jsonify(code=0, result="Login or password is incorrect, please check it!") return jsonify(code=0, result="Login or password is incorrect, please check it!")
# software views # software views
@login_required() @login_required()
def editSoftwareProfile(): def editSoftwareProfile():
...@@ -120,11 +130,13 @@ def editSoftwareProfile(): ...@@ -120,11 +130,13 @@ def editSoftwareProfile():
return render_template('updateSoftwareProfile.html', workDir='workspace', return render_template('updateSoftwareProfile.html', workDir='workspace',
profile=profile, projectList=getProjectList(app.config['workspace'])) profile=profile, projectList=getProjectList(app.config['workspace']))
@login_required() @login_required()
def inspectSoftware(): def inspectSoftware():
return render_template('runResult.html', softwareRoot='software_link/', return render_template('runResult.html', softwareRoot='software_link/',
softwares=loadSoftwareRList(app.config)) softwares=loadSoftwareRList(app.config))
#remove content of compiled software release #remove content of compiled software release
@login_required() @login_required()
def removeSoftware(): def removeSoftware():
...@@ -138,12 +150,14 @@ def removeSoftware(): ...@@ -138,12 +150,14 @@ def removeSoftware():
flash('Software removed') flash('Software removed')
return redirect(url_for('inspectSoftware')) return redirect(url_for('inspectSoftware'))
@login_required() @login_required()
def runSoftwareProfile(): def runSoftwareProfile():
if runSoftwareWithLock(app.config): if runSoftwareWithLock(app.config):
return jsonify(result = True) return jsonify(result=True)
else: else:
return jsonify(result = False) return jsonify(result=False)
@login_required() @login_required()
def viewSoftwareLog(): def viewSoftwareLog():
...@@ -154,6 +168,7 @@ def viewSoftwareLog(): ...@@ -154,6 +168,7 @@ def viewSoftwareLog():
return render_template('viewLog.html', type='software', return render_template('viewLog.html', type='software',
result=result.encode("utf-8")) result=result.encode("utf-8"))
# instance views # instance views
@login_required() @login_required()
def editInstanceProfile(): def editInstanceProfile():
...@@ -163,6 +178,7 @@ def editInstanceProfile(): ...@@ -163,6 +178,7 @@ def editInstanceProfile():
return render_template('updateInstanceProfile.html', workDir='workspace', return render_template('updateInstanceProfile.html', workDir='workspace',
profile=profile, projectList=getProjectList(app.config['workspace'])) profile=profile, projectList=getProjectList(app.config['workspace']))
# get status of all computer partitions and process state # get status of all computer partitions and process state
@login_required() @login_required()
def inspectInstance(): def inspectInstance():
...@@ -178,6 +194,7 @@ def inspectInstance(): ...@@ -178,6 +194,7 @@ def inspectInstance():
slap_status=getSlapStatus(app.config), slap_status=getSlapStatus(app.config),
supervisore=result, partition_amount=app.config['partition_amount']) supervisore=result, partition_amount=app.config['partition_amount'])
#Reload instance process ans returns new value to ajax #Reload instance process ans returns new value to ajax
@login_required() @login_required()
def supervisordStatus(): def supervisordStatus():
...@@ -200,13 +217,14 @@ def supervisordStatus(): ...@@ -200,13 +217,14 @@ def supervisordStatus():
html += "</tr>" html += "</tr>"
return jsonify(code=1, result=html) return jsonify(code=1, result=html)
@login_required() @login_required()
def removeInstance(): def removeInstance():
if isInstanceRunning(app.config): if isInstanceRunning(app.config):
flash('Instantiation in progress, cannot remove') flash('Instantiation in progress, cannot remove')
else: else:
removeProxyDb(app.config) removeProxyDb(app.config)
svcStopAll(app.config) #Stop All instance process svcStopAll(app.config) # Stop All instance process
removeInstanceRoot(app.config) removeInstanceRoot(app.config)
param_path = os.path.join(app.config['etc_dir'], ".parameter.xml") param_path = os.path.join(app.config['etc_dir'], ".parameter.xml")
if os.path.exists(param_path): if os.path.exists(param_path):
...@@ -214,14 +232,16 @@ def removeInstance(): ...@@ -214,14 +232,16 @@ def removeInstance():
flash('Instance removed') flash('Instance removed')
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@login_required() @login_required()
def runInstanceProfile(): def runInstanceProfile():
if not os.path.exists(app.config['instance_root']): if not os.path.exists(app.config['instance_root']):
os.mkdir(app.config['instance_root']) os.mkdir(app.config['instance_root'])
if runInstanceWithLock(app.config): if runInstanceWithLock(app.config):
return jsonify(result = True) return jsonify(result=True)
else: else:
return jsonify(result = False) return jsonify(result=False)
@login_required() @login_required()
def viewInstanceLog(): def viewInstanceLog():
...@@ -232,49 +252,63 @@ def viewInstanceLog(): ...@@ -232,49 +252,63 @@ def viewInstanceLog():
return render_template('viewLog.html', type='instance', return render_template('viewLog.html', type='instance',
result=result.encode("utf-8")) result=result.encode("utf-8"))
@login_required() @login_required()
def stopAllPartition(): def stopAllPartition():
svcStopAll(app.config) svcStopAll(app.config)
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@login_required(login_redirect) @login_required(login_redirect)
def tailProcess(process): def tailProcess(process):
return render_template('processTail.html', return render_template('processTail.html',
process_log=getSvcTailProcess(app.config, process), process=process) process_log=getSvcTailProcess(app.config, process), process=process)
@login_required(login_redirect) @login_required(login_redirect)
def startStopProccess(process, action): def startStopProccess(process, action):
svcStartStopProcess(app.config, process, action) svcStartStopProcess(app.config, process, action)
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@login_required(login_redirect) @login_required(login_redirect)
def openProject(method): def openProject(method):
return render_template('projectFolder.html', method=method, return render_template('projectFolder.html', method=method,
workDir='workspace') workDir='workspace')
@login_required() @login_required()
def cloneRepository(): def cloneRepository():
path = realpath(app.config, request.form['name'], False) path = realpath(app.config, request.form['name'], False)
data = {"repo":request.form['repo'], "user":request.form['user'], data = {
"email":request.form['email'], "path":path} 'repo': request.form['repo'],
'user': request.form['user'],
'email': request.form['email'],
'path': path
}
return cloneRepo(data) return cloneRepo(data)
@login_required() @login_required()
def readFolder(): def readFolder():
return getFolderContent(app.config, request.form['dir']) return getFolderContent(app.config, request.form['dir'])
@login_required() @login_required()
def openFolder(): def openFolder():
return getFolder(app.config, request.form['dir']) return getFolder(app.config, request.form['dir'])
@login_required() @login_required()
def createSoftware(): def createSoftware():
return newSoftware(request.form['folder'], app.config, session) return newSoftware(request.form['folder'], app.config, session)
@login_required() @login_required()
def checkFolder(): def checkFolder():
return checkSoftwareFolder(request.form['path'], app.config) return checkSoftwareFolder(request.form['path'], app.config)
@login_required() @login_required()
def setCurrentProject(): def setCurrentProject():
if configNewSR(app.config, request.form['path']): if configNewSR(app.config, request.form['path']):
...@@ -283,11 +317,13 @@ def setCurrentProject(): ...@@ -283,11 +317,13 @@ def setCurrentProject():
else: else:
return jsonify(code=0, result=("Can not setup this Software Release")) return jsonify(code=0, result=("Can not setup this Software Release"))
@login_required() @login_required()
def manageProject(): def manageProject():
return render_template('manageProject.html', workDir='workspace', return render_template('manageProject.html', workDir='workspace',
project=getProjectList(app.config['workspace'])) project=getProjectList(app.config['workspace']))
@login_required() @login_required()
def getProjectStatus(): def getProjectStatus():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
...@@ -296,6 +332,7 @@ def getProjectStatus(): ...@@ -296,6 +332,7 @@ def getProjectStatus():
else: else:
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
#view for current software release files #view for current software release files
@login_required() @login_required()
def editCurrentProject(): def editCurrentProject():
...@@ -306,12 +343,13 @@ def editCurrentProject(): ...@@ -306,12 +343,13 @@ def editCurrentProject():
projectList=getProjectList(app.config['workspace'])) projectList=getProjectList(app.config['workspace']))
return redirect(url_for('configRepo')) return redirect(url_for('configRepo'))
#create file or directory #create file or directory
@login_required() @login_required()
def createFile(): def createFile():
path = realpath(app.config, request.form['file'], False) path = realpath(app.config, request.form['file'], False)
if not path: if not path:
return jsonify(code=0, result="Error when creating your " + \ return jsonify(code=0, result="Error when creating your " +
request.form['type'] + ": Permission Denied") request.form['type'] + ": Permission Denied")
try: try:
if request.form['type'] == "file": if request.form['type'] == "file":
...@@ -322,6 +360,7 @@ def createFile(): ...@@ -322,6 +360,7 @@ def createFile():
except Exception as e: except Exception as e:
return jsonify(code=0, result=str(e)) return jsonify(code=0, result=str(e))
#remove file or directory #remove file or directory
@login_required() @login_required()
def removeFile(): def removeFile():
...@@ -334,6 +373,7 @@ def removeFile(): ...@@ -334,6 +373,7 @@ def removeFile():
except Exception as e: except Exception as e:
return jsonify(code=0, result=str(e)) return jsonify(code=0, result=str(e))
@login_required() @login_required()
def removeSoftwareDir(): def removeSoftwareDir():
try: try:
...@@ -343,6 +383,7 @@ def removeSoftwareDir(): ...@@ -343,6 +383,7 @@ def removeSoftwareDir():
except Exception as e: except Exception as e:
return jsonify(code=0, result=str(e)) return jsonify(code=0, result=str(e))
#read file and return content to ajax #read file and return content to ajax
@login_required() @login_required()
def getFileContent(): def getFileContent():
...@@ -351,14 +392,15 @@ def getFileContent(): ...@@ -351,14 +392,15 @@ def getFileContent():
if not isText(file_path): if not isText(file_path):
return jsonify(code=0, return jsonify(code=0,
result="Can not open a binary file, please select a text file!") result="Can not open a binary file, please select a text file!")
if not request.form.has_key('truncate'): if 'truncate' in request.form:
return jsonify(code=1, result=open(file_path, 'r').read())
else:
content = tail(open(file_path, 'r'), int(request.form['truncate'])) content = tail(open(file_path, 'r'), int(request.form['truncate']))
return jsonify(code=1, result=content) return jsonify(code=1, result=content)
else:
return jsonify(code=1, result=open(file_path, 'r').read())
else: else:
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@login_required() @login_required()
def saveFileContent(): def saveFileContent():
file_path = realpath(app.config, request.form['file']) file_path = realpath(app.config, request.form['file'])
...@@ -368,6 +410,7 @@ def saveFileContent(): ...@@ -368,6 +410,7 @@ def saveFileContent():
else: else:
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@login_required() @login_required()
def changeBranch(): def changeBranch():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
...@@ -376,6 +419,7 @@ def changeBranch(): ...@@ -376,6 +419,7 @@ def changeBranch():
else: else:
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required() @login_required()
def newBranch(): def newBranch():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
...@@ -387,12 +431,14 @@ def newBranch(): ...@@ -387,12 +431,14 @@ def newBranch():
else: else:
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required(login_redirect) @login_required(login_redirect)
def getProjectDiff(project): def getProjectDiff(project):
path = os.path.join(app.config['workspace'], project) path = os.path.join(app.config['workspace'], project)
return render_template('projectDiff.html', project=project, return render_template('projectDiff.html', project=project,
diff=getDiff(path)) diff=getDiff(path))
@login_required() @login_required()
def pushProjectFiles(): def pushProjectFiles():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
...@@ -401,6 +447,7 @@ def pushProjectFiles(): ...@@ -401,6 +447,7 @@ def pushProjectFiles():
else: else:
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required() @login_required()
def pullProjectFiles(): def pullProjectFiles():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
...@@ -409,6 +456,7 @@ def pullProjectFiles(): ...@@ -409,6 +456,7 @@ def pullProjectFiles():
else: else:
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required() @login_required()
def checkFileType(): def checkFileType():
path = realpath(app.config, request.form['path']) path = realpath(app.config, request.form['path'])
...@@ -420,6 +468,7 @@ def checkFileType(): ...@@ -420,6 +468,7 @@ def checkFileType():
return jsonify(code=0, return jsonify(code=0,
result="Can not open a binary file, please select a text file!") result="Can not open a binary file, please select a text file!")
@login_required() @login_required()
def getmd5sum(): def getmd5sum():
realfile = realpath(app.config, request.form['file']) realfile = realpath(app.config, request.form['file'])
...@@ -431,26 +480,33 @@ def getmd5sum(): ...@@ -431,26 +480,33 @@ def getmd5sum():
else: else:
return jsonify(code=0, result="Can not get md5sum for this file!") return jsonify(code=0, result="Can not get md5sum for this file!")
#return information about state of slapgrid process #return information about state of slapgrid process
@login_required() @login_required()
def slapgridResult(): def slapgridResult():
software_state = isSoftwareRunning(app.config) software_state = isSoftwareRunning(app.config)
instance_state = isInstanceRunning(app.config) instance_state = isInstanceRunning(app.config)
log_result = {"content":"", "position":0, "truncated":False} log_result = {
if request.form['log'] == "software" or\ 'content': '',
'position': 0,
'truncated': False
}
if request.form['log'] == "software" or \
request.form['log'] == "instance": request.form['log'] == "instance":
log_file = request.form['log'] + "_log" log_file = request.form['log'] + "_log"
if os.path.exists(app.config[log_file]): if os.path.exists(app.config[log_file]):
log_result = readFileFrom(open(app.config[log_file], 'r'), log_result = readFileFrom(open(app.config[log_file], 'r'),
int(request.form['position'])) int(request.form['position']))
return jsonify(software=software_state, instance=instance_state, return jsonify(software=software_state, instance=instance_state,
result=(instance_state or software_state), content=log_result) result=(instance_state or software_state), content=log_result)
@login_required() @login_required()
def stopSlapgrid(): def stopSlapgrid():
result = killRunningProcess(request.form['type']) result = killRunningProcess(request.form['type'])
return jsonify(result=result) return jsonify(result=result)
@login_required() @login_required()
def getPath(): def getPath():
files = request.form['file'].split('#') files = request.form['file'].split('#')
...@@ -469,6 +525,7 @@ def getPath(): ...@@ -469,6 +525,7 @@ def getPath():
else: else:
return jsonify(code=1, result=realfile) return jsonify(code=1, result=realfile)
@login_required() @login_required()
def saveParameterXml(): def saveParameterXml():
""" """
...@@ -500,6 +557,7 @@ def saveParameterXml(): ...@@ -500,6 +557,7 @@ def saveParameterXml():
result="An error occurred while applying your settings!<br/>" + str(e)) result="An error occurred while applying your settings!<br/>" + str(e))
return jsonify(code=1, result="") return jsonify(code=1, result="")
@login_required() @login_required()
def getSoftwareType(): def getSoftwareType():
software_type_path = os.path.join(app.config['etc_dir'], ".software_type.xml") software_type_path = os.path.join(app.config['etc_dir'], ".software_type.xml")
...@@ -507,6 +565,7 @@ def getSoftwareType(): ...@@ -507,6 +565,7 @@ def getSoftwareType():
return jsonify(code=1, result=open(software_type_path, 'r').read()) return jsonify(code=1, result=open(software_type_path, 'r').read())
return jsonify(code=1, result="default") return jsonify(code=1, result="default")
#read instance parameters into the local xml file and return a dict #read instance parameters into the local xml file and return a dict
@login_required() @login_required()
def getParameterXml(request): def getParameterXml(request):
...@@ -636,6 +695,7 @@ def fileBrowser(): ...@@ -636,6 +695,7 @@ def fileBrowser():
return str(e) return str(e)
return result return result
@login_required() @login_required()
def editFile(): def editFile():
return render_template('editFile.html', workDir='workspace', return render_template('editFile.html', workDir='workspace',
...@@ -643,6 +703,7 @@ def editFile(): ...@@ -643,6 +703,7 @@ def editFile():
projectList=getProjectList(app.config['workspace']), projectList=getProjectList(app.config['workspace']),
filename=urllib.unquote(request.args.get('filename', ''))) filename=urllib.unquote(request.args.get('filename', '')))
#Setup List of URLs #Setup List of URLs
app.add_url_rule('/', 'home', home) app.add_url_rule('/', 'home', home)
app.add_url_rule('/browseWorkspace', 'browseWorkspace', browseWorkspace) app.add_url_rule('/browseWorkspace', 'browseWorkspace', browseWorkspace)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment