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 feedparser
import httplib # To avoid magic numbers
import io
import socket
import json
import time
import math
import httplib # To avoid magic numbers
import argparse
import os
import socket
import sys
import time
from datetime import datetime
from hashlib import sha512
from atomize import Entry
......@@ -19,6 +20,9 @@ from flask import abort
from flask import request
app = Flask(__name__)
# csv entries can be very large, increase limit.
csv.field_size_limit(sys.maxsize)
@app.route('/get/<feed>')
def get_feed(feed):
global app
......
......@@ -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: 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.
------------
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
import logging
import time
import os
class ResiliencyTestSuite(object):
"""
......@@ -104,6 +105,14 @@ class ResiliencyTestSuite(object):
"""
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):
"""
......@@ -115,6 +124,7 @@ class ResiliencyTestSuite(object):
software_type='resilient',
partition_reference=self.root_instance_name
).getConnectionParameterDict()
self.deleteTimestamp()
def _returnNewInstanceParameter(self, parameter_key, old_parameter_value):
"""
......@@ -126,8 +136,8 @@ class ResiliencyTestSuite(object):
new_parameter_value = None
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)
time.sleep(60)
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)
return new_parameter_value
......
......@@ -28,6 +28,7 @@
from .resiliencytestsuite import ResiliencyTestSuite
import base64
import cookielib
import random
import string
......@@ -63,6 +64,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
300
)
def _connectToSlaprunner(self, resource, data=None):
"""
Utility.
......@@ -81,10 +83,8 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
def _login(self):
self.logger.debug('Logging in...')
self._connectToSlaprunner('doLogin', data='clogin=%s&cpwd=%s' % (
self.slaprunner_user,
self.slaprunner_password)
)
b64string = base64.encodestring('%s:%s' % (self.slaprunner_user, self.slaprunner_password))[:-1]
self._opener_director.addheaders = [('Authorization', 'Basic %s'%b64string)]
def _retrieveInstanceLogFile(self):
"""
......@@ -112,10 +112,17 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
return data
def _waitForSoftwareBuild(self):
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.')
#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...')
time.sleep(15)
except (NotHttpOkException, urllib2.HTTPError):
# The nginx frontend might timeout before software release is finished.
self._waitForSoftwareBuild()
def _buildSoftwareRelease(self):
self.logger.info('Building the Software Release...')
......@@ -199,6 +206,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
self._openSoftwareRelease('helloworld')
self._buildSoftwareRelease()
time.sleep(15)
self._deployInstance()
self.data = self._retrieveInstanceLogFile()
......@@ -219,9 +227,7 @@ class SlaprunnerTestSuite(ResiliencyTestSuite):
)
self._login()
self._waitForSoftwareBuild()
# XXX: in theory, it should be done automatically by slaprunner.
# In practice, it is still too dangerous for ERP5 instances.
self._deployInstance()
time.sleep(15)
new_data = self._retrieveInstanceLogFile()
if new_data == self.data:
......
......@@ -6,51 +6,12 @@ import ConfigParser
import datetime
import logging
import logging.handlers
from optparse import OptionParser, Option
import os
import slapos.runner.process
from slapos.htpasswd import HtpasswdFile
from slapos.runner.process import setHandler
import sys
from slapos.runner.utils import runInstanceWithLock
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]
from slapos.runner.views import *
class Config:
......@@ -61,19 +22,15 @@ class Config:
self.logger = None
self.verbose = None
def setConfig(self, option_dict, configuration_file_path):
def setConfig(self):
"""
Set options given by parameters.
"""
self.configuration_file_path = os.path.abspath(configuration_file_path)
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
self.configuration_file_path = os.path.abspath(os.getenv('RUNNER_CONFIG'))
# Load configuration file
configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path)
# Merges the arguments and configuration
configuration_parser.read(self.configuration_file_path)
for section in ("slaprunner", "slapos", "slapproxy", "slapformat",
"sshkeys_authority", "gitclient", "cloud9_IDE"):
......@@ -88,17 +45,17 @@ class Config:
if self.console:
self.logger.addHandler(logging.StreamHandler())
if 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
# continue to run
raise ValueError('Please create directory %r to store %r log file' % (
os.path.dirname(self.log_file), self.log_file))
else:
file_handler = logging.FileHandler(self.log_file)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
self.logger.addHandler(file_handler)
self.logger.info('Configured logging to file %r' % self.log_file)
self.log_file = self.log_dir + '/slaprunner.log'
if not os.path.isdir(os.path.dirname(self.log_file)):
# fallback to console only if directory for logs does not exists and
# continue to run
raise ValueError('Please create directory %r to store %r log file' % (
os.path.dirname(self.log_file), self.log_file))
else:
file_handler = logging.FileHandler(self.log_file)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
self.logger.addHandler(file_handler)
self.logger.info('Configured logging to file %r' % self.log_file)
self.logger.info("Started.")
self.logger.info(os.environ['PATH'])
......@@ -107,30 +64,33 @@ class Config:
self.logger.debug("Verbose mode enabled.")
def run():
"Run default configuration."
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
# Parse arguments
config = Config()
config.setConfig(*Parser(usage=usage).check_args())
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
if os.getuid() == 0:
# avoid mistakes (mainly in development mode)
raise Exception('Do not run SlapRunner as root.')
serve(config)
return_code = 0
except SystemExit as err:
# Catch exception raise by optparse
return_code = err
def run():
"Run default configuration."
# Parse arguments
config = Config()
config.setConfig()
sys.exit(return_code)
if os.getuid() == 0:
# avoid mistakes (mainly in development mode)
raise Exception('Do not run SlapRunner as root.')
serve(config)
def serve(config):
from views import app
from werkzeug.contrib.fixers import ProxyFix
workdir = os.path.join(config.runner_workdir, 'project')
software_link = os.path.join(config.runner_workdir, 'softwareLink')
......@@ -145,14 +105,15 @@ def serve(config):
SECRET_KEY=os.urandom(24),
PERMANENT_SESSION_LIFETIME=datetime.timedelta(days=31),
)
checkHtpasswd(app.config)
if not os.path.exists(workdir):
os.mkdir(workdir)
if not os.path.exists(software_link):
os.mkdir(software_link)
slapos.runner.process.setHandler()
setHandler()
config.logger.info('Running slapgrid...')
runInstanceWithLock(app.config)
config.logger.info('Done.')
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):
result = safeResult(str(e))
return result
def gitCommit(project, msg):
"""Commit changes for the specified repository
Args:
project: directory of the local repository
msg: commit message"""
code = 0
json = ""
repo = Repo(project)
if repo.is_dirty:
git = repo.git
#add file to be commited
files = repo.untracked_files
for f in files:
git.add(f)
#Commit all modified and untracked files
git.commit('-a', '-m', msg)
else:
code = 1
json = "Nothing to be commited"
return jsonify(code=code, result=json)
def gitPush(project, msg):
"""Commit and Push changes for the specified repository
def gitPush(project):
"""Push changes for the specified repository
Args:
project: directory of the local repository
msg: commit message"""
code = 0
json = ""
undo_commit = False
try:
repo = Repo(project)
if repo.is_dirty:
git = repo.git
current_branch = repo.active_branch.name
#add file to be commited
files = repo.untracked_files
for f in files:
git.add(f)
#Commit all modified and untracked files
git.commit('-a', '-m', msg)
undo_commit = True
#push changes to repo
git.push('origin', current_branch)
code = 1
else:
json = "Nothing to commit"
code = 1
#push changes to repo
current_branch = repo.active_branch.name
git.push('origin', current_branch)
code = 1
except Exception as e:
if undo_commit:
git.reset("HEAD~") # undo previous commit
json = safeResult(str(e))
return jsonify(code=code, result=json)
......
......@@ -2,6 +2,14 @@
# vim: set et sts=2:
# 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 ConfigParser
import datetime
......@@ -13,10 +21,12 @@ import time
import unittest
from slapos.runner.utils import (getProfilePath, getSession, isInstanceRunning,
isSoftwareRunning, startProxy)
isSoftwareRunning, startProxy,
isSoftwareReleaseReady)
from slapos.runner.process import killRunningProcess, isRunning
from slapos.runner import views
import slapos.slap
from slapos.htpasswd import HtpasswdFile
#Helpers
......@@ -63,7 +73,6 @@ class SlaprunnerTestCase(unittest.TestCase):
self.project = 'slapos' # Default project name
self.template = 'template.cfg'
self.partitionPrefix = 'slappart'
self.slaposBuildout = "1.6.0-dev-SlapOS-010"
#create slaprunner configuration
config = Config()
config.setConfig()
......@@ -110,7 +119,6 @@ class SlaprunnerTestCase(unittest.TestCase):
shutil.rmtree(self.app.config['instance_root'])
if os.path.exists(self.app.config['software_link']):
shutil.rmtree(self.app.config['software_link'])
self.logout()
#Stop process
killRunningProcess('slapproxy', recursive=True)
killRunningProcess('slapgrid-cp', recursive=True)
......@@ -128,26 +136,11 @@ class SlaprunnerTestCase(unittest.TestCase):
),
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):
"""Initialize user account and log user in"""
response = loadJson(self.configAccount(self.users[0], self.users[1],
self.users[2], self.users[3], self.rcode))
response2 = loadJson(self.login(self.users[0], self.users[1]))
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):
"""Helper for update user account data"""
......@@ -186,8 +179,7 @@ class SlaprunnerTestCase(unittest.TestCase):
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 += "\ndownload-dir-url = http://www.shacache.org/shadir\n\n"
sr += "[command]\nrecipe = zc.recipe.egg\neggs = plone.recipe.command\n\n"
sr += "[versions]\nzc.buildout = %s\n" % self.slaposBuildout
sr += "[command]\nrecipe = zc.recipe.egg\neggs = plone.recipe.command\n zc.buildout\n\n"
os.mkdir(testSoftware)
open(os.path.join(testSoftware, self.app.config['software_profile']),
'w').write(sr)
......@@ -216,13 +208,6 @@ class SlaprunnerTestCase(unittest.TestCase):
"""Kill slapproxy process"""
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):
"""For the first lauch of slaprunner user need do create first account"""
result = self.configAccount(self.users[0], self.users[1], self.users[2],
......@@ -232,34 +217,16 @@ class SlaprunnerTestCase(unittest.TestCase):
account = getSession(self.app.config)
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):
"""test Update accound, this needs the user to log in"""
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))
self.assertEqual(response['code'], 1)
result = self.logout()
assert "<h2>Login to Slapos Web Runner</h2>" in result.data
#retry login with new values
response = loadJson(self.login(self.updateUser[0], self.updateUser[1]))
self.assertEqual(response['result'], "")
#log out now!
self.logout()
encode = HtpasswdFile(htpasswd, False)
encode.update(self.updateUser[0], self.updateUser[1])
assert self.updateUser[0] in open(htpasswd).read()
def test_startProxy(self):
"""Test slapproxy"""
......@@ -301,7 +268,6 @@ class SlaprunnerTestCase(unittest.TestCase):
),
follow_redirects=True))
self.assertEqual(response['result'], "")
self.logout()
def test_createSR(self):
"""Scenario 2: Create a new software release"""
......@@ -315,13 +281,10 @@ class SlaprunnerTestCase(unittest.TestCase):
self.assertEqual(response['result'], "")
currentSR = self.getCurrentSR()
assert newSoftware in currentSR
self.logout()
def test_openSR(self):
"""Scenario 3: Open software release"""
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
response = loadJson(self.app.post('/setCurrentProject',
data=dict(path=software),
......@@ -336,7 +299,6 @@ class SlaprunnerTestCase(unittest.TestCase):
# newSoftware = os.path.join(self.software, 'slaprunner-test')
self.proxyStatus(True)
self.stopSlapproxy()
self.logout()
def test_runSoftware(self):
"""Scenario 4: CReate empty SR and save software.cfg file
......@@ -345,8 +307,6 @@ class SlaprunnerTestCase(unittest.TestCase):
#Call config account
#call create software Release
self.test_createSR()
#Login
self.login(self.users[0], self.users[1])
newSoftware = self.getCurrentSR()
softwareRelease = "[buildout]\n\nparts =\n test-application\n"
softwareRelease += "#Test download git web repos éè@: utf-8 caracters\n"
......@@ -376,7 +336,6 @@ class SlaprunnerTestCase(unittest.TestCase):
self.assertTrue(os.path.exists(createdFile))
self.proxyStatus(True)
self.stopSlapproxy()
self.logout()
def test_updateInstanceParameter(self):
"""Scenarion 5: Update parameters of current sofware profile"""
......@@ -419,13 +378,10 @@ class SlaprunnerTestCase(unittest.TestCase):
response = loadJson(self.app.get('/getParameterXml/dict'))
self.assertEqual(parameterDict, response['result']['instance'])
self.stopSlapproxy()
self.logout()
def test_requestInstance(self):
"""Scenarion 6: request software instance"""
self.test_updateInstanceParameter()
#Login
self.login(self.users[0], self.users[1])
self.proxyStatus(False, sleep_time=1)
#run Software profile
response = loadJson(self.app.post('/runSoftwareProfile',
......@@ -453,8 +409,34 @@ class SlaprunnerTestCase(unittest.TestCase):
assert 'simple file' in open(createdFile).read()
self.proxyStatus(True)
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():
# Empty parser for now - so that erp5testnode is happy when doing --help
......
......@@ -297,6 +297,10 @@ input[type="radio"], input[type="checkbox"]{
margin-bottom:10px;
}
#commitmsg {
width:95%;
}
.message {
color:#FF5500;
line-height:21px;
......@@ -449,7 +453,7 @@ padding: 10px;height: 80px;padding-bottom:15px;}
}
#code{
float: right;
width: 692px;
width: 680px;
}
#details_head{margin-bottom: 10px;}
......@@ -728,3 +732,5 @@ padding:10px; font-size:14px; color:#03406A}
.login-input{width:220px;}
.information{display:block; float:left; height:16px; margin-top:10px; margin-left:10px; font-weight:bold}
.account{margin-left:60px;}
/* ********************/
#shellinabox{width:100%; min-height:530px;}
......@@ -43,6 +43,8 @@ $(document).ready(function () {
return false;
}
send = true;
var base_url = 'https://' + $("input#username").val() + ':'
+ $("input#password").val() + '@' + location.host
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + ((hasAccount) ? '/updateAccount' : '/configAccount'),
......@@ -55,7 +57,7 @@ $(document).ready(function () {
},
success: function (data) {
if (data.code === 1) {
window.location.href = $SCRIPT_ROOT + "/";
window.location.href = base_url + $SCRIPT_ROOT + '/';
} else {
$("#error").Popup(data.result, {type: 'error', duration: 5000});
}
......
......@@ -90,3 +90,4 @@ function bindRemove() {
}
});
}(jQuery, document, this));
......@@ -27,7 +27,9 @@ $(document).ready(function () {
$("#login").removeClass("button").addClass("dsblebutton");
$.post(url, param, function (data) {
if (data.code === 1) {
window.location.href = $SCRIPT_ROOT + '/';
url = 'https://' + param.clogin + ':' + param.cpwd + '@'
+ location.host + $SCRIPT_ROOT + '/';
window.location.href = url;
} else {
$("#error").Popup(data.result, {type: 'alert', duration: 3000});
}
......
......@@ -2,6 +2,13 @@
/*global $, document, $SCRIPT_ROOT */
/* vim: set et sts=4: */
$.valHooks.textarea = {
get: function (elem) {
"use strict";
return elem.value.replace(/\r?\n/g, "\r\n");
}
};
$(document).ready(function () {
"use strict";
......@@ -23,7 +30,7 @@ $(document).ready(function () {
urldata = $("input#workdir").val() + "/" + project;
$("#status").empty();
$("#push").hide();
$("#commit").hide();
$("#flash").empty();
if (project === "") {
$("#status").append("<h2>Please select one project...</h2><br/><br/>");
......@@ -45,7 +52,7 @@ $(document).ready(function () {
//alert(message);
$("#status").append("<p>" + message + "</p>");
if (data.dirty) {
$("#push").show();
$("#commit").show();
$("#status").append("<br/><h2>Display Diff for current Project</h2>");
$("#status").append("<p style='font-size:15px;'>You have changes in your project." +
" <a href='" + $SCRIPT_ROOT + "/getProjectDiff/"
......@@ -119,9 +126,9 @@ $(document).ready(function () {
checkout("0");
return false;
});
$("#commit").click(function () {
$("#commitbutton").click(function () {
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});
return false;
}
......@@ -131,12 +138,12 @@ $(document).ready(function () {
send = true;
var project = $("#project").val();
$("#imgwaitting").fadeIn('normal');
$("#commit").empty();
$("#commit").attr("value", "Wait...");
//$("#commit").empty();
$("#commitbbutton").attr("value", "Wait...");
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/pushProjectFiles',
data: {project: $("input#workdir").val() + "/" + project, msg: $("input#commitmsg").val()},
url: $SCRIPT_ROOT + '/commitProjectFiles',
data: {project: $("input#workdir").val() + "/" + project, msg: $("textarea#commitmsg").val()},
success: function (data) {
if (data.code === 1) {
if (data.result !== "") {
......@@ -144,19 +151,46 @@ $(document).ready(function () {
} else {
$("#error").Popup("Commit done!", {type: 'confirm', duration: 3000});
}
$("#commit").hide();
gitStatus();
} else {
$("#error").Popup(data.result, {type: 'error'});
}
$("#imgwaitting").hide();
$("#commit").empty();
$("#commit").attr("value", "Commit");
$("#commitmsg").empty();
$("#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;
}
});
return false;
});
/*
$("#pullbranch").click(function (){
if (send){
......
......@@ -55,9 +55,12 @@
<a href="{{ url_for('home') }}" style="float:left;" id="home" {% if request.path != '/' %}rel="tooltip"{% endif %} title="Home"><img alt="" src="{{ url_for('static', filename='images/home.png') }}" /></a>
<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>
<div class="line"></div>
<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>
<a href="{{ url_for('dologout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a>
<div class="line"></div>
<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') }}"
height='26' title="slapgrid is currently running"/></span></div>
......
......@@ -40,15 +40,22 @@
<!--<img class="waitting" id="pullimgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />-->
</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>
<div style="margin-left:15px;">
<label for='commitmsg'>Commit message: </label>
<input type="text" name="commitmsg" id="commitmsg" size='40' value="Enter message..." />
<input type="submit" name="commit" id ="commit" value="Commit" class="button"/>
<textarea name="commitmsg" id="commitmsg" cols="40" rows="3">
</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="" />
</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/>
</div>
</div>
......
{% extends "layout.html" %}
{% block body %}
<iframe id="shellinabox" src="/shellinabox"></iframe>
{% endblock %}
......@@ -5,9 +5,10 @@
import logging
import md5
import multiprocessing
import os
import re
import shutil
import os
import thread
import time
import urllib
from xml.dom import minidom
......@@ -15,6 +16,8 @@ from xml.dom import minidom
import xml_marshaller
from flask import jsonify
from slapos.runner.gittools import cloneRepo
from slapos.runner.process import Popen, isRunning, killRunningProcess
from slapos.htpasswd import HtpasswdFile
import slapos.slap
......@@ -23,6 +26,7 @@ import slapos.slap
logger = logging.getLogger('werkzeug')
TRUE_VALUES = (1, '1', True, 'true', 'True')
html_escape_table = {
"&": "&amp;",
......@@ -276,12 +280,16 @@ def config_SR_folder(config):
if len(cfg) != 2:
continue # there is a broken config file
list.append(cfg[1])
folder_list = os.listdir(config['software_root'])
if os.path.exists(config['software_root']):
folder_list = os.listdir(config['software_root'])
else:
return
if not folder_list:
return
current_project = open(os.path.join(config['etc_dir'], ".project")).read()
projects = current_project.split('/')
name = projects[-2]
if current_project[-1] == '/':
current_project = current_project[:-1]
name = current_project.split('/')[-1]
for folder in folder_list:
if folder in list:
continue # this folder is already registered
......@@ -337,7 +345,7 @@ def runInstanceWithLock(config):
slapgrid = Popen([config['slapgrid_cp'], '-vc',
'--pidfile', slapgrid_pid,
config['configuration_file_path'], '--now'],
stdout=logfile, name='slapgrid-cp')
stdout=logfile, name='slapgrid-cp')
slapgrid.wait()
return True
......@@ -803,3 +811,58 @@ def readParameters(path):
return str(e)
else:
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,))
This diff is collapsed.
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