Commit 314206ec authored by Nicolas Wavrant's avatar Nicolas Wavrant

Merge branch 'slaprunner-paas'

parents 4eb93526 22c18547
from datetime import datetime import argparse
import csv import csv
import feedparser import feedparser
import httplib # To avoid magic numbers
import io import io
import socket
import json import json
import time
import math import math
import httplib # To avoid magic numbers
import argparse
import os import os
import socket
import sys
import time
from datetime import datetime
from hashlib import sha512 from hashlib import sha512
from atomize import Entry from atomize import Entry
...@@ -19,6 +20,9 @@ from flask import abort ...@@ -19,6 +20,9 @@ from flask import abort
from flask import request from flask import request
app = Flask(__name__) app = Flask(__name__)
# csv entries can be very large, increase limit.
csv.field_size_limit(sys.maxsize)
@app.route('/get/<feed>') @app.route('/get/<feed>')
def get_feed(feed): def get_feed(feed):
global app global app
......
...@@ -47,3 +47,17 @@ For reference: How-to deploy the whole test system ...@@ -47,3 +47,17 @@ For reference: How-to deploy the whole test system
Note: the slapos nodes are currently deployed using slapos-in-partition. Note: the slapos nodes are currently deployed using slapos-in-partition.
Note: you have to manually kill -10 the erp5testnode process to start deployment of test because it doesn't know when SR installation is finished. Note: you have to manually kill -10 the erp5testnode process to start deployment of test because it doesn't know when SR installation is finished.
Note: you have to manually run slapos-node-software --all on the slapos nodes if you are developping the SR you are testing. Note: you have to manually run slapos-node-software --all on the slapos nodes if you are developping the SR you are testing.
------------
STANDALONE TESTS
Here is an example on how to deploy standalone tests on the webrunner, which means without using erp5.
1/ Deploy a SlapRunner software instance using the type test.
2/ In slapos.org, you should tell on which server you want to deploy your instances. You can adapt to your case the parameter.xml above. For the first time, you can deploy all the instances on the same node, it will run the tests faster, and it will be easier to debug :
<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="_">{"cluster": {"-sla-0-computer_guid": "COMP-XXXX", "-sla-1-computer_guid": "COMP-XXXX", "-sla-2-computer_guid": "COMP-XXXX"}}</parameter>
</instance>
3/ Then go to the root instance folder : it is the one who has only "runStandaloneResiliencyTestSuite" in its bin folder.
4/ Run ./bin/runStandaloneResiliencyTestSuite and wait :) it would return "success" or "failure"
...@@ -32,6 +32,7 @@ import slapos.slap ...@@ -32,6 +32,7 @@ import slapos.slap
import logging import logging
import time import time
import os
class ResiliencyTestSuite(object): class ResiliencyTestSuite(object):
""" """
...@@ -104,6 +105,14 @@ class ResiliencyTestSuite(object): ...@@ -104,6 +105,14 @@ class ResiliencyTestSuite(object):
""" """
raise NotImplementedError('Overload me, I am an abstract method.') raise NotImplementedError('Overload me, I am an abstract method.')
def deleteTimestamp():
"""
XXX-Nicolas delete .timestamp in test partition to force the full processing
by slapgrid, to force the good parameters to be passed to the instances of the tree
"""
home = os.getenv('HOME')
timestamp = os.path.join(home, '.timestamp')
os.remove(timestamp)
def _getPartitionParameterDict(self): def _getPartitionParameterDict(self):
""" """
...@@ -115,6 +124,7 @@ class ResiliencyTestSuite(object): ...@@ -115,6 +124,7 @@ class ResiliencyTestSuite(object):
software_type='resilient', software_type='resilient',
partition_reference=self.root_instance_name partition_reference=self.root_instance_name
).getConnectionParameterDict() ).getConnectionParameterDict()
self.deleteTimestamp()
def _returnNewInstanceParameter(self, parameter_key, old_parameter_value): def _returnNewInstanceParameter(self, parameter_key, old_parameter_value):
""" """
...@@ -126,8 +136,8 @@ class ResiliencyTestSuite(object): ...@@ -126,8 +136,8 @@ class ResiliencyTestSuite(object):
new_parameter_value = None new_parameter_value = None
while not new_parameter_value or new_parameter_value == 'None' or new_parameter_value == old_parameter_value: while not new_parameter_value or new_parameter_value == 'None' or new_parameter_value == old_parameter_value:
self.logger.info('Not ready yet. SlapOS says new parameter value is %s' % new_parameter_value) self.logger.info('Not ready yet. SlapOS says new parameter value is %s' % new_parameter_value)
time.sleep(60)
new_parameter_value = self._getPartitionParameterDict().get(parameter_key, None) new_parameter_value = self._getPartitionParameterDict().get(parameter_key, None)
time.sleep(120)
self.logger.info('New parameter value of instance is %s' % new_parameter_value) self.logger.info('New parameter value of instance is %s' % new_parameter_value)
return new_parameter_value return new_parameter_value
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
from .resiliencytestsuite import ResiliencyTestSuite from .resiliencytestsuite import ResiliencyTestSuite
import base64
import cookielib import cookielib
import random import random
import string import string
...@@ -63,6 +64,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite): ...@@ -63,6 +64,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
300 300
) )
def _connectToSlaprunner(self, resource, data=None): def _connectToSlaprunner(self, resource, data=None):
""" """
Utility. Utility.
...@@ -81,10 +83,8 @@ class SlaprunnerTestSuite(ResiliencyTestSuite): ...@@ -81,10 +83,8 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
def _login(self): def _login(self):
self.logger.debug('Logging in...') self.logger.debug('Logging in...')
self._connectToSlaprunner('doLogin', data='clogin=%s&cpwd=%s' % ( b64string = base64.encodestring('%s:%s' % (self.slaprunner_user, self.slaprunner_password))[:-1]
self.slaprunner_user, self._opener_director.addheaders = [('Authorization', 'Basic %s'%b64string)]
self.slaprunner_password)
)
def _retrieveInstanceLogFile(self): def _retrieveInstanceLogFile(self):
""" """
...@@ -112,10 +112,17 @@ class SlaprunnerTestSuite(ResiliencyTestSuite): ...@@ -112,10 +112,17 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
return data return data
def _waitForSoftwareBuild(self): def _waitForSoftwareBuild(self):
while self._connectToSlaprunner(resource='slapgridResult', data='position=0&log=').find('"software": true') is not -1: #while self._connectToSlaprunner(resource='slapgridResult', data='position=0&log=').find('"software": true') is not -1:
# self.logger.info('Software release is still building. Sleeping...')
# time.sleep(15)
#self.logger.info('Software Release has been built / is no longer building.')
try:
while self._connectToSlaprunner(resource='isSRReady') != "1":
self.logger.info('Software release is still building. Sleeping...') self.logger.info('Software release is still building. Sleeping...')
time.sleep(15) time.sleep(15)
self.logger.info('Software Release has been built / is no longer building.') except (NotHttpOkException, urllib2.HTTPError):
# The nginx frontend might timeout before software release is finished.
self._waitForSoftwareBuild()
def _buildSoftwareRelease(self): def _buildSoftwareRelease(self):
self.logger.info('Building the Software Release...') self.logger.info('Building the Software Release...')
...@@ -199,6 +206,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite): ...@@ -199,6 +206,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
self._openSoftwareRelease('helloworld') self._openSoftwareRelease('helloworld')
self._buildSoftwareRelease() self._buildSoftwareRelease()
time.sleep(15)
self._deployInstance() self._deployInstance()
self.data = self._retrieveInstanceLogFile() self.data = self._retrieveInstanceLogFile()
...@@ -219,9 +227,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite): ...@@ -219,9 +227,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
) )
self._login() self._login()
self._waitForSoftwareBuild() self._waitForSoftwareBuild()
# XXX: in theory, it should be done automatically by slaprunner. time.sleep(15)
# In practice, it is still too dangerous for ERP5 instances.
self._deployInstance()
new_data = self._retrieveInstanceLogFile() new_data = self._retrieveInstanceLogFile()
if new_data == self.data: if new_data == self.data:
......
...@@ -6,51 +6,12 @@ import ConfigParser ...@@ -6,51 +6,12 @@ import ConfigParser
import datetime import datetime
import logging import logging
import logging.handlers import logging.handlers
from optparse import OptionParser, Option
import os import os
import slapos.runner.process from slapos.htpasswd import HtpasswdFile
from slapos.runner.process import setHandler
import sys import sys
from slapos.runner.utils import runInstanceWithLock from slapos.runner.utils import runInstanceWithLock
from slapos.runner.views import *
class Parser(OptionParser):
"""
Parse all arguments.
"""
def __init__(self, usage=None, version=None):
"""
Initialize all possible options.
"""
option_list = [
Option("-l", "--log_file",
help="The path to the log file used by the script.",
type=str),
Option("-v", "--verbose",
default=False,
action="store_true",
help="Verbose output."),
Option("-c", "--console",
default=False,
action="store_true",
help="Console output."),
Option("-d", "--debug",
default=False,
action="store_true",
help="Debug mode."),
]
OptionParser.__init__(self, usage=usage, version=version,
option_list=option_list)
def check_args(self):
"""
Check arguments
"""
(options, args) = self.parse_args()
if len(args) != 1:
self.error("Incorrect number of arguments")
return options, args[0]
class Config: class Config:
...@@ -61,19 +22,15 @@ class Config: ...@@ -61,19 +22,15 @@ class Config:
self.logger = None self.logger = None
self.verbose = None self.verbose = None
def setConfig(self, option_dict, configuration_file_path): def setConfig(self):
""" """
Set options given by parameters. Set options given by parameters.
""" """
self.configuration_file_path = os.path.abspath(configuration_file_path) self.configuration_file_path = os.path.abspath(os.getenv('RUNNER_CONFIG'))
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
# Load configuration file # Load configuration file
configuration_parser = ConfigParser.SafeConfigParser() configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path) configuration_parser.read(self.configuration_file_path)
# Merges the arguments and configuration
for section in ("slaprunner", "slapos", "slapproxy", "slapformat", for section in ("slaprunner", "slapos", "slapproxy", "slapformat",
"sshkeys_authority", "gitclient", "cloud9_IDE"): "sshkeys_authority", "gitclient", "cloud9_IDE"):
...@@ -88,7 +45,7 @@ class Config: ...@@ -88,7 +45,7 @@ class Config:
if self.console: if self.console:
self.logger.addHandler(logging.StreamHandler()) self.logger.addHandler(logging.StreamHandler())
if self.log_file: self.log_file = self.log_dir + '/slaprunner.log'
if not os.path.isdir(os.path.dirname(self.log_file)): if not os.path.isdir(os.path.dirname(self.log_file)):
# fallback to console only if directory for logs does not exists and # fallback to console only if directory for logs does not exists and
# continue to run # continue to run
...@@ -107,30 +64,33 @@ class Config: ...@@ -107,30 +64,33 @@ class Config:
self.logger.debug("Verbose mode enabled.") self.logger.debug("Verbose mode enabled.")
def checkHtpasswd(config):
"""XXX:set for backward compatiblity
create a htpassword if etc/.users exist"""
user = os.path.join(config['etc_dir'], '.users')
htpasswdfile = os.path.join(config['etc_dir'], '.htpasswd')
if os.path.exists(user) and not os.path.exists(htpasswdfile):
data = open(user).read().strip().split(';')
htpasswd = HtpasswdFile(htpasswdfile, create=True)
htpasswd.update(data[0], data[1])
htpasswd.save()
else:
return
def run(): def run():
"Run default configuration." "Run default configuration."
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments # Parse arguments
config = Config() config = Config()
config.setConfig(*Parser(usage=usage).check_args()) config.setConfig()
if os.getuid() == 0: if os.getuid() == 0:
# avoid mistakes (mainly in development mode) # avoid mistakes (mainly in development mode)
raise Exception('Do not run SlapRunner as root.') raise Exception('Do not run SlapRunner as root.')
serve(config) serve(config)
return_code = 0
except SystemExit as err:
# Catch exception raise by optparse
return_code = err
sys.exit(return_code)
def serve(config): def serve(config):
from views import app
from werkzeug.contrib.fixers import ProxyFix from werkzeug.contrib.fixers import ProxyFix
workdir = os.path.join(config.runner_workdir, 'project') workdir = os.path.join(config.runner_workdir, 'project')
software_link = os.path.join(config.runner_workdir, 'softwareLink') software_link = os.path.join(config.runner_workdir, 'softwareLink')
...@@ -145,14 +105,15 @@ def serve(config): ...@@ -145,14 +105,15 @@ def serve(config):
SECRET_KEY=os.urandom(24), SECRET_KEY=os.urandom(24),
PERMANENT_SESSION_LIFETIME=datetime.timedelta(days=31), PERMANENT_SESSION_LIFETIME=datetime.timedelta(days=31),
) )
checkHtpasswd(app.config)
if not os.path.exists(workdir): if not os.path.exists(workdir):
os.mkdir(workdir) os.mkdir(workdir)
if not os.path.exists(software_link): if not os.path.exists(software_link):
os.mkdir(software_link) os.mkdir(software_link)
slapos.runner.process.setHandler() setHandler()
config.logger.info('Running slapgrid...') config.logger.info('Running slapgrid...')
runInstanceWithLock(app.config) runInstanceWithLock(app.config)
config.logger.info('Done.') config.logger.info('Done.')
app.wsgi_app = ProxyFix(app.wsgi_app) app.wsgi_app = ProxyFix(app.wsgi_app)
app.run(host=config.runner_host, port=int(config.runner_port),
debug=config.debug, threaded=True) run()
...@@ -121,36 +121,40 @@ def getDiff(project): ...@@ -121,36 +121,40 @@ def getDiff(project):
result = safeResult(str(e)) result = safeResult(str(e))
return result return result
def gitCommit(project, msg):
def gitPush(project, msg): """Commit changes for the specified repository
"""Commit and Push changes for the specified repository
Args: Args:
project: directory of the local repository project: directory of the local repository
msg: commit message""" msg: commit message"""
code = 0 code = 0
json = "" json = ""
undo_commit = False
try:
repo = Repo(project) repo = Repo(project)
if repo.is_dirty: if repo.is_dirty:
git = repo.git git = repo.git
current_branch = repo.active_branch.name
#add file to be commited #add file to be commited
files = repo.untracked_files files = repo.untracked_files
for f in files: for f in files:
git.add(f) git.add(f)
#Commit all modified and untracked files #Commit all modified and untracked files
git.commit('-a', '-m', msg) git.commit('-a', '-m', msg)
undo_commit = True else:
code = 1
json = "Nothing to be commited"
return jsonify(code=code, result=json)
def gitPush(project):
"""Push changes for the specified repository
Args:
project: directory of the local repository
msg: commit message"""
code = 0
json = ""
try:
#push changes to repo #push changes to repo
current_branch = repo.active_branch.name
git.push('origin', current_branch) git.push('origin', current_branch)
code = 1 code = 1
else:
json = "Nothing to commit"
code = 1
except Exception as e: except Exception as e:
if undo_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)
......
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
# vim: set et sts=2: # vim: set et sts=2:
# pylint: disable-msg=W0311,C0301,C0103,C0111,R0904 # pylint: disable-msg=W0311,C0301,C0103,C0111,R0904
#############################################
# !!! Attention !!!
# You now have to comment the last line
# in __init__py, wich starts the functiun
# run() in order to start the tests,
# or it will NOT work
#############################################
import argparse import argparse
import ConfigParser import ConfigParser
import datetime import datetime
...@@ -13,10 +21,12 @@ import time ...@@ -13,10 +21,12 @@ import time
import unittest import unittest
from slapos.runner.utils import (getProfilePath, getSession, isInstanceRunning, from slapos.runner.utils import (getProfilePath, getSession, isInstanceRunning,
isSoftwareRunning, startProxy) isSoftwareRunning, startProxy,
isSoftwareReleaseReady)
from slapos.runner.process import killRunningProcess, isRunning from slapos.runner.process import killRunningProcess, isRunning
from slapos.runner import views from slapos.runner import views
import slapos.slap import slapos.slap
from slapos.htpasswd import HtpasswdFile
#Helpers #Helpers
...@@ -63,7 +73,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -63,7 +73,6 @@ class SlaprunnerTestCase(unittest.TestCase):
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"
#create slaprunner configuration #create slaprunner configuration
config = Config() config = Config()
config.setConfig() config.setConfig()
...@@ -110,7 +119,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -110,7 +119,6 @@ class SlaprunnerTestCase(unittest.TestCase):
shutil.rmtree(self.app.config['instance_root']) shutil.rmtree(self.app.config['instance_root'])
if os.path.exists(self.app.config['software_link']): if os.path.exists(self.app.config['software_link']):
shutil.rmtree(self.app.config['software_link']) shutil.rmtree(self.app.config['software_link'])
self.logout()
#Stop process #Stop process
killRunningProcess('slapproxy', recursive=True) killRunningProcess('slapproxy', recursive=True)
killRunningProcess('slapgrid-cp', recursive=True) killRunningProcess('slapgrid-cp', recursive=True)
...@@ -128,26 +136,11 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -128,26 +136,11 @@ class SlaprunnerTestCase(unittest.TestCase):
), ),
follow_redirects=True) follow_redirects=True)
def login(self, username, password):
"""Helper for Login method"""
return self.app.post('/doLogin',
data=dict(
clogin=username,
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"""
response = loadJson(self.configAccount(self.users[0], self.users[1], response = loadJson(self.configAccount(self.users[0], self.users[1],
self.users[2], self.users[3], self.rcode)) self.users[2], self.users[3], self.rcode))
response2 = loadJson(self.login(self.users[0], self.users[1]))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
self.assertEqual(response2['result'], "")
def logout(self):
"""Helper for Logout current user"""
return self.app.get('/dologout', follow_redirects=True)
def updateAccount(self, newaccount, rcode): def updateAccount(self, newaccount, rcode):
"""Helper for update user account data""" """Helper for update user account data"""
...@@ -186,8 +179,7 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -186,8 +179,7 @@ class SlaprunnerTestCase(unittest.TestCase):
sr += "find-links += http://www.nexedi.org/static/packages/source/slapos.buildout/\n\n" sr += "find-links += http://www.nexedi.org/static/packages/source/slapos.buildout/\n\n"
sr += "[networkcache]\ndownload-cache-url = http://www.shacache.org/shacache" sr += "[networkcache]\ndownload-cache-url = http://www.shacache.org/shacache"
sr += "\ndownload-dir-url = http://www.shacache.org/shadir\n\n" sr += "\ndownload-dir-url = http://www.shacache.org/shadir\n\n"
sr += "[command]\nrecipe = zc.recipe.egg\neggs = plone.recipe.command\n\n" sr += "[command]\nrecipe = zc.recipe.egg\neggs = plone.recipe.command\n zc.buildout\n\n"
sr += "[versions]\nzc.buildout = %s\n" % self.slaposBuildout
os.mkdir(testSoftware) os.mkdir(testSoftware)
open(os.path.join(testSoftware, self.app.config['software_profile']), open(os.path.join(testSoftware, self.app.config['software_profile']),
'w').write(sr) 'w').write(sr)
...@@ -216,13 +208,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -216,13 +208,6 @@ class SlaprunnerTestCase(unittest.TestCase):
"""Kill slapproxy process""" """Kill slapproxy process"""
killRunningProcess('slapproxy', recursive=True) killRunningProcess('slapproxy', recursive=True)
#Begin test case here
def test_wrong_login(self):
"""Test Login user before create session. This should return an error value"""
response = self.login(self.users[0], self.users[1])
#redirect to config account page
assert "<h2 class='title'>Your personal information</h2><br/>" in response.data
def test_configAccount(self): def test_configAccount(self):
"""For the first lauch of slaprunner user need do create first account""" """For the first lauch of slaprunner user need do create first account"""
result = self.configAccount(self.users[0], self.users[1], self.users[2], result = self.configAccount(self.users[0], self.users[1], self.users[2],
...@@ -232,34 +217,16 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -232,34 +217,16 @@ class SlaprunnerTestCase(unittest.TestCase):
account = getSession(self.app.config) account = getSession(self.app.config)
self.assertEqual(account, self.users) self.assertEqual(account, self.users)
def test_login_logout(self):
"""test login with good and wrong values, test logout"""
response = loadJson(self.configAccount(self.users[0], self.users[1],
self.users[2], self.users[3], self.rcode))
self.assertEqual(response['result'], "")
result = loadJson(self.login(self.users[0], "wrongpwd"))
self.assertEqual(result['result'], "Login or password is incorrect, please check it!")
resultwr = loadJson(self.login("wronglogin", "wrongpwd"))
self.assertEqual(resultwr['result'], "Login or password is incorrect, please check it!")
#try now with true values
resultlg = loadJson(self.login(self.users[0], self.users[1]))
self.assertEqual(resultlg['result'], "")
#after login test logout
result = self.logout()
assert "<h2>Login to Slapos Web Runner</h2>" in result.data
def test_updateAccount(self): def test_updateAccount(self):
"""test Update accound, this needs the user to log in""" """test Update accound, this needs the user to log in"""
self.setAccount() self.setAccount()
htpasswd = os.path.join(self.app.config['etc_dir'], '.htpasswd')
assert self.users[0] in open(htpasswd).read()
response = loadJson(self.updateAccount(self.updateUser, self.rcode)) response = loadJson(self.updateAccount(self.updateUser, self.rcode))
self.assertEqual(response['code'], 1) self.assertEqual(response['code'], 1)
result = self.logout() encode = HtpasswdFile(htpasswd, False)
assert "<h2>Login to Slapos Web Runner</h2>" in result.data encode.update(self.updateUser[0], self.updateUser[1])
#retry login with new values assert self.updateUser[0] in open(htpasswd).read()
response = loadJson(self.login(self.updateUser[0], self.updateUser[1]))
self.assertEqual(response['result'], "")
#log out now!
self.logout()
def test_startProxy(self): def test_startProxy(self):
"""Test slapproxy""" """Test slapproxy"""
...@@ -301,7 +268,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -301,7 +268,6 @@ class SlaprunnerTestCase(unittest.TestCase):
), ),
follow_redirects=True)) follow_redirects=True))
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
self.logout()
def test_createSR(self): def test_createSR(self):
"""Scenario 2: Create a new software release""" """Scenario 2: Create a new software release"""
...@@ -315,13 +281,10 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -315,13 +281,10 @@ class SlaprunnerTestCase(unittest.TestCase):
self.assertEqual(response['result'], "") self.assertEqual(response['result'], "")
currentSR = self.getCurrentSR() currentSR = self.getCurrentSR()
assert newSoftware in currentSR assert newSoftware in currentSR
self.logout()
def test_openSR(self): def test_openSR(self):
"""Scenario 3: Open software release""" """Scenario 3: Open software release"""
self.test_cloneProject() self.test_cloneProject()
#Login
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),
...@@ -336,7 +299,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -336,7 +299,6 @@ class SlaprunnerTestCase(unittest.TestCase):
# newSoftware = os.path.join(self.software, 'slaprunner-test') # newSoftware = os.path.join(self.software, 'slaprunner-test')
self.proxyStatus(True) self.proxyStatus(True)
self.stopSlapproxy() self.stopSlapproxy()
self.logout()
def test_runSoftware(self): def test_runSoftware(self):
"""Scenario 4: CReate empty SR and save software.cfg file """Scenario 4: CReate empty SR and save software.cfg file
...@@ -345,8 +307,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -345,8 +307,6 @@ class SlaprunnerTestCase(unittest.TestCase):
#Call config account #Call config account
#call create software Release #call create software Release
self.test_createSR() self.test_createSR()
#Login
self.login(self.users[0], self.users[1])
newSoftware = self.getCurrentSR() newSoftware = self.getCurrentSR()
softwareRelease = "[buildout]\n\nparts =\n test-application\n" softwareRelease = "[buildout]\n\nparts =\n test-application\n"
softwareRelease += "#Test download git web repos éè@: utf-8 caracters\n" softwareRelease += "#Test download git web repos éè@: utf-8 caracters\n"
...@@ -376,7 +336,6 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -376,7 +336,6 @@ class SlaprunnerTestCase(unittest.TestCase):
self.assertTrue(os.path.exists(createdFile)) self.assertTrue(os.path.exists(createdFile))
self.proxyStatus(True) self.proxyStatus(True)
self.stopSlapproxy() self.stopSlapproxy()
self.logout()
def test_updateInstanceParameter(self): def test_updateInstanceParameter(self):
"""Scenarion 5: Update parameters of current sofware profile""" """Scenarion 5: Update parameters of current sofware profile"""
...@@ -419,13 +378,10 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -419,13 +378,10 @@ class SlaprunnerTestCase(unittest.TestCase):
response = loadJson(self.app.get('/getParameterXml/dict')) response = loadJson(self.app.get('/getParameterXml/dict'))
self.assertEqual(parameterDict, response['result']['instance']) self.assertEqual(parameterDict, response['result']['instance'])
self.stopSlapproxy() self.stopSlapproxy()
self.logout()
def test_requestInstance(self): def test_requestInstance(self):
"""Scenarion 6: request software instance""" """Scenarion 6: request software instance"""
self.test_updateInstanceParameter() self.test_updateInstanceParameter()
#Login
self.login(self.users[0], self.users[1])
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',
...@@ -453,8 +409,34 @@ class SlaprunnerTestCase(unittest.TestCase): ...@@ -453,8 +409,34 @@ class SlaprunnerTestCase(unittest.TestCase):
assert 'simple file' in open(createdFile).read() assert 'simple file' in open(createdFile).read()
self.proxyStatus(True) self.proxyStatus(True)
self.stopSlapproxy() self.stopSlapproxy()
self.logout()
def test_safeAutoDeploy(self):
"""Scenario 7: isSRReady won't overwrite the existing
Sofware Instance if it has been deployed yet"""
# Test that SR won't be deployed with auto_deploy=False
self.app.config['auto_deploy'] = False
project = open(os.path.join(self.app.config['etc_dir'],
'.project'), "w")
project.write(self.software + 'slaprunner-test')
project.close()
response = isSoftwareReleaseReady(self.app.config)
self.assertEqual(response, "0")
# Test if auto_deploy parameter starts the deployment of SR
self.app.config['auto_deploy'] = True
self.setupSoftwareFolder()
response = isSoftwareReleaseReady(self.app.config)
self.assertEqual(response, "2")
# Test that the new call to isSoftwareReleaseReady
# doesn't overwrite the previous installed one
completed_path = os.path.join(self.app.config['runner_workdir'],
'softwareLink', 'slaprunner-test', '.completed')
completed_text = ".completed file: test"
completed = open(completed_path, "w")
completed.write(completed_text)
completed.close()
response = isSoftwareReleaseReady(self.app.config)
self.assertEqual(response, "1")
assert completed_text in open(completed_path).read()
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
......
...@@ -297,6 +297,10 @@ input[type="radio"], input[type="checkbox"]{ ...@@ -297,6 +297,10 @@ input[type="radio"], input[type="checkbox"]{
margin-bottom:10px; margin-bottom:10px;
} }
#commitmsg {
width:95%;
}
.message { .message {
color:#FF5500; color:#FF5500;
line-height:21px; line-height:21px;
...@@ -449,7 +453,7 @@ padding: 10px;height: 80px;padding-bottom:15px;} ...@@ -449,7 +453,7 @@ padding: 10px;height: 80px;padding-bottom:15px;}
} }
#code{ #code{
float: right; float: right;
width: 692px; width: 680px;
} }
#details_head{margin-bottom: 10px;} #details_head{margin-bottom: 10px;}
...@@ -728,3 +732,5 @@ padding:10px; font-size:14px; color:#03406A} ...@@ -728,3 +732,5 @@ padding:10px; font-size:14px; color:#03406A}
.login-input{width:220px;} .login-input{width:220px;}
.information{display:block; float:left; height:16px; margin-top:10px; margin-left:10px; font-weight:bold} .information{display:block; float:left; height:16px; margin-top:10px; margin-left:10px; font-weight:bold}
.account{margin-left:60px;} .account{margin-left:60px;}
/* ********************/
#shellinabox{width:100%; min-height:530px;}
...@@ -43,6 +43,8 @@ $(document).ready(function () { ...@@ -43,6 +43,8 @@ $(document).ready(function () {
return false; return false;
} }
send = true; send = true;
var base_url = 'https://' + $("input#username").val() + ':'
+ $("input#password").val() + '@' + location.host
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + ((hasAccount) ? '/updateAccount' : '/configAccount'), url: $SCRIPT_ROOT + ((hasAccount) ? '/updateAccount' : '/configAccount'),
...@@ -55,7 +57,7 @@ $(document).ready(function () { ...@@ -55,7 +57,7 @@ $(document).ready(function () {
}, },
success: function (data) { success: function (data) {
if (data.code === 1) { if (data.code === 1) {
window.location.href = $SCRIPT_ROOT + "/"; window.location.href = base_url + $SCRIPT_ROOT + '/';
} else { } else {
$("#error").Popup(data.result, {type: 'error', duration: 5000}); $("#error").Popup(data.result, {type: 'error', duration: 5000});
} }
......
...@@ -90,3 +90,4 @@ function bindRemove() { ...@@ -90,3 +90,4 @@ function bindRemove() {
} }
}); });
}(jQuery, document, this)); }(jQuery, document, this));
...@@ -27,7 +27,9 @@ $(document).ready(function () { ...@@ -27,7 +27,9 @@ $(document).ready(function () {
$("#login").removeClass("button").addClass("dsblebutton"); $("#login").removeClass("button").addClass("dsblebutton");
$.post(url, param, function (data) { $.post(url, param, function (data) {
if (data.code === 1) { if (data.code === 1) {
window.location.href = $SCRIPT_ROOT + '/'; url = 'https://' + param.clogin + ':' + param.cpwd + '@'
+ location.host + $SCRIPT_ROOT + '/';
window.location.href = url;
} else { } else {
$("#error").Popup(data.result, {type: 'alert', duration: 3000}); $("#error").Popup(data.result, {type: 'alert', duration: 3000});
} }
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
/*global $, document, $SCRIPT_ROOT */ /*global $, document, $SCRIPT_ROOT */
/* vim: set et sts=4: */ /* vim: set et sts=4: */
$.valHooks.textarea = {
get: function (elem) {
"use strict";
return elem.value.replace(/\r?\n/g, "\r\n");
}
};
$(document).ready(function () { $(document).ready(function () {
"use strict"; "use strict";
...@@ -23,7 +30,7 @@ $(document).ready(function () { ...@@ -23,7 +30,7 @@ $(document).ready(function () {
urldata = $("input#workdir").val() + "/" + project; urldata = $("input#workdir").val() + "/" + project;
$("#status").empty(); $("#status").empty();
$("#push").hide(); $("#commit").hide();
$("#flash").empty(); $("#flash").empty();
if (project === "") { if (project === "") {
$("#status").append("<h2>Please select one project...</h2><br/><br/>"); $("#status").append("<h2>Please select one project...</h2><br/><br/>");
...@@ -45,7 +52,7 @@ $(document).ready(function () { ...@@ -45,7 +52,7 @@ $(document).ready(function () {
//alert(message); //alert(message);
$("#status").append("<p>" + message + "</p>"); $("#status").append("<p>" + message + "</p>");
if (data.dirty) { if (data.dirty) {
$("#push").show(); $("#commit").show();
$("#status").append("<br/><h2>Display Diff for current Project</h2>"); $("#status").append("<br/><h2>Display Diff for current Project</h2>");
$("#status").append("<p style='font-size:15px;'>You have changes in your project." + $("#status").append("<p style='font-size:15px;'>You have changes in your project." +
" <a href='" + $SCRIPT_ROOT + "/getProjectDiff/" " <a href='" + $SCRIPT_ROOT + "/getProjectDiff/"
...@@ -119,9 +126,9 @@ $(document).ready(function () { ...@@ -119,9 +126,9 @@ $(document).ready(function () {
checkout("0"); checkout("0");
return false; return false;
}); });
$("#commit").click(function () { $("#commitbutton").click(function () {
if ($("input#commitmsg").val() === "" || if ($("input#commitmsg").val() === "" ||
$("input#commitmsg").val() === "Enter message...") { $("textarea#commitmsg").val() === "Enter message...") {
$("#error").Popup("Please Enter the commit message", {type: 'alert', duration: 3000}); $("#error").Popup("Please Enter the commit message", {type: 'alert', duration: 3000});
return false; return false;
} }
...@@ -131,12 +138,12 @@ $(document).ready(function () { ...@@ -131,12 +138,12 @@ $(document).ready(function () {
send = true; send = true;
var project = $("#project").val(); var project = $("#project").val();
$("#imgwaitting").fadeIn('normal'); $("#imgwaitting").fadeIn('normal');
$("#commit").empty(); //$("#commit").empty();
$("#commit").attr("value", "Wait..."); $("#commitbbutton").attr("value", "Wait...");
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/pushProjectFiles', url: $SCRIPT_ROOT + '/commitProjectFiles',
data: {project: $("input#workdir").val() + "/" + project, msg: $("input#commitmsg").val()}, data: {project: $("input#workdir").val() + "/" + project, msg: $("textarea#commitmsg").val()},
success: function (data) { success: function (data) {
if (data.code === 1) { if (data.code === 1) {
if (data.result !== "") { if (data.result !== "") {
...@@ -144,19 +151,46 @@ $(document).ready(function () { ...@@ -144,19 +151,46 @@ $(document).ready(function () {
} else { } else {
$("#error").Popup("Commit done!", {type: 'confirm', duration: 3000}); $("#error").Popup("Commit done!", {type: 'confirm', duration: 3000});
} }
$("#commit").hide();
gitStatus(); gitStatus();
} else { } else {
$("#error").Popup(data.result, {type: 'error'}); $("#error").Popup(data.result, {type: 'error'});
} }
$("#imgwaitting").hide(); $("#imgwaitting").hide();
$("#commit").empty(); $("#commitmsg").empty();
$("#commit").attr("value", "Commit"); $("#commitbutton").attr("value", "Commit");
send = false;
}
});
return false;
});
$("#push").click(function () {
if (send) {
return false;
}
send = true;
var project = $("#project").val();
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/pushProjectFiles',
data: {project: $("input#workdir").val() + "/" + project},
success: function (data) {
if (data.code === 1) {
if (data.result !== "") {
$("#error").Popup(data.result, {type: 'error', duration: 5000});
} else {
$("#error").Popup("The local commits have correctly been saved on the server", {type: 'confirm', duration: 3000});
}
gitStatus();
} else {
$("#error").Popup(data.result, {type: 'error'});
}
$("#push").hide();
send = false; send = false;
} }
}); });
return false; return false;
}); });
/* /*
$("#pullbranch").click(function (){ $("#pullbranch").click(function (){
if (send){ if (send){
......
...@@ -56,8 +56,11 @@ ...@@ -56,8 +56,11 @@
<div class="line"></div> <div class="line"></div>
<a href="{{ url_for('editCurrentProject') }}" style="float:left" title="Edit your current project"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a> <a href="{{ url_for('editCurrentProject') }}" style="float:left" title="Edit your current project"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a>
<div class="line"></div> <div class="line"></div>
<a href="{{ url_for('dologout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a> <a href="{{ url_for('manageProject') }}" style="float:left" title="Manage Your repositories"><img alt="" src="{{ url_for('static', filename='images/manage_repo-little.png') }}" /></a>
<div class="line"></div>
<a href="{{ url_for('shell') }}" style="float:left" title="Use the shell"><img alt="" src="{{ url_for('static', filename='images/terminal.png') }}" /></a>
<div class="line"></div> <div class="line"></div>
<a href="{{ url_for('dologout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a>
<h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2> <h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2>
<div class="run"><span id="running" style="display:none"><img alt="" src="{{ url_for('static', filename='images/ajax_roller.gif') }}" <div class="run"><span id="running" style="display:none"><img alt="" src="{{ url_for('static', filename='images/ajax_roller.gif') }}"
height='26' title="slapgrid is currently running"/></span></div> height='26' title="slapgrid is currently running"/></span></div>
......
...@@ -40,15 +40,22 @@ ...@@ -40,15 +40,22 @@
<!--<img class="waitting" id="pullimgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />--> <!--<img class="waitting" id="pullimgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />-->
</div> </div>
</div> </div>
<div id="push" style="margin-bottom:20px;"> <div id="commit" style="margin-bottom:20px;">
<h2>Commit All your changes (On active branch)</h2> <h2>Commit All your changes (On active branch)</h2>
<div style="margin-left:15px;"> <div style="margin-left:15px;">
<label for='commitmsg'>Commit message: </label> <label for='commitmsg'>Commit message: </label>
<input type="text" name="commitmsg" id="commitmsg" size='40' value="Enter message..." /> <textarea name="commitmsg" id="commitmsg" cols="40" rows="3">
<input type="submit" name="commit" id ="commit" value="Commit" class="button"/> </textarea>
<input type="submit" name="commit" id ="commitbutton" value="Commit" class="button"/>
<img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" /> <img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />
</div> </div>
</div> </div>
<div id="push" style="margin-bottom:20px;">
<h2>Push your Last Commits</h2>
<div style="margin-left:15px;">
<input type="submit" name="push" id="push" value="Push" class="button"/>
</div>
</div>
<br/> <br/>
</div> </div>
</div> </div>
......
{% extends "layout.html" %}
{% block body %}
<iframe id="shellinabox" src="/shellinabox"></iframe>
{% endblock %}
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
import logging import logging
import md5 import md5
import multiprocessing import multiprocessing
import os
import re import re
import shutil import shutil
import os import thread
import time import time
import urllib import urllib
from xml.dom import minidom from xml.dom import minidom
...@@ -15,6 +16,8 @@ from xml.dom import minidom ...@@ -15,6 +16,8 @@ from xml.dom import minidom
import xml_marshaller import xml_marshaller
from flask import jsonify from flask import jsonify
from slapos.runner.gittools import cloneRepo
from slapos.runner.process import Popen, isRunning, killRunningProcess from slapos.runner.process import Popen, isRunning, killRunningProcess
from slapos.htpasswd import HtpasswdFile from slapos.htpasswd import HtpasswdFile
import slapos.slap import slapos.slap
...@@ -23,6 +26,7 @@ import slapos.slap ...@@ -23,6 +26,7 @@ import slapos.slap
logger = logging.getLogger('werkzeug') logger = logging.getLogger('werkzeug')
TRUE_VALUES = (1, '1', True, 'true', 'True')
html_escape_table = { html_escape_table = {
"&": "&amp;", "&": "&amp;",
...@@ -276,12 +280,16 @@ def config_SR_folder(config): ...@@ -276,12 +280,16 @@ def config_SR_folder(config):
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])
if os.path.exists(config['software_root']):
folder_list = os.listdir(config['software_root']) folder_list = os.listdir(config['software_root'])
else:
return
if not folder_list: if not folder_list:
return return
current_project = open(os.path.join(config['etc_dir'], ".project")).read() current_project = open(os.path.join(config['etc_dir'], ".project")).read()
projects = current_project.split('/') if current_project[-1] == '/':
name = projects[-2] current_project = current_project[:-1]
name = current_project.split('/')[-1]
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
...@@ -803,3 +811,58 @@ def readParameters(path): ...@@ -803,3 +811,58 @@ def readParameters(path):
return str(e) return str(e)
else: else:
return "No such file or directory: %s" % path return "No such file or directory: %s" % path
def isSoftwareReleaseReady(config):
"""Return 1 if the Software Release has
correctly been deployed, 0 if not,
and 2 if it is currently deploying"""
project = os.path.join(config['etc_dir'], '.project')
if not os.path.exists(project):
return "0"
path = open(project, 'r').readline().strip()
software_name = path
if software_name[-1] == '/':
software_name = software_name[:-1]
software_name = software_name.split('/')[-1]
config_SR_folder(config)
if os.path.exists(os.path.join(config['runner_workdir'],
'softwareLink', software_name, '.completed')):
return "1"
else:
if isSoftwareRunning(config):
return "2"
elif config['auto_deploy'] in TRUE_VALUES:
configNewSR(config, path)
runSoftwareWithLock(config)
return "2"
else:
return "0"
def cloneDefaultGit(config):
"""Test if the default git has been downloaded yet
If not, download it in read-only mode"""
default_git = os.path.join(config['runner_workdir'],
'project', 'default_repo')
if not os.path.exists(default_git):
data = {'path': default_git,
'repo': config['default_repo'],
}
cloneRepo(data)
def buildAndRun(config):
runSoftwareWithLock(config)
runInstanceWithLock(config)
def setupDefaultSR(config):
"""If a default_sr is in the parameters,
and no SR is deployed yet, setup it
also run SR and Instance if required"""
project = os.path.join(config['etc_dir'], '.project')
if not os.path.exists(project) and config['default_sr'] != '':
configNewSR(config, config['default_sr'])
if config['auto_deploy']:
thread.start_new_thread(buildAndRun, (config,))
...@@ -7,7 +7,7 @@ import os ...@@ -7,7 +7,7 @@ import os
import shutil import shutil
import urllib import urllib
from flaskext.auth import Auth, AuthUser, login_required, logout from flaskext.auth import logout
from flask import (Flask, request, redirect, url_for, render_template, from flask import (Flask, request, redirect, url_for, render_template,
g, flash, jsonify, session, abort, send_file) g, flash, jsonify, session, abort, send_file)
...@@ -17,7 +17,7 @@ from slapos.runner.utils import (checkSoftwareFolder, configNewSR, getFolder, ...@@ -17,7 +17,7 @@ from slapos.runner.utils import (checkSoftwareFolder, configNewSR, getFolder,
getProjectList, getProjectTitle, getSession, getProjectList, getProjectTitle, getSession,
getSlapStatus, getSvcStatus, getSlapStatus, getSvcStatus,
getSvcTailProcess, isInstanceRunning, getSvcTailProcess, isInstanceRunning,
isSoftwareRunning, isText, isSoftwareRunning, isSoftwareReleaseReady, isText,
loadSoftwareRList, md5sum, newSoftware, loadSoftwareRList, md5sum, newSoftware,
readFileFrom, readParameters, realpath, readFileFrom, readParameters, realpath,
removeInstanceRoot, removeProxyDb, removeInstanceRoot, removeProxyDb,
...@@ -28,13 +28,11 @@ from slapos.runner.utils import (checkSoftwareFolder, configNewSR, getFolder, ...@@ -28,13 +28,11 @@ from slapos.runner.utils import (checkSoftwareFolder, configNewSR, getFolder,
from slapos.runner.fileBrowser import FileBrowser from slapos.runner.fileBrowser import FileBrowser
from slapos.runner.gittools import (cloneRepo, gitStatus, switchBranch, from slapos.runner.gittools import (cloneRepo, gitStatus, switchBranch,
addBranch, getDiff, gitPush, gitPull) addBranch, getDiff, gitCommit, gitPush, gitPull)
app = Flask(__name__) app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 20 * 1024 * 1024 app.config['MAX_CONTENT_LENGTH'] = 20 * 1024 * 1024
auth = Auth(app, login_url_name='login')
auth.user_timeout = 0
file_request = FileBrowser(app.config) file_request = FileBrowser(app.config)
# Setup default flask (werkzeug) parser # Setup default flask (werkzeug) parser
...@@ -46,18 +44,15 @@ def login_redirect(*args, **kwargs): ...@@ -46,18 +44,15 @@ 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
@app.before_request @app.before_request
def before_request(): def before_request():
if request.path.startswith('/static'): if request.path.startswith('/static') \
or request.path == '/isSRReady':
return return
account = getSession(app.config) account = getSession(app.config)
if account: if account:
user = AuthUser(username=account[0])
user.set_and_encrypt_password(account[1], "123400ZYX")
session['title'] = getProjectTitle(app.config) session['title'] = getProjectTitle(app.config)
g.users = {account[0]: user}
else: else:
session['title'] = "No account is defined" session['title'] = "No account is defined"
if request.path != "/setAccount" and request.path != "/configAccount": if request.path != "/setAccount" and request.path != "/configAccount":
...@@ -65,13 +60,11 @@ def before_request(): ...@@ -65,13 +60,11 @@ def before_request():
# general views # general views
@login_required()
def home(): def home():
return render_template('index.html') return render_template('index.html')
# general views # general views
@login_required()
def browseWorkspace(): def browseWorkspace():
return render_template('workspace.html') return render_template('workspace.html')
...@@ -89,7 +82,6 @@ def setAccount(): ...@@ -89,7 +82,6 @@ def setAccount():
return redirect(url_for('login')) return redirect(url_for('login'))
@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],
...@@ -102,7 +94,6 @@ def dologout(): ...@@ -102,7 +94,6 @@ def dologout():
return redirect(url_for('login')) return redirect(url_for('login'))
@login_required()
def configRepo(): def configRepo():
public_key = open(app.config['public_key']).read() public_key = open(app.config['public_key']).read()
account = getSession(app.config) account = getSession(app.config)
...@@ -113,16 +104,12 @@ def configRepo(): ...@@ -113,16 +104,12 @@ def configRepo():
@app.route("/doLogin", methods=['POST']) @app.route("/doLogin", methods=['POST'])
def doLogin(): def doLogin():
username = request.form['clogin'] #XXX Now has to check the .htpasswd if we want to warn
if username in g.users: #the user that he misspelled his name/password
# Authenticate and log in!
if g.users[username].authenticate(request.form['cpwd']):
return jsonify(code=1, result="") return jsonify(code=1, result="")
return jsonify(code=0, result="Login or password is incorrect, please check it!"), 401
# software views # software views
@login_required()
def editSoftwareProfile(): def editSoftwareProfile():
profile = getProfilePath(app.config['etc_dir'], app.config['software_profile']) profile = getProfilePath(app.config['etc_dir'], app.config['software_profile'])
if profile == "": if profile == "":
...@@ -131,14 +118,12 @@ def editSoftwareProfile(): ...@@ -131,14 +118,12 @@ def editSoftwareProfile():
profile=profile, projectList=getProjectList(app.config['workspace'])) profile=profile, projectList=getProjectList(app.config['workspace']))
@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()
def removeSoftware(): def removeSoftware():
if isSoftwareRunning(app.config) or isInstanceRunning(app.config): if isSoftwareRunning(app.config) or isInstanceRunning(app.config):
flash('Software installation or instantiation in progress, cannot remove') flash('Software installation or instantiation in progress, cannot remove')
...@@ -151,7 +136,6 @@ def removeSoftware(): ...@@ -151,7 +136,6 @@ def removeSoftware():
return redirect(url_for('inspectSoftware')) return redirect(url_for('inspectSoftware'))
@login_required()
def runSoftwareProfile(): def runSoftwareProfile():
if runSoftwareWithLock(app.config): if runSoftwareWithLock(app.config):
return jsonify(result=True) return jsonify(result=True)
...@@ -159,7 +143,6 @@ def runSoftwareProfile(): ...@@ -159,7 +143,6 @@ def runSoftwareProfile():
return jsonify(result=False) return jsonify(result=False)
@login_required()
def viewSoftwareLog(): def viewSoftwareLog():
if os.path.exists(app.config['software_log']): if os.path.exists(app.config['software_log']):
result = tail(open(app.config['software_log']), lines=1500) result = tail(open(app.config['software_log']), lines=1500)
...@@ -170,7 +153,6 @@ def viewSoftwareLog(): ...@@ -170,7 +153,6 @@ def viewSoftwareLog():
# instance views # instance views
@login_required()
def editInstanceProfile(): def editInstanceProfile():
profile = getProfilePath(app.config['etc_dir'], app.config['instance_profile']) profile = getProfilePath(app.config['etc_dir'], app.config['instance_profile'])
if profile == "": if profile == "":
...@@ -180,7 +162,6 @@ def editInstanceProfile(): ...@@ -180,7 +162,6 @@ def editInstanceProfile():
# get status of all computer partitions and process state # get status of all computer partitions and process state
@login_required()
def inspectInstance(): def inspectInstance():
if os.path.exists(app.config['instance_root']): if os.path.exists(app.config['instance_root']):
file_path = 'instance_root' file_path = 'instance_root'
...@@ -196,7 +177,6 @@ def inspectInstance(): ...@@ -196,7 +177,6 @@ def inspectInstance():
#Reload instance process ans returns new value to ajax #Reload instance process ans returns new value to ajax
@login_required()
def supervisordStatus(): def supervisordStatus():
result = getSvcStatus(app.config) result = getSvcStatus(app.config)
if not result: if not result:
...@@ -213,7 +193,6 @@ def supervisordStatus(): ...@@ -213,7 +193,6 @@ def supervisordStatus():
return jsonify(code=1, result=html) return jsonify(code=1, result=html)
@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')
...@@ -228,7 +207,6 @@ def removeInstance(): ...@@ -228,7 +207,6 @@ def removeInstance():
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@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'])
...@@ -238,7 +216,6 @@ def runInstanceProfile(): ...@@ -238,7 +216,6 @@ def runInstanceProfile():
return jsonify(result=False) return jsonify(result=False)
@login_required()
def viewInstanceLog(): def viewInstanceLog():
if os.path.exists(app.config['instance_log']): if os.path.exists(app.config['instance_log']):
result = open(app.config['instance_log']).read() result = open(app.config['instance_log']).read()
...@@ -248,31 +225,26 @@ def viewInstanceLog(): ...@@ -248,31 +225,26 @@ def viewInstanceLog():
result=result.encode("utf-8")) result=result.encode("utf-8"))
@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)
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)
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)
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()
def cloneRepository(): def cloneRepository():
path = realpath(app.config, request.form['name'], False) path = realpath(app.config, request.form['name'], False)
data = { data = {
...@@ -284,27 +256,22 @@ def cloneRepository(): ...@@ -284,27 +256,22 @@ def cloneRepository():
return cloneRepo(data) return cloneRepo(data)
@login_required()
def readFolder(): def readFolder():
return getFolderContent(app.config, request.form['dir']) return getFolderContent(app.config, request.form['dir'])
@login_required()
def openFolder(): def openFolder():
return getFolder(app.config, request.form['dir']) return getFolder(app.config, request.form['dir'])
@login_required()
def createSoftware(): def createSoftware():
return newSoftware(request.form['folder'], app.config, session) return newSoftware(request.form['folder'], app.config, session)
@login_required()
def checkFolder(): def checkFolder():
return checkSoftwareFolder(request.form['path'], app.config) return checkSoftwareFolder(request.form['path'], app.config)
@login_required()
def setCurrentProject(): def setCurrentProject():
if configNewSR(app.config, request.form['path']): if configNewSR(app.config, request.form['path']):
session['title'] = getProjectTitle(app.config) session['title'] = getProjectTitle(app.config)
...@@ -313,13 +280,11 @@ def setCurrentProject(): ...@@ -313,13 +280,11 @@ def setCurrentProject():
return jsonify(code=0, result=("Can not setup this Software Release")) return jsonify(code=0, result=("Can not setup this Software Release"))
@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()
def getProjectStatus(): def getProjectStatus():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
if path: if path:
...@@ -329,7 +294,6 @@ def getProjectStatus(): ...@@ -329,7 +294,6 @@ def getProjectStatus():
#view for current software release files #view for current software release files
@login_required()
def editCurrentProject(): def editCurrentProject():
project = os.path.join(app.config['etc_dir'], ".project") project = os.path.join(app.config['etc_dir'], ".project")
if os.path.exists(project): if os.path.exists(project):
...@@ -340,7 +304,6 @@ def editCurrentProject(): ...@@ -340,7 +304,6 @@ def editCurrentProject():
#create file or directory #create file or directory
@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:
...@@ -356,7 +319,6 @@ def createFile(): ...@@ -356,7 +319,6 @@ def createFile():
#remove file or directory #remove file or directory
@login_required()
def removeFile(): def removeFile():
try: try:
if request.form['type'] == "folder": if request.form['type'] == "folder":
...@@ -368,7 +330,6 @@ def removeFile(): ...@@ -368,7 +330,6 @@ def removeFile():
return jsonify(code=0, result=str(e)) return jsonify(code=0, result=str(e))
@login_required()
def removeSoftwareDir(): def removeSoftwareDir():
try: try:
data = removeSoftwareByName(app.config, request.form['md5'], data = removeSoftwareByName(app.config, request.form['md5'],
...@@ -379,7 +340,6 @@ def removeSoftwareDir(): ...@@ -379,7 +340,6 @@ def removeSoftwareDir():
#read file and return content to ajax #read file and return content to ajax
@login_required()
def getFileContent(): def getFileContent():
file_path = realpath(app.config, request.form['file']) file_path = realpath(app.config, request.form['file'])
if file_path: if file_path:
...@@ -395,7 +355,6 @@ def getFileContent(): ...@@ -395,7 +355,6 @@ def getFileContent():
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@login_required()
def saveFileContent(): def saveFileContent():
file_path = realpath(app.config, request.form['file']) file_path = realpath(app.config, request.form['file'])
if file_path: if file_path:
...@@ -405,7 +364,6 @@ def saveFileContent(): ...@@ -405,7 +364,6 @@ def saveFileContent():
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@login_required()
def changeBranch(): def changeBranch():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
if path: if path:
...@@ -414,7 +372,6 @@ def changeBranch(): ...@@ -414,7 +372,6 @@ def changeBranch():
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required()
def newBranch(): def newBranch():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
if path: if path:
...@@ -426,23 +383,26 @@ def newBranch(): ...@@ -426,23 +383,26 @@ def newBranch():
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)
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))
def commitProjectFiles():
path = realpath(app.config, request.form['project'])
if path:
return gitCommit(path, request.form['msg'])
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required()
def pushProjectFiles(): def pushProjectFiles():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
if path: if path:
return gitPush(path, request.form['msg']) return gitPush(path)
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()
def pullProjectFiles(): def pullProjectFiles():
path = realpath(app.config, request.form['project']) path = realpath(app.config, request.form['project'])
if path: if path:
...@@ -451,7 +411,6 @@ def pullProjectFiles(): ...@@ -451,7 +411,6 @@ def pullProjectFiles():
return jsonify(code=0, result="Can not read folder: Permission Denied") return jsonify(code=0, result="Can not read folder: Permission Denied")
@login_required()
def checkFileType(): def checkFileType():
path = realpath(app.config, request.form['path']) path = realpath(app.config, request.form['path'])
if not path: if not path:
...@@ -463,7 +422,6 @@ def checkFileType(): ...@@ -463,7 +422,6 @@ def checkFileType():
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()
def getmd5sum(): def getmd5sum():
realfile = realpath(app.config, request.form['file']) realfile = realpath(app.config, request.form['file'])
if not realfile: if not realfile:
...@@ -476,7 +434,6 @@ def getmd5sum(): ...@@ -476,7 +434,6 @@ def getmd5sum():
#return information about state of slapgrid process #return information about state of slapgrid process
@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)
...@@ -494,13 +451,11 @@ def slapgridResult(): ...@@ -494,13 +451,11 @@ def slapgridResult():
result=(instance_state or software_state), content=log_result) result=(instance_state or software_state), content=log_result)
@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()
def getPath(): def getPath():
files = request.form['file'].split('#') files = request.form['file'].split('#')
list = [] list = []
...@@ -519,7 +474,6 @@ def getPath(): ...@@ -519,7 +474,6 @@ def getPath():
return jsonify(code=1, result=realfile) return jsonify(code=1, result=realfile)
@login_required()
def saveParameterXml(): def saveParameterXml():
""" """
Update instance parameter into a local xml file. Update instance parameter into a local xml file.
...@@ -550,7 +504,6 @@ def saveParameterXml(): ...@@ -550,7 +504,6 @@ def saveParameterXml():
return jsonify(code=1, result="") return jsonify(code=1, result="")
@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")
if os.path.exists(software_type_path): if os.path.exists(software_type_path):
...@@ -559,7 +512,6 @@ def getSoftwareType(): ...@@ -559,7 +512,6 @@ def getSoftwareType():
#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()
def getParameterXml(request): def getParameterXml(request):
param_path = os.path.join(app.config['etc_dir'], ".parameter.xml") param_path = os.path.join(app.config['etc_dir'], ".parameter.xml")
if not os.path.exists(param_path): if not os.path.exists(param_path):
...@@ -576,7 +528,6 @@ def getParameterXml(request): ...@@ -576,7 +528,6 @@ def getParameterXml(request):
#update user account data #update user account data
@login_required()
def updateAccount(): def updateAccount():
code = request.form['rcode'].strip() code = request.form['rcode'].strip()
recovery_code = open(os.path.join(app.config['etc_dir'], ".rcode"), "r").read() recovery_code = open(os.path.join(app.config['etc_dir'], ".rcode"), "r").read()
...@@ -622,7 +573,6 @@ def configAccount(): ...@@ -622,7 +573,6 @@ def configAccount():
#Global File Manager #Global File Manager
@login_required()
def fileBrowser(): def fileBrowser():
if request.method == 'POST': if request.method == 'POST':
filename = request.form.get('filename', '').encode('utf-8') filename = request.form.get('filename', '').encode('utf-8')
...@@ -687,13 +637,19 @@ def fileBrowser(): ...@@ -687,13 +637,19 @@ def fileBrowser():
return result return result
@login_required()
def editFile(): def editFile():
return render_template('editFile.html', workDir='workspace', return render_template('editFile.html', workDir='workspace',
profile=urllib.unquote(request.args.get('profile', '')), profile=urllib.unquote(request.args.get('profile', '')),
projectList=getProjectList(app.config['workspace']), projectList=getProjectList(app.config['workspace']),
filename=urllib.unquote(request.args.get('filename', ''))) filename=urllib.unquote(request.args.get('filename', '')))
def shell():
return render_template('shell.html')
def isSRReady():
return isSoftwareReleaseReady(app.config)
#Setup List of URLs #Setup List of URLs
app.add_url_rule('/', 'home', home) app.add_url_rule('/', 'home', home)
...@@ -735,6 +691,8 @@ app.add_url_rule("/checkFileType", 'checkFileType', checkFileType, ...@@ -735,6 +691,8 @@ app.add_url_rule("/checkFileType", 'checkFileType', checkFileType,
methods=['POST']) methods=['POST'])
app.add_url_rule("/pullProjectFiles", 'pullProjectFiles', pullProjectFiles, app.add_url_rule("/pullProjectFiles", 'pullProjectFiles', pullProjectFiles,
methods=['POST']) methods=['POST'])
app.add_url_rule("/commitProjectFiles", 'commitProjectFiles', commitProjectFiles,
methods=['POST'])
app.add_url_rule("/pushProjectFiles", 'pushProjectFiles', pushProjectFiles, app.add_url_rule("/pushProjectFiles", 'pushProjectFiles', pushProjectFiles,
methods=['POST']) methods=['POST'])
app.add_url_rule("/getProjectDiff/<project>", 'getProjectDiff', getProjectDiff, app.add_url_rule("/getProjectDiff/<project>", 'getProjectDiff', getProjectDiff,
...@@ -774,3 +732,5 @@ app.add_url_rule("/updateAccount", 'updateAccount', updateAccount, ...@@ -774,3 +732,5 @@ app.add_url_rule("/updateAccount", 'updateAccount', updateAccount,
app.add_url_rule("/fileBrowser", 'fileBrowser', fileBrowser, app.add_url_rule("/fileBrowser", 'fileBrowser', fileBrowser,
methods=['GET', 'POST']) methods=['GET', 'POST'])
app.add_url_rule("/editFile", 'editFile', editFile, methods=['GET']) app.add_url_rule("/editFile", 'editFile', editFile, methods=['GET'])
app.add_url_rule('/shell', 'shell', shell)
app.add_url_rule('/isSRReady', 'isSRReady', isSRReady)
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