Commit 4d444533 authored by Antoine Catton's avatar Antoine Catton

Merge branch 'master' into skynet

parents 37faafcc bd12f3f2
0.11 (unreleased) 0.17 (unreleased)
=================
* No change yet.
0.16 (2012-01-20)
=================
* Fix MANIFEST.in [Cedric de Saint Martin]
0.15 (2012-01-20)
=================
* slaprunner: Adding project and git repository management [Alain Takoudjou]
0.14 (2012-01-09)
=================
* onetimeupload: SSL should be provided by an http frontend [Romain Courteaud]
0.13 (2011-12-30)
=================
* builder: fix usage of mkstemp [Romain Courteaud]
0.12 (2011-12-29)
=================
* builder: dynamic offset calculation [Romain Courteaud]
0.11 (2011-12-23)
================= =================
* equeue: Add execution queue server. [Antoine Catton] * equeue: Add execution queue server. [Antoine Catton]
* pubsub: Add pubsub server using pubsubhubbub for notifications. [Antoine Catton]
0.10 (2011-11-07) 0.10 (2011-11-07)
================= =================
......
...@@ -4,4 +4,4 @@ include slapos/builder/script/slapos ...@@ -4,4 +4,4 @@ include slapos/builder/script/slapos
include slapos/builder/script/slapos_firstboot include slapos/builder/script/slapos_firstboot
recursive-include slapos/onetimeupload/templates *.html recursive-include slapos/onetimeupload/templates *.html
recursive-include slapos/runner/templates *.html recursive-include slapos/runner/templates *.html
recursive-include slapos/runner/static *.css .png recursive-include slapos/runner/static *.css *.png *.js
...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages ...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import glob import glob
import os import os
version = '0.11-dev' version = '0.17-dev'
name = 'slapos.toolbox' name = 'slapos.toolbox'
long_description = open("README.txt").read() + "\n" + \ long_description = open("README.txt").read() + "\n" + \
open("CHANGES.txt").read() + "\n" open("CHANGES.txt").read() + "\n"
...@@ -36,6 +36,7 @@ setup(name=name, ...@@ -36,6 +36,7 @@ setup(name=name,
'slapos.core', # as it provides library for slap 'slapos.core', # as it provides library for slap
'SQLAlchemy', # needed by wordpress.ia 'SQLAlchemy', # needed by wordpress.ia
'xml_marshaller', # needed to dump information 'xml_marshaller', # needed to dump information
'GitPython', #needed for git manipulation into slaprunner
], ],
extras_require = { extras_require = {
'lampconfigure': ["mysql-python"] #needed for MySQL Database access 'lampconfigure': ["mysql-python"] #needed for MySQL Database access
......
...@@ -30,7 +30,7 @@ import sys ...@@ -30,7 +30,7 @@ import sys
from optparse import OptionParser, Option from optparse import OptionParser, Option
from subprocess import call as subprocessCall from subprocess import call as subprocessCall
from stat import S_ISBLK, ST_MODE from stat import S_ISBLK, ST_MODE
from tempfile import mkdtemp from tempfile import mkdtemp, mkstemp
import shutil import shutil
import pkg_resources import pkg_resources
...@@ -138,10 +138,23 @@ def run(config): ...@@ -138,10 +138,23 @@ def run(config):
print "Creating temp directory" print "Creating temp directory"
if not dry_run: if not dry_run:
mount_dir_path = mkdtemp() mount_dir_path = mkdtemp()
fdisk_output_path = mkstemp()[1]
else: else:
mount_dir_path = "/tmp/a_generated_directory" mount_dir_path = "/tmp/a_generated_directory"
fdisk_output_path = "/tmp/a_generated_file"
try: try:
_call(['mount', '-o', 'loop,offset=32256', config.system_path, offset = 0
fdisk_output_file = open(fdisk_output_path, 'w')
_call(['sfdisk', '-d', '-uS', config.system_path], stdout=fdisk_output_file)
fdisk_output_file.close()
fdisk_output_file = open(fdisk_output_path, 'r')
for line in fdisk_output_file:
line = line.rstrip().replace(' ', '')
if line.endswith("bootable"):
offset = int(line.split(':')[1].split(',')[0].split('=')[1])
fdisk_output_file.close()
offset = offset * 512
_call(['mount', '-o', 'loop,offset=%i' % offset, config.system_path,
mount_dir_path], dry_run=dry_run) mount_dir_path], dry_run=dry_run)
try: try:
# Create slapos configuration directory if needed # Create slapos configuration directory if needed
...@@ -267,6 +280,9 @@ def run(config): ...@@ -267,6 +280,9 @@ def run(config):
print "Deleting temp directory: %s" % mount_dir_path print "Deleting temp directory: %s" % mount_dir_path
if not dry_run: if not dry_run:
shutil.rmtree(mount_dir_path) shutil.rmtree(mount_dir_path)
print "Deleting temp file: %s" % fdisk_output_path
if not dry_run:
os.remove(fdisk_output_path)
# Copying # Copying
if not config.no_usb: if not config.no_usb:
......
...@@ -104,7 +104,7 @@ def run(config): ...@@ -104,7 +104,7 @@ def run(config):
template = app.open_resource('templates/index.html') template = app.open_resource('templates/index.html')
return template.read() return template.read()
app.run(host=config.host, port=config.port, ssl_context='adhoc') app.run(host=config.host, port=config.port)
def main(): def main():
"Run default configuration." "Run default configuration."
......
...@@ -4,6 +4,7 @@ import logging ...@@ -4,6 +4,7 @@ import logging
import logging.handlers import logging.handlers
import os import os
import sys import sys
import subprocess
class Parser(OptionParser): class Parser(OptionParser):
""" """
...@@ -56,7 +57,8 @@ class Config: ...@@ -56,7 +57,8 @@ class Config:
configuration_parser = ConfigParser.SafeConfigParser() configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path) configuration_parser.read(configuration_file_path)
# Merges the arguments and configuration # Merges the arguments and configuration
for section in ("slaprunner", "slapos", "slapproxy", "slapformat"):
for section in ("slaprunner", "slapos", "slapproxy", "slapformat", "sshkeys_authority", "gitclient"):
configuration_dict = dict(configuration_parser.items(section)) configuration_dict = dict(configuration_parser.items(section))
for key in configuration_dict: for key in configuration_dict:
if not getattr(self, key, None): if not getattr(self, key, None):
...@@ -81,6 +83,7 @@ class Config: ...@@ -81,6 +83,7 @@ class Config:
self.logger.info('Configured logging to file %r' % self.log_file) self.logger.info('Configured logging to file %r' % self.log_file)
self.logger.info("Started.") self.logger.info("Started.")
self.logger.info(os.environ['PATH'])
if self.verbose: if self.verbose:
self.logger.setLevel(logging.DEBUG) self.logger.setLevel(logging.DEBUG)
self.logger.debug("Verbose mode enabled.") self.logger.debug("Verbose mode enabled.")
...@@ -105,13 +108,17 @@ def run(): ...@@ -105,13 +108,17 @@ def run():
def serve(config): def serve(config):
from views import app from views import app
workdir = os.path.join(config.runner_workdir, 'project')
app.config.update(**config.__dict__) app.config.update(**config.__dict__)
app.config.update( app.config.update(
software_log=config.software_root.rstrip('/') + '.log', software_log=config.software_root.rstrip('/') + '.log',
instance_log=config.instance_root.rstrip('/') + '.log', instance_log=config.instance_root.rstrip('/') + '.log',
instance_profile=os.path.join(config.runner_workdir, 'instance.cfg'), workspace = workdir,
software_profile=os.path.join(config.runner_workdir, 'software.cfg'), instance_profile='instance.cfg',
software_profile='software.cfg',
SECRET_KEY='123', SECRET_KEY='123',
) )
if not os.path.exists(workdir):
os.mkdir(workdir)
app.run(host=config.runner_host, port=int(config.runner_port), app.run(host=config.runner_host, port=int(config.runner_port),
debug=config.debug, threaded=True) debug=config.debug, threaded=True)
import slapos.slap
import time
import subprocess
import os
import re
import urllib
from flask import jsonify
import shutil
import string
from git import *
class Popen(subprocess.Popen):
def __init__(self, *args, **kwargs):
kwargs['stdin'] = subprocess.PIPE
kwargs['stderr'] = subprocess.STDOUT
kwargs.setdefault('stdout', subprocess.PIPE)
kwargs.setdefault('close_fds', True)
subprocess.Popen.__init__(self, *args, **kwargs)
self.stdin.flush()
self.stdin.close()
self.stdin = None
def cloneRepo(data):
workDir = data['path']
code = 0
json = ""
try:
if os.path.exists(workDir) and len(os.listdir(workDir)) < 2:
shutil.rmtree(workDir) #delete useless files
repo = Repo.clone_from(data["repo"], workDir)
config_writer = repo.config_writer()
config_writer.add_section("user")
config_writer.set_value("user", "name", data["user"])
config_writer.set_value("user", "email", data["email"])
code = 1
except Exception, e:
json = str(e)
if os.path.exists(workDir):
shutil.rmtree(workDir)
return jsonify(code=code, result=json)
def gitStatus(project):
code = 0
json = ""
try:
repo = Repo(project)
git = repo.git
json = git.status().replace('#', '')
branch = git.branch().replace(' ', '').split('\n')
isdirty = repo.is_dirty(untracked_files=True)
code = 1
except Exception, e:
json = str(e)
return jsonify(code=code, result=json, branch=branch, dirty=isdirty)
def switchBranch(project, name):
code = 0
json = ""
try:
repo = Repo(project)
branches = repo.branches
current_branch = repo.active_branch.name
if name == current_branch:
json = "This is already your active branch for this project"
else:
branch = none
for b in branches:
if b.name == name:
branch = b
if branch != none:
repo.heads.master.checkout()
repo.heads.branch.checkout()
code = 1
else:
code = 0
json = "Error: Can not found branch '" + name + "'"
except Exception, e:
json = str(e)
return jsonify(code=code, result=json)
\ No newline at end of file
define(function(a,b,c){a("pilot/browser_focus"),a("pilot/dom"),a("pilot/event"),a("pilot/event_emitter"),a("pilot/fixoldbrowsers"),a("pilot/keys"),a("pilot/lang"),a("pilot/oop"),a("pilot/useragent"),a("pilot/canon")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/browser_focus' is deprecated. Use 'ace/lib/browser_focus' instead"),c.exports=a("ace/lib/browser_focus")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/dom' is deprecated. Use 'ace/lib/dom' instead"),c.exports=a("ace/lib/dom")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/event' is deprecated. Use 'ace/lib/event' instead"),c.exports=a("ace/lib/event")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/event_emitter' is deprecated. Use 'ace/lib/event_emitter' instead"),c.exports=a("ace/lib/event_emitter")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/fixoldbrowsers' is deprecated. Use 'ace/lib/fixoldbrowsers' instead"),c.exports=a("ace/lib/fixoldbrowsers")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/keys' is deprecated. Use 'ace/lib/keys' instead"),c.exports=a("ace/lib/keys")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/lang' is deprecated. Use 'ace/lib/lang' instead"),c.exports=a("ace/lib/lang")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/oop' is deprecated. Use 'ace/lib/oop' instead"),c.exports=a("ace/lib/oop")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/useragent' is deprecated. Use 'ace/lib/useragent' instead"),c.exports=a("ace/lib/useragent")}),define(function(a,b,c){console.warn("DEPRECATED: 'pilot/canon' is deprecated."),b.addCommand=function(){console.warn("DEPRECATED: 'canon.addCommand()' is deprecated. Use 'editor.commands.addCommand(command)' instead."),console.trace()},b.removeCommand=function(){console.warn("DEPRECATED: 'canon.removeCommand()' is deprecated. Use 'editor.commands.removeCommand(command)' instead."),console.trace()}})
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
define("ace/keyboard/keybinding/emacs",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f={start:[{key:"ctrl-x",then:"c-x"},{regex:["(?:command-([0-9]*))*","(down|ctrl-n)"],exec:"golinedown",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(right|ctrl-f)"],exec:"gotoright",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(up|ctrl-p)"],exec:"golineup",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(left|ctrl-b)"],exec:"gotoleft",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{comment:"This binding matches all printable characters except numbers as long as they are no numbers and print them n times.",regex:["(?:command-([0-9]*))","([^0-9]+)*"],match:e,exec:"inserttext",params:[{name:"times",match:1,type:"number",defaultValue:"1"},{name:"text",match:2}]},{comment:"This binding matches numbers as long as there is no meta_number in the buffer.",regex:["(command-[0-9]*)*","([0-9]+)"],match:e,disallowMatches:[1],exec:"inserttext",params:[{name:"text",match:2,type:"text"}]},{regex:["command-([0-9]*)","(command-[0-9]|[0-9])"],comment:"Stops execution if the regex /meta_[0-9]+/ matches to avoid resetting the buffer."}],"c-x":[{key:"ctrl-g",then:"start"},{key:"ctrl-s",exec:"save",then:"start"}]};b.Emacs=new d(f)}),define("ace/keyboard/state_handler",["require","exports","module"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp("^"+a.key+"$"):Array.isArray(a.regex)?("key"in a||(a.key=new RegExp("^"+a.regex[1]+"$")),a.regex=new RegExp(a.regex.join("")+"$")):a.regex&&(a.regex=new RegExp(a.regex+"$"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state="start",a.buffer="";var e=[];b&1&&e.push("ctrl"),b&8&&e.push("command"),b&2&&e.push("option"),b&4&&e.push("shift"),c&&e.push(c);var f=e.join("-"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type==="number"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=""}return i.then&&(a.state=i.then,a.buffer=""),h.command==null&&(h.command="null"),d&&console.log("KeyboardStateMapper#find",i),!0}),h.command?h:(a.buffer="",!1)},handleKeyboard:function(a,b,c,e,f){if(b==0||c!=""&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log("KeyboardStateMapper#match",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e})
\ No newline at end of file
define("ace/keyboard/keybinding/vim",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f=function(a,b,c){return{regex:["([0-9]*)",a],exec:b,params:[{name:"times",match:1,type:"number",defaultValue:1}],then:c}},g={start:[{key:"i",then:"insertMode"},{key:"d",then:"deleteMode"},{key:"a",exec:"gotoright",then:"insertMode"},{key:"shift-i",exec:"gotolinestart",then:"insertMode"},{key:"shift-a",exec:"gotolineend",then:"insertMode"},{key:"shift-c",exec:"removetolineend",then:"insertMode"},{key:"shift-r",exec:"overwrite",then:"replaceMode"},f("(k|up)","golineup"),f("(j|down)","golinedown"),f("(l|right)","gotoright"),f("(h|left)","gotoleft"),{key:"shift-g",exec:"gotoend"},f("b","gotowordleft"),f("e","gotowordright"),f("x","del"),f("shift-x","backspace"),f("shift-d","removetolineend"),f("u","undo"),{comment:"Catch some keyboard input to stop it here",match:e}],insertMode:[{key:"esc",then:"start"}],replaceMode:[{key:"esc",exec:"overwrite",then:"start"}],deleteMode:[{key:"d",exec:"removeline",then:"start"}]};b.Vim=new d(g)}),define("ace/keyboard/state_handler",["require","exports","module"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp("^"+a.key+"$"):Array.isArray(a.regex)?("key"in a||(a.key=new RegExp("^"+a.regex[1]+"$")),a.regex=new RegExp(a.regex.join("")+"$")):a.regex&&(a.regex=new RegExp(a.regex+"$"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state="start",a.buffer="";var e=[];b&1&&e.push("ctrl"),b&8&&e.push("command"),b&2&&e.push("option"),b&4&&e.push("shift"),c&&e.push(c);var f=e.join("-"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type==="number"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=""}return i.then&&(a.state=i.then,a.buffer=""),h.command==null&&(h.command="null"),d&&console.log("KeyboardStateMapper#find",i),!0}),h.command?h:(a.buffer="",!1)},handleKeyboard:function(a,b,c,e,f){if(b==0||c!=""&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log("KeyboardStateMapper#match",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e})
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/python","ace/range"],function(a,b,c){var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./python_highlight_rules").PythonHighlightRules,h=a("./folding/python").FoldMode,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.foldingRules=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d};var a={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(b,c,d){if(d!=="\r\n"&&d!=="\r"&&d!=="\n")return!1;var e=this.$tokenizer.getLineTokens(c.trim(),b).tokens;if(!e)return!1;do var f=e.pop();while(f&&(f.type=="comment"||f.type=="text"&&f.value.match(/^\s+$/)));return f?f.type=="keyword"&&a[f.value]:!1},this.autoOutdent=function(a,b,c){c+=1;var d=this.$getIndent(b.getLine(c)),e=b.getTabString();d.slice(-e.length)==e&&b.remove(new i(c,d.length-e.length,c,d.length))}}.call(j.prototype),b.Mode=j}),define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield".split("|")),b=e.arrayToMap("True|False|None|NotImplemented|Ellipsis|__debug__".split("|")),c=e.arrayToMap("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern".split("|")),d=e.arrayToMap("".split("|")),f="(?:r|u|ur|R|U|UR|Ur|uR)?",g="(?:(?:[1-9]\\d*)|(?:0))",h="(?:0[oO]?[0-7]+)",i="(?:0[xX][\\dA-Fa-f]+)",j="(?:0[bB][01]+)",k="(?:"+g+"|"+h+"|"+i+"|"+j+")",l="(?:[eE][+-]?\\d+)",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:(?:"+o+"|"+n+")"+l+")",q="(?:"+p+"|"+o+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:f+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",merge:!0,regex:f+'"{3}.*$',next:"qqstring"},{token:"string",regex:f+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:f+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",merge:!0,regex:f+"'{3}.*$",next:"qstring"},{token:"string",regex:f+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+q+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:q},{token:"constant.numeric",regex:k+"[lL]\\b"},{token:"constant.numeric",regex:k+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"invalid.illegal":c.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PythonHighlightRules=g}),define("ace/mode/folding/python",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(){};d.inherits(f,e),function(){this.foldingStartMarker=/\:(:?\s*)?(:?#.*)?$/,this.getFoldWidgetRange=e.prototype.indentationBlock}.call(f.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.FOO=12,this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){return this.foldingStartMarker?this.foldingStopMarker?(e.prototype.getFoldWidget=this.$testBoth,this.$testBoth(a,b,c)):(e.prototype.getFoldWidget=this.$testStart,this.$testStart(a,b,c)):""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=c,g=c,h=a.getLine(c),i=h.length-1,j=h.match(e)[0].length;while(h=a.getLine(++c)){var k=h.match(e)[0].length;if(k==h.length)continue;if(k<=j)break;g=c}if(g>f){var l=a.getLine(g).length;return new d(f,i,g,l)}},this.$testStart=function(a,b,c){return this.foldingStartMarker.test(a.getLine(c))?"start":""},this.$testBoth=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker.test(d)?"end":""}})).call(e.prototype)})
\ No newline at end of file
define("ace/theme/crimson_editor",["require","exports","module"],function(a,b,c){b.isDark=!1,b.cssText=".ace-crimson-editor .ace_editor { border: 2px solid rgb(159, 159, 159);}.ace-crimson-editor .ace_editor.ace_focus { border: 2px solid #327fbd;}.ace-crimson-editor .ace_gutter { width: 50px; background: #e8e8e8; color: #333; overflow : hidden;}.ace-crimson-editor .ace_gutter-layer { width: 100%; text-align: right;}.ace-crimson-editor .ace_gutter-layer .ace_gutter-cell { padding-right: 6px;}.ace-crimson-editor .ace_print_margin { width: 1px; background: #e8e8e8;}.ace-crimson-editor .ace_text-layer { cursor: text; color: rgb(64, 64, 64);}.ace-crimson-editor .ace_cursor { border-left: 2px solid black;}.ace-crimson-editor .ace_cursor.ace_overwrite { border-left: 0px; border-bottom: 1px solid black;}.ace-crimson-editor .ace_line .ace_invisible { color: rgb(191, 191, 191);}.ace-crimson-editor .ace_line .ace_identifier { color: black;}.ace-crimson-editor .ace_line .ace_keyword { color: blue;}.ace-crimson-editor .ace_line .ace_constant.ace_buildin { color: rgb(88, 72, 246);}.ace-crimson-editor .ace_line .ace_constant.ace_language { color: rgb(255, 156, 0);}.ace-crimson-editor .ace_line .ace_constant.ace_library { color: rgb(6, 150, 14);}.ace-crimson-editor .ace_line .ace_invalid { text-decoration: line-through; color: rgb(224, 0, 0);}.ace-crimson-editor .ace_line .ace_fold { background-color: rgba(228, 228, 228, 0.5);}.ace-crimson-editor .ace_line .ace_support.ace_function { color: rgb(192, 0, 0);}.ace-crimson-editor .ace_line .ace_support.ace_constant { color: rgb(6, 150, 14);}.ace-crimson-editor .ace_line .ace_support.ace_type,.ace-crimson-editor .ace_line .ace_support.ace_class { color: rgb(109, 121, 222);}.ace-crimson-editor .ace_line .ace_keyword.ace_operator { color: rgb(49, 132, 149);}.ace-crimson-editor .ace_line .ace_string { color: rgb(128, 0, 128);}.ace-crimson-editor .ace_line .ace_comment { color: rgb(76, 136, 107);}.ace-crimson-editor .ace_line .ace_comment.ace_doc { color: rgb(0, 102, 255);}.ace-crimson-editor .ace_line .ace_comment.ace_doc.ace_tag { color: rgb(128, 159, 191);}.ace-crimson-editor .ace_line .ace_constant.ace_numeric { color: rgb(0, 0, 64);}.ace-crimson-editor .ace_line .ace_variable { color: rgb(0, 64, 128);}.ace-crimson-editor .ace_line .ace_xml_pe { color: rgb(104, 104, 91);}.ace-crimson-editor .ace_marker-layer .ace_selection { background: rgb(181, 213, 255);}.ace-crimson-editor .ace_marker-layer .ace_step { background: rgb(252, 255, 0);}.ace-crimson-editor .ace_marker-layer .ace_stack { background: rgb(164, 229, 101);}.ace-crimson-editor .ace_marker-layer .ace_bracket { margin: -1px 0 0 -1px; border: 1px solid rgb(192, 192, 192);}.ace-crimson-editor .ace_marker-layer .ace_active_line { background: rgb(232, 242, 254);}.ace-crimson-editor .ace_meta.ace_tag { color:rgb(28, 2, 255);}.ace-crimson-editor .ace_marker-layer .ace_selected_word { background: rgb(250, 250, 255); border: 1px solid rgb(200, 200, 250);}.ace-crimson-editor .ace_string.ace_regex { color: rgb(192, 0, 192);}",b.cssClass="ace-crimson-editor";var d=a("../lib/dom");d.importCssString(b.cssText)})
\ No newline at end of file
[Dolphin]
ShowPreview=true
Timestamp=2012,1,11,18,9,34
Version=2
UL.jqueryFileTree {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12px;
line-height: 20px;
padding: 0px;
margin: 0px;
}
UL.jqueryFileTree LI {
list-style: none;
padding: 0px;
padding-left: 22px;
margin: 0px;
white-space: nowrap;
}
UL.jqueryFileTree A {
color: #333;
text-decoration: none;
display: block;
padding: 0px 2px;
}
UL.jqueryFileTree A:hover {
background: #BDF;
}
/* Core Styles */
.jqueryFileTree LI.directory { background: url(images/directory.png) left top no-repeat; }
.jqueryFileTree LI.expanded { background: url(images/folder_open.png) left top no-repeat; }
.jqueryFileTree LI.file { background: url(images/file.png) left top no-repeat; }
.jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; }
/* File Extensions*/
.jqueryFileTree LI.ext_3gp { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_afp { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_afpa { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_asp { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_aspx { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_avi { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_bat { background: url(images/application.png) left top no-repeat; }
.jqueryFileTree LI.ext_bmp { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_c { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_cfg { background: url(images/cfg.png) left top no-repeat; }
.jqueryFileTree LI.ext_cfm { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_cgi { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_com { background: url(images/application.png) left top no-repeat; }
.jqueryFileTree LI.ext_cpp { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_css { background: url(images/css.png) left top no-repeat; }
.jqueryFileTree LI.ext_doc { background: url(images/doc.png) left top no-repeat; }
.jqueryFileTree LI.ext_exe { background: url(images/application.png) left top no-repeat; }
.jqueryFileTree LI.ext_gif { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_fla { background: url(images/flash.png) left top no-repeat; }
.jqueryFileTree LI.ext_h { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_htm { background: url(images/html.png) left top no-repeat; }
.jqueryFileTree LI.ext_html { background: url(images/html.png) left top no-repeat; }
.jqueryFileTree LI.ext_jar { background: url(images/java.png) left top no-repeat; }
.jqueryFileTree LI.ext_jpg { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_jpeg { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_js { background: url(images/script.png) left top no-repeat; }
.jqueryFileTree LI.ext_lasso { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_log { background: url(images/txt.png) left top no-repeat; }
.jqueryFileTree LI.ext_m4p { background: url(images/music.png) left top no-repeat; }
.jqueryFileTree LI.ext_mov { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_mp3 { background: url(images/music.png) left top no-repeat; }
.jqueryFileTree LI.ext_mp4 { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_mpg { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_mpeg { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_ogg { background: url(images/music.png) left top no-repeat; }
.jqueryFileTree LI.ext_pcx { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_pdf { background: url(images/pdf.png) left top no-repeat; }
.jqueryFileTree LI.ext_php { background: url(images/php.png) left top no-repeat; }
.jqueryFileTree LI.ext_png { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_ppt { background: url(images/ppt.png) left top no-repeat; }
.jqueryFileTree LI.ext_psd { background: url(images/psd.png) left top no-repeat; }
.jqueryFileTree LI.ext_pl { background: url(images/script.png) left top no-repeat; }
.jqueryFileTree LI.ext_py { background: url(images/script.png) left top no-repeat; }
.jqueryFileTree LI.ext_rb { background: url(images/ruby.png) left top no-repeat; }
.jqueryFileTree LI.ext_rbx { background: url(images/ruby.png) left top no-repeat; }
.jqueryFileTree LI.ext_rhtml { background: url(images/ruby.png) left top no-repeat; }
.jqueryFileTree LI.ext_rpm { background: url(images/linux.png) left top no-repeat; }
.jqueryFileTree LI.ext_ruby { background: url(images/ruby.png) left top no-repeat; }
.jqueryFileTree LI.ext_sql { background: url(images/db.png) left top no-repeat; }
.jqueryFileTree LI.ext_swf { background: url(images/flash.png) left top no-repeat; }
.jqueryFileTree LI.ext_tif { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_tiff { background: url(images/picture.png) left top no-repeat; }
.jqueryFileTree LI.ext_txt { background: url(images/txt.png) left top no-repeat; }
.jqueryFileTree LI.ext_vb { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_wav { background: url(images/music.png) left top no-repeat; }
.jqueryFileTree LI.ext_wmv { background: url(images/film.png) left top no-repeat; }
.jqueryFileTree LI.ext_xls { background: url(images/xls.png) left top no-repeat; }
.jqueryFileTree LI.ext_xml { background: url(images/code.png) left top no-repeat; }
.jqueryFileTree LI.ext_zip { background: url(images/zip.png) left top no-repeat; }
\ No newline at end of file
*
{
margin: 0px;
padding: 0px;
}
a{
color: #4DA0C6;
}
a:hover {
text-decoration: none;
color: #000;
}
table {
margin: 0;
border: 1px solid #0271BF;
border-right: none;
border-bottom: none;
}
td{
padding: 5px;
border: none;
border-bottom: 1px solid #0271BF;
border-right: 1px solid #0271BF;
}
th{
background: #D0D0D0;
padding: 5px;
border: none;
border-bottom: 1px solid #0271BF;
border-right: 1px solid #0271BF;
}
textarea {
width:762px;
}
body {
background: #0271BF;
font: 13px 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #000000;
}
#page
{
margin: 5px auto;
width: 841px;
}
#logo{
margin-left:60px;
}
#header{
height: 78px;
padding-top: 15px;
width: 847px;
background: url(../images/head.png) no-repeat;
}
.block_header{
text-align: left;
padding-left: 25px;
height: 30px;
}
#header .text{
font-weight: bold;
font-size: 14px;
padding-top: 6px;
margin-left: 5px;
float: left;
}
#header .info{
font-size: 16px;
font-weight: normal;
padding-top: 3px;
float: left;
width: 700px;
height: 22px;
text-align: center;
color: #4c6172;
text-shadow: 0 1px 1px #fff;
overflow: hidden;
}
#header .line{
width:1px;
border-left: 1px solid #678DAD;
background: #CAD4DC;
height: 24px;
float: left;
margin-top: 2px;
margin-right: 5px;
margin-left:5px
}
#editor {
margin: 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.wmenu{
}
.wmenu ul{
list-style:none;
margin:0;
margin-top:1px;
padding:0;
margin-left:20px;
height: 36px;
}
.space{
margin-left: 18px;
}
.wmenu li{
float:left;
background: url(../images/sep.png) left center no-repeat;
}
.wmenu li .title_software{
float:left;
background: url(../images/software.png) left center no-repeat;
font-size:15px;
font-weight:bold;
color:#678dad;
cursor: default;
padding:8px;
padding-left: 20px;
padding-right: 5px;
margin-left:4px;
height: 20px;
text-shadow:1px 1px 0 #E6EDF2;
}
.wmenu li .title_instance{
float:left;
background: url(../images/settings2.png) left center no-repeat;
font-size:15px;
font-weight:bold;
color:#678dad;
cursor: default;
padding:8px;
padding-left: 20px;
padding-right: 5px;
height: 20px;
margin-left:2px;
text-shadow:1px 1px 0 #E6EDF2;
}
.wmenu ul li a{
display:block;
height: 20px;
Color:#000;
font-size:14px;
text-decoration:none;
padding:8px;
padding-left: 6px;
}
.wmenu ul li a:focus, .wmenu ul li a:hover, .wmenu ul li a.active{
color:#0271BF;
background:url(../images/menu_hover.png) bottom repeat-x;
}
#main
{
background: url(../images/main_bg_all.png) repeat-y;
padding-left: 24px;
padding-right: 24px;
min-height: 400px;
}
.main_content{
position:relative;
width: 100%;
height: 430px;
margin-top:10px;
border:1px solid #4c6172;
overflow:auto;
}
.main_head{
height: 15px;
background: url(../images/main_top.png) no-repeat;
width: 794px;
}
.content{
background: url(../images/content.png) repeat-y;
width: 764px;
padding: 15px;
padding-top:0;
padding-bottom:0;
min-height: 400px;
}
.content h2{
color: #4c6172;
font-weight: normal;
font-size: 18px;
}
.main_foot{
height: 15px;
background: url(../images/main_bottom.png) no-repeat;
width: 794px;
}
#footer{
height: 35px;
width: 767px;
background: url(../images/footer_bg.png) no-repeat;
padding-left: 40px;
padding-right: 40px;
padding-top: 5px;
text-align: center;
color: #4c6172;
text-shadow: 0px 1px 1px #fff;
}
.button {
padding: 5px 10px;
display: inline;
background: #eee;
border: none;
color: #000;
cursor: pointer;
font-weight: bold;
border:1px solid #000;
margin-top:10px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
}
.button:hover {
background-position: 0 center;
background: #666666;
color: #fff;
box-shadow: 1px 1px 1px #888888;
}
.button:active {
background-position: 0 top;
position: relative;
top: 1px;
padding: 6px 10px 4px;
box-shadow: 1px 1px 1px #888888;
}
.focusField{
border:solid 1px #73A6FF;
background:#EFF5FF;
color:#000;
padding:5px;
outline:none;
}
.idleField{
background:#fff;
color: #6F6F6F;
border: solid 1px #678dad;
padding:5px;
outline:none;
}
.flash{
margin-left:20px;
color:#4A131F;
font-style:italic;
font-size:14px;
position:relative;
}
.flashes{
margin-bottom:10px;
}
.message {
color:#FF5500;
line-height:21px;
}
.clear{
clear: both;
height:1px;
}
.home_content{
padding: 15px;
}
#home_box{
background: none;
border: 1px solid #678dad;
padding: 0;
height: 405px;
color: #4c6172;
margin: 15px;
}
#home_box a{
color: #4c6172;
cursor: pointer;
text-decoration: none;
}
#home_box a:hover{
text-decoration: underline;
}
#home_box h2{
font-weight: normal;
font-size: 23px;
color: #4c6172;
}
#home_box p{
font-size: 13px;
float: left;
}
#home_box img{
border: none;
float: left;
margin-left: 10px;
}
.inner_box{
background: none;
margin: 0;
border: 1px solid #CAD4DC;
display: block;
padding: 15px;
height: 373px;
}
.inner_box p{
font-size: 13px;
float: left;
width: 400px;
cursor:default;
}
.lmenu{
display: block;
height: 80px;
margin: 10px;
margin-left: 80px;
padding: 15px;
border: #678dad;
width: 500px;
border: 1px solid #678dad;
}
.lmenu:hover, .smenu:hover, .sright_menu:hover{
background: #96b9d7;
}
.smenu{
display: block;
height: 80px;
margin-left: 80px;
margin-right: 10px;
padding: 15px;
border: #678dad;
width: 230px;
border: 1px solid #678dad;
float: left;
}
.sright_menu{
display: block;
height: 80px;
padding: 15px;
border: #678dad;
width: 227px;
border: 1px solid #678dad;
float: left;
}
.sright_menu p, .smenu p{
font-size: 13px;
float: left;
width: 150px;
cursor:default;
}
.file_tree {
width: 752px;
height: 300px;
border: solid 1px #678dad;
background: #fff;
overflow: auto;
padding: 5px;
}
.file_tree_short{
width: 352px;
height: 100px;
border: solid 1px #678dad;
background: #fff;
overflow: auto;
padding: 5px;
float:left;
}
.box_software{
width: 382px;
height: 100px;
background: #fff;
padding: 5px;
float:right;
}
#contentInfo{
width: 752px;
border: solid 1px #678dad;
background: #fff;
overflow: auto;
padding: 5px;
}
#contentInfo p{
font-size: 14px;
margin: 5px;
}
.log_content{
border: solid 1px #4c6172;
padding: 2px;
}
.log {
border: none;
background: #f6f7f8;
color: #000;
width: 754px;
padding: 2px;
height: 600px;
}
.waitting{
margin-left: 10px;
display: none;
}
.file_info{
margin-top:10px;
background: #e4e4e4;
padding: 5px 10px 5px;
box-shadow: 1px 1px 1px #888888;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
color: #737373;
font-weight: bold;
text-shadow: 0px 1px #FFF;
margin-bottom: 9px;
font-size: 14px;
cursor:default;
}
#check{
margin-right:5px;
margin-top:2px;
display: none;
float: left;
}
.public_key{
border: 1px solid #678dad;
overflow: auto;
height: 95px;
padding: 5px;
width: 754px;
background:#fff;
margin-bottom: 10px;
color: #3A494F;
font-size: 12px;
}
.div{
border-top: 1px solid #678dad;
height: 1px;
width: 734px;
margin: 10px;
margin-top: 15px;
}
select {
-webkit-appearance: button;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
-webkit-padding-end: 20px;
-webkit-padding-start: 2px;
-webkit-user-select: none;
background: #fff;
border: 1px solid #678dad;
color: #000;
font-size: inherit;
margin: 0;
overflow: hidden;
padding: 4px;
text-overflow: ellipsis;
white-space: nowrap;}
#
# jQuery File Tree
# Python/Django connector script
# By Martin Skou
#
import os
import urllib
def dirlist(request):
r=['<ul class="jqueryFileTree" style="display: none;">']
try:
r=['<ul class="jqueryFileTree" style="display: none;">']
d=urllib.unquote(request.POST.get('dir','c:\\temp'))
for f in os.listdir(d):
ff=os.path.join(d,f)
if os.path.isdir(ff):
r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff,f))
else:
e=os.path.splitext(f)[1][1:] # get .ext and remove dot
r.append('<li class="file ext_%s"><a href="#" rel="%s">%s</a></li>' % (e,ff,f))
r.append('</ul>')
except Exception,e:
r.append('Could not load directory: %s' % str(e))
r.append('</ul>')
return HttpResponse(''.join(r))
\ No newline at end of file
[Dolphin]
ShowPreview=true
Timestamp=2012,1,6,11,14,34
Version=2
slapos/runner/static/images/head.png

2.31 KB | W: | H:

slapos/runner/static/images/head.png

1.27 KB | W: | H:

slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
  • 2-up
  • Swipe
  • Onion skin
This diff is collapsed.
// jQuery File Tree Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 24 March 2008
//
// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
//
// Usage: $('.fileTreeDemo').fileTree( options, callback )
//
// Options: root - root folder to display; default = /
// script - location of the serverside AJAX file to use; default = jqueryFileTree.php
// folderEvent - event to trigger expand/collapse; default = click
// expandSpeed - default = 500 (ms); use -1 for no animation
// collapseSpeed - default = 500 (ms); use -1 for no animation
// expandEasing - easing function to use on expand (optional)
// collapseEasing - easing function to use on collapse (optional)
// multiFolder - whether or not to limit the browser to one subfolder at a time
// loadMessage - Message to display while initial tree loads (can be HTML)
//
// History:
//
// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
// 1.00 - released (24 March 2008)
//
// TERMS OF USE
//
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC.
//
if(jQuery) (function($){
$.extend($.fn, {
fileTree: function(o, h) {
// Defaults
if( !o ) var o = {};
if( o.root == undefined ) o.root = '/';
if( o.script == undefined ) o.script = 'jqueryFileTree.php';
if( o.folderEvent == undefined ) o.folderEvent = 'click';
if( o.expandSpeed == undefined ) o.expandSpeed= 500;
if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
if( o.expandEasing == undefined ) o.expandEasing = null;
if( o.collapseEasing == undefined ) o.collapseEasing = null;
if( o.multiFolder == undefined ) o.multiFolder = true;
if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';
if( o.selectFolder == undefined ) o.selectFolder = false;
$(this).each( function() {
function showTree(c, t) {
$(c).addClass('wait');
$(".jqueryFileTree.start").remove();
$.post(o.script, { dir: t }, function(data) {
$(c).find('.start').html('');
$(c).removeClass('wait').append(data.result);
if( o.root == t ) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
bindTree(c);
});
}
function bindTree(t) {
$(t).find('LI A').bind(o.folderEvent, function() {
if( $(this).parent().hasClass('directory') ) {
if( $(this).parent().hasClass('collapsed') ) {
// Expand
if( !o.multiFolder ) {
$(this).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
}
$(this).parent().find('UL').remove(); // cleanup
showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) );
$(this).parent().removeClass('collapsed').addClass('expanded');
} else {
// Collapse
$(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().removeClass('expanded').addClass('collapsed');
}
if(o.selectFolder){
h($(this).attr('rel'));
}
} else {
h($(this).attr('rel'));
}
return false;
});
// Prevent A from triggering the # on non-click events
if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
}
// Loading message
$(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
// Get the initial file list
showTree( $(this), escape(o.root) );
});
}
});
})(jQuery);
\ No newline at end of file
$(document).ready( function() {
var send = false;
var cloneRequest;
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
selectFile(file);
});
$("#clone").click(function(){
if(send){
cloneRequest.abort();
$("#imgwaitting").fadeOut('normal');
$("#clone").empty();
$("#clone").append("Clone");
send = false;
return;
}
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#flash").fadeIn('normal');
repo_url = $("input#repo").val();
/* /^(ht|f)tps?:\/\/[a-z0-9-\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?$/ */
if($("input#repo").val() == "" || !repo_url.match(/^[\w\d\.\/:~@_-]+$/)){
$("#flash").append("<ul class='flashes'><li>Error: Invalid url for the repository</li></ul>");
return false;
}
if($("input#name").val() == "" || !$("input#name").val().match(/^[\w\d\._-]+$/)){
$("#flash").append("<ul class='flashes'><li>Error: Invalid project name</li></ul>");
return false;
}
if($("input#user").val() == "" || $("input#user").val() == "Enter your name..."){
$("#flash").append("<ul class='flashes'><li>Error: Please enter your name!</li></ul>");
return false;
}
if($("input#email").val() == "" || !$("input#email").val().match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)){
$("#flash").append("<ul class='flashes'><li>Error: Please enter your email adress!</li></ul>");
return false;
}
$("#imgwaitting").fadeIn('normal');
$("#clone").empty();
$("#clone").append("Stop");
send = true;
cloneRequest = $.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/cloneRepository',
data: "repo=" + repo_url + "&name=" + $("input#name").val() + "&email=" + $("input#email").val() +
"&user=" + $("input#user").val(),
success: function(data){
if(data.code == 1){
$("#file_navigation").fadeIn('normal');
$("#flash").append("<ul class='flashes'><li>Repository is cloned!</li></ul>");
$("input#repo").val("Enter the url of your repository...");
$("input#name").val("Enter the project name...");
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
selectFile(file);
});
}
else{
$("#flash").append("<ul class='flashes'><li>Error: " + data.result + "</li></ul>");
}
$("#imgwaitting").hide()
$("#clone").empty();
$("#clone").append("Clone");
send = false;
}
});
return false;
});
function selectFile(file){
//nothing
return;
}
});
\ No newline at end of file
$(document).ready( function() {
var method = $("input#method").val();
var workdir = $("input#workdir").val();
if (method != "file"){
script = (method == "new") ? "/openFolder" : "/readFolder";
$('#fileTree').fileTree({ root: workdir, script: $SCRIPT_ROOT + script, folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
});
}
$("input#subfolder").val("");
$("#create").click(function(){
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#flash").fadeIn('normal');
repo_url = $("input#software").val();
if($("input#software").val() == "" || !$("input#software").val().match(/^[\w\d._-]+$/)){
$("#flash").append("<ul class='flashes'><li>Error: Invalid Software name</li></ul>");
return false;
}
if($("input#subfolder").val() == ""){
$("#flash").append("<ul class='flashes'><li>Error: Select the parent folder of your software!</li></ul>");
return false;
}
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/createSoftware',
data: "folder=" + $("input#subfolder").val() + $("input#software").val(),
success: function(data){
if(data.code == 1){
location.href = $SCRIPT_ROOT + '/editSoftwareProfile'
}
else{
$("#flash").append("<ul class='flashes'><li>Error: " + data.result + "</li></ul>");
}
}
});
return false;
});
$("#open").click(function(){
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#flash").fadeIn('normal');
if($("input#path").val() == ""){
$("#flash").append("<ul class='flashes'><li>Error: Select the folder of your software</li></ul>");
return false;
}
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/setCurentProject',
data: "path=" + $("input#path").val(),
success: function(data){
if(data.code == 1){
location.href = $SCRIPT_ROOT + '/editSoftwareProfile'
}
else{
$("#flash").append("<ul class='flashes'><li>Error: " + data.result + "</li></ul>");
}
}
});
return false;
});
function selectFile(file){
relativeFile = file.replace(workdir, "");
$("#info").empty();
$("#info").append("Selection: " + relativeFile);
$("input#subfolder").val(file);
path = "";
if(method == "open"){
checkFolder(file);
}
return;
}
function checkFolder(path){
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/checkFolder',
data: "path=" + path,
success: function(data){
var path = data.result;
$("input#path").val(path);
if (path != ""){
$("#check").fadeIn('normal');
}
else{
$("#check").hide();
}
}
});
return "";
}
});
\ No newline at end of file
$(document).ready( function() {
var send = false;
gitStatus();
$("#project").change(function(){
if (send){
getStatus.abort();
send=false;
}
gitStatus();
});
$("#activebranch").change(function(){
});
$("#addbranch").click(function(){
if($("input#branchname").val() == "" ||
$("input#branchname").val() == "Enter the branch name..."){
error("Error: Please Enter your branch name");
return false;
}
alert($("input#branchname").val());
return false;
});
$("#commit").click(function(){
if($("input#commitmsg").val() == "" ||
$("input#commitmsg").val() == "Enter message..."){
error("Error: Please Enter the commit message");
return false;
}
alert($("input#commitmsg").val());
return false;
});
function gitStatus(){
var project = $("#project").val();
$("#status").empty();
$("#push").hide();
$("#flash").empty();
if (project == ""){
$("#status").append("<h2>Please select one project...</h2><br/><br/>");
$("#branchlist").hide();
return;
}
send = true;
getStatus = $.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/getProjectStatus',
data: "project=" + $("input#workdir").val() + "/" + project,
success: function(data){
if(data.code == 1){
$("#branchlist").show();
$("#status").append("<h2>Your Repository status</h2>");
message = data.result.split('\n').join('<br/>');
//alert(message);
$("#status").append("<p>" + message + "</p>");
loadBranch(data.branch);
if(data.dirty){
$("#push").show();
}
}
else{
$("#flash").append("<ul class='flashes'><li>Error: " + data.result + "</li></ul>");
}
}
});
}
function loadBranch(branch){
$("#activebranch").empty();
for(i=0; i< branch.length; i++){
selected = (branch[i].indexOf('*') == 0)? "selected":"";
$("#activebranch").append("<option value='" + branch[i] +
"'>" + branch[i] + "</option>");
}
}
function error(msg){
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#flash").fadeIn('normal');
$("#flash").append("<ul class='flashes'><li>" + msg + "</li></ul>");
}
});
\ No newline at end of file
$(document).ready( function() {
var editor = ace.edit("editor");
editor.setTheme("ace/theme/crimson_editor");
var CurentMode = require("ace/mode/text").Mode;
editor.getSession().setMode(new CurentMode());
editor.getSession().setTabSize(2);
editor.getSession().setUseSoftTabs(true);
editor.renderer.setHScrollBarAlwaysVisible(false);
var script = "/readFolder";
var Mode = function(name, desc, clazz, extensions) {
this.name = name;
this.desc = desc;
this.clazz = clazz;
this.mode = new clazz();
this.mode.name = name;
this.extRe = new RegExp("^.*\\.(" + extensions.join("|") + ")$");
};
var modes = [
new Mode("php", "PHP",require("ace/mode/php").Mode, ["php", "in", "inc"]),
new Mode("python", "Python", require("ace/mode/python").Mode, ["py"]),
new Mode("buildout", "Python Buildout config", require("ace/mode/buildout").Mode, ["cfg"])
];
var projectDir = $("input#project").val();
var send = false;
var edit = false;
var workdir = $("input#workdir").val();
$('#fileTree').fileTree({ root: projectDir, script: $SCRIPT_ROOT + script, folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
});
$("#add").click(function(){
var path = $("input#project").val();
if (send) return false;
if($("input#file").val() == "" ||
$("input#file").val() == "Enter name here..."){
error("Error: Please enter your file or folder name");
return false;
}
if($("input#subfolder").val() != ""){
path = $("input#subfolder").val();
}
path = path + "/" + $("input#file").val();
send = true;
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/createFile',
data: "file=" + path + "&type=" + $("#type").val(),
success: function(data){
if(data.code == 1){
$('#fileTree').fileTree({ root: projectDir, script: $SCRIPT_ROOT + script, folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
});
$("input#file").val("");
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#info").empty();
$("#info").append("Please select your file or folder into the box...");
$("input#subfolder").val("");
}
else{
error(data.result);
}
send = false;
}
});
return false;
});
$("#save").click(function(){
if(!edit){
error("Please select the file to edit");
return false;
}
send = false;
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/saveFileContent',
data: "file=" + $("input#subfolder").val() + "&content=" + editor.getSession().getValue(),
success: function(data){
if(data.code == 1){
$("#flash").fadeOut('normal');
$("#flash").empty();
}
else{
error(data.result);
}
send = false;
}
});
return false;
});
function error(msg){
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#flash").fadeIn('normal');
$("#flash").append("<ul class='flashes'><li>" + msg + "</li></ul>");
}
function selectFile(file){
relativeFile = file.replace(projectDir, "");
$("#info").empty();
$("#info").append(relativeFile);
$("input#subfolder").val(file);
path = "";
send = false;
edit = false;
if(file.substr(-1) != "/"){
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/getFileContent',
data: "file=" + file,
success: function(data){
if(data.code == 1){
$("#flash").fadeOut('normal');
$("#flash").empty();
$("#edit_info").empty();
var name = file.split('/');
$("#edit_info").append("Edit selected file (" +
name[name.length - 1] + ")");
editor.getSession().setValue(data.result);
setEditMode(name[name.length - 1]);
edit = true;
}
else{
error(data.result);
}
send = false;
}
});
}
else{
$("#edit_info").empty();
$("#edit_info").append("Edit your selected file");
editor.getSession().setValue("");
}
return;
}
function setEditMode(file){
var CurentMode = require("ace/mode/text").Mode;
editor.getSession().setMode(new CurentMode());
for (var i=0; i< modes.length; i++){
if(modes[i].extRe.test(file)){
editor.getSession().setMode(modes[i].mode);
set = true;
break;
}
}
}
});
\ No newline at end of file
*
{
margin: 0px;
padding: 0px;
}
a:link {
color: #4DA0C6;
}
a:hover {
text-decoration: underline;
color: #FF0000;
}
a:visited {
color: #4DA0C6;
}
textarea {
width:762px;
}
body {
background: #0271BF;
font: 13px Arial, Helvetica, sans-serif;
color: #000000;
}
#page
{
margin: 20px auto;
width: 847px;
}
#logo{
margin-left:60px;
}
#header{
height: 92px;
padding-top: 18px;
width: 847px;
background: url(images/head.png) no-repeat;
}
.block_header{
text-align: left;
padding-left: 25px;
height: 30px;
}
#header .text{
font-weight: bold;
font-size: 14px;
padding-top: 6px;
margin-left: 5px;
float: left;
}
#header .info{
font-weight: bold;
font-size: 14px;
padding-top: 6px;
float: left;
width: 700px;
text-align: center;
}
.wmenu{
}
.wmenu ul{
list-style:none;
margin:0;
padding:0;
margin-left:20px;
height: 35px;
}
.space{
margin-left: 18px;
}
.wmenu li{
float:left;
background: url(images/sep.png) left center no-repeat;
}
.wmenu li .title_software{
float:left;
background: url(images/software.png) left center no-repeat;
font-size:14px;
font-weight:bold;
color:#0271BF;
padding:8px;
padding-left: 20px;
padding-right: 5px;
margin-left:4px;
height: 20px;
text-shadow:1px 1px 0 #F8F8F8;
}
.wmenu li .title_instance{
float:left;
background: url(images/settings2.png) left center no-repeat;
font-size:14px;
font-weight:bold;
color:#0271BF;
padding:8px;
padding-left: 20px;
padding-righclass="title_instance"t: 5px;
height: 20px;
margin-left:2px;
text-shadow:1px 1px 0 #F8F8F8;
}
.wmenu ul li a{
display:block;
height: 20px;
Color:#000;
font-size:14px;
text-decoration:none;
padding:8px;
padding-left: 6px;
}
.wmenu ul li a:focus, .wmenu ul li a:hover, .wmenu ul li a.active{
color:#0271BF;
background:url(images/menu_hover.png) repeat-x;
}
#main
{
min-height: 400px;
background: url(images/main_bg.png) repeat-y;
padding:10px;
padding-left: 40px;
padding-right: 40px;
width: 767px;
}
#main h2{
margin-top:10px;
font-size:14px;
font-weight:bold;
text-decoration: capitalize;
color:#0271BF;
}
#footer{
height: 40px;
width: 767px;
background: url(images/footer.png) no-repeat;
padding-left: 40px;
padding-right: 40px;
padding-top: 25px;
text-align: center;
}
.button {
padding: 5px 10px;
display: inline;
background: #eee;
border: none;
color: #000;
cursor: pointer;
font-weight: bold;
border:1px solid #000;
margin-top:10px;
}
.button:hover {
background-position: 0 center;
background: #666666;
color: #fff;
}
.button:active {
background-position: 0 top;
position: relative;
top: 1px;
padding: 6px 10px 4px;
}
.flash{
margin-left:20px;
color:#FF5500;
font-style:italic;
font-size:14px;
}
.flashes{
margin-bottom:10px;
}
.message {
color:#FF5500;
line-height:21px;
}
.clear{
clear: both;
}
{% extends "layout.html" %}
{% block title %}Adding new repository{% endblock %}
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='scripts/folder.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<div id="repository">
<h2>Clone your repository into the workspace</h2>
<label for='name'>Project name: </label>
<input type="text" name="name" id="name" size='20' value="Enter the project name..." />
<label for='repo'>url: &nbsp;&nbsp;&nbsp;</label>
<input type="text" name="repo" id="repo" size='25' value="Enter the url of your repository..." /><br/>
<label for='user'>Your name: &nbsp;&nbsp;</label>
<input type="text" name="user" id="user" size='20' value="Enter your name..." />
<label for='email'>Email: </label>
<input type="text" name="email" id="email" size='25' value="Enter your email adress..." />
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<button class="button" id="clone">clone</button>
<img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />
<br/><br/>
</div>
<h2>You can use this public key for Git SSH</h2>
<textarea class="public_key" readonly>
{{public_key}}
</textarea>
<p>to use git with https, please enter your repository url like this
<strong><i>https://your_login:your_passeword@your_repository_url</i></strong></p><br/>
<div id="file_navigation">
<h2>Your project folder</h2>
<div id="fileTree" class="file_tree"></div>
</div>
{% endblock %}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}SlapOs buildout web based runner {% endblock %}
{% block body %} {% block body %}
Welcome!<br> <div id="home_box">
<div class="inner_box">
This is SlapOS buildout web based runner. <div class="lmenu">
<h2><a href="{{ url_for('configRepo')}}">Create a new Project from your repository</a></h2>
SlapOS runner is web based development tool which uses slapgrid to install and instantiate the software. <p>Your repository will be cloned into your project folder, you will need the url of the repository.
This allows you to open and edit your local project copy and synchonize content with online repository.
</p>
<img src="{{ url_for('static', filename='images/folder_html.png') }}" />
<div class="clear"></div>
</div>
<div class="smenu">
<h2><a href="{{ url_for('openProject', method='open')}}">Open Existing Project</a></h2>
<p>Once you have cloned your repository, you can open project here.</p>
<img src="{{ url_for('static', filename='images/mydocuments.png') }}" />
<div class="clear"></div>
</div>
<div class="sright_menu">
<h2><a href="{{ url_for('manageProject')}}">Manage your Project</a></h2>
<p>You can view details of your project and commit content here.</p>
<img src="{{ url_for('static', filename='images/manage_repo.png') }}" />
</div>
<div class="clear"></div>
<div class="lmenu">
<h2><a href="{{ url_for('openProject', method='new')}}">Start a new software release</a></h2>
<p>Create a new software into your selected project directory. This allows you to create, edit and run a new software on SlapOs, using webrunner tools.
</p>
<img src="{{ url_for('static', filename='images/folder_blue.png') }}" />
<div class="clear"></div>
</div>
</div>
</div>
{% endblock %} {% endblock %}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}Instance inspection{% endblock %}
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
{%if file_path != "" %}
<script type="text/javascript" charset="utf-8">
$(document).ready( function() {
$('#fileTree').fileTree({ root: "{{file_path}}", script: $SCRIPT_ROOT + "/readFolder", folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: false }, function(file) {
alert(file);
});
});
</script>
{%endif%}
{% endblock %}
{% block body %} {% block body %}
<h2>Instance inspection</h2><br/> <h2>Instance inspection</h2><br/>
<h2>Supervisor:</h2> <h2>Supervisor:</h2>
<textarea cols=103 rows=10 readonly>{{ supervisor }}</textarea><br> {% if supervisor != [] %}
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<th>Partition and Process name</th><th>Status</th><th>Process PID </th><th> UpTime</th><th></th>
</tr>
{% for item in supervisor %}
<tr>
<td><b><a href="{{ url_for('tailProcess', process=item[0]) }}">{{ item[0]}}</a></b></td>
<td align="center"><a href="{{ url_for('startStopProccess', process=item[0], action=item[1]) }}">{{ item[1]}}</a></td>
<td align="center">{{ item[3]}}</td><td>{{ item[5]}}</td>
<td align="center"><a href="{{ url_for('startStopProccess', process=item[0], action='RESTART') }}">Restart</a></td>
</tr>
{% endfor %}
</table>
{% else %}
<h3>Please run the software instance before displaying process</h3>
{%endif%}
<br/>
<h2>SLAP:</h2> <h2>SLAP:</h2>
{% for item in slap_status %} {% for item in slap_status %}
<b>{{ item[0 ]}}</b><br> <b>{{ item[0 ]}}</b><br>
<textarea cols=103 rows=5 readonly>{{ item[1] }}</textarea><br> <textarea cols=103 rows=5 readonly>{{ item[1] }}</textarea><br>
{% endfor %} {% endfor %}
<h2>File content:</h2> <h2>File content:</h2>
<textarea cols=103 rows=40 readonly>{{ file_content }}</textarea><br> <div id="fileTree" class="file_tree"></div>
{% endblock %} {% endblock %}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
{% block head %}
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Buildout runner</title> <title>Buildout runner</title>
...@@ -12,19 +12,66 @@ ...@@ -12,19 +12,66 @@
<meta name="description" content="" /> <meta name="description" content="" />
<link href="{{ url_for('static', filename='styles.css') }}" rel="stylesheet" type="text/css" media="screen" /> <link href="{{ url_for('static', filename='css/styles.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jquery-1.6.2.min.js') }}" type="text/javascript" charset="utf-8"></script>
{% if request.path == '/editSoftwareProfile' or request.path == '/editInstanceProfile' %}
<script src="{{ url_for('static', filename='ace/ace-uncompressed.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/theme-crimson_editor.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/mode-buildout.js') }}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(document).ready(function() {
var editor = ace.edit("editor");
editor.setTheme("ace/theme/crimson_editor");
var CurentMode = require("ace/mode/buildout").Mode;
editor.getSession().setMode(new CurentMode());
editor.getSession().setTabSize(2);
editor.getSession().setUseSoftTabs(true);
editor.renderer.setHScrollBarAlwaysVisible(false);
$('#save').click(function(){
$('#editor_content').val(editor.getSession().getValue());
});
});
</script>
{% endif %}
<script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
<script type="text/javascript">
$(document).ready(function() {
$('input[type="text"]').addClass("idleField");
$('input[type="text"]').focus(function() {
$(this).removeClass("idleField").addClass("focusField");
if (this.value == this.defaultValue){
this.value = '';
}
if(this.value != this.defaultValue){
this.select();
}
});
$('input[type="text"]').blur(function() {
$(this).removeClass("focusField").addClass("idleField");
if ($.trim(this.value) == ''){
this.value = (this.defaultValue ? this.defaultValue : '');
}
});
});
</script>
{% endblock %}
</head> </head>
<body> <body>
<div id="page"> <div id="page">
<div id="logo"> <div id="logo">
<a href="{{ url_for('home') }}"><img src="{{ url_for('static', filename='images/logo.png') }}" alt="" /></a> <a href="{{ url_for('home') }}"><img src="{{ url_for('static', filename='images/logo.png') }}" alt="" /></a>
</div> </div>
<div id="header"> <div id="header">
<div class="block_header"> <div class="block_header">
<a href="{{ url_for('home') }}" style="float:left"><img alt="" src="{{ url_for('static', filename='images/home.png') }}" /></a> <a href="{{ url_for('home') }}" style="float:left;" title="Home"><img alt="" src="{{ url_for('static', filename='images/home.png') }}" /></a>
<h2 class="text"> Home</h2> <div class="line"></div>
<h2 class="info"></h2> <a href="{{ url_for('curentSoftware') }}" style="float:left" title="Current Software Folder"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a>
<div class="line"></div>
<h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2>
</div> </div>
<div class="wmenu"> <div class="wmenu">
<ul> <ul>
...@@ -47,10 +94,10 @@ ...@@ -47,10 +94,10 @@
<div class="clear"></div> <div class="clear"></div>
</div> </div>
<div id="main"> <div id="main">
<div class="flash"> <div class="flash" id="flash">
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<ul class=flashes> <ul class="flashes">
{% for message in messages %} {% for message in messages %}
<li>{{ message }}</li> <li>{{ message }}</li>
{% endfor %} {% endfor %}
...@@ -58,12 +105,22 @@ ...@@ -58,12 +105,22 @@
{% endif %} {% endif %}
{% endwith %} {% endwith %}
</div> </div>
<div {% if request.path == '/' %} class="home_content" {%else%} id="content" {% endif %}>
{% if request.path != '/' %}
<div class="main_head">
</div>
<div class="content"> <div class="content">
{% endif %}
{% block body %}{% endblock %} {% block body %}{% endblock %}
{% if request.path != '/' %}
</div>
<div class="main_foot">
</div>
{% endif %}
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
&copy; Vifib SARL 2011 - All right reserved - Creative Commons Shared Alike Non Commercial SlapOs webrunner &copy; Vifib SARL 2011 - All right reserved - Creative Commons Shared Alike Non Commercial
</div> </div>
</div> </div>
</body> </body>
......
<!doctype html>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://[::1]:9080/piwik/" : "http://[::1]:9080/piwik/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 1);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
</script><noscript><p><img src="http://[::1]:9080/piwik/piwik.php?idsite=1" style="border:0" alt="" /></p></noscript>
<!-- End Piwik Tracking Code -->
<title>Buildout runner</title>
<div class=menu>
<a href="{{ url_for('home') }}">Home</a> |
Software:
<a href="{{ url_for('editSoftwareProfile') }}">Edit</a>
<a href="{{ url_for('runSoftwareProfile') }}">Run</a>
<a href="{{ url_for('viewSoftwareLog') }}">Build log</a>
<a href="{{ url_for('inspectSoftware') }}">Inspect</a>
<a href="{{ url_for('removeSoftware') }}">Remove</a>
|
Instance
<a href="{{ url_for('editInstanceProfile') }}">Edit</a>
<a href="{{ url_for('runInstanceProfile') }}">Run</a>
<a href="{{ url_for('viewInstanceLog') }}">Build log</a>
<a href="{{ url_for('inspectInstance') }}">Inspect</a>
<a href="{{ url_for('stopAllPartition') }}">Stop all</a>
<a href="{{ url_for('removeInstance') }}">Remove</a>
</div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<div class=page>
{% block body %}{% endblock %}
</div>
{% extends "layout.html" %}
{% block title %}Manage your Project folder{% endblock %}
{% block head %}
{{ super() }}
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='scripts/repo.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<form action="" method=post>
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<input type="hidden" name="subfolder" id="subfolder" value="" />
<div id="repoContent">
<h2>Manage your repository</h2>
<label for='project'>Select your project into the list: </label>
<select id="project" name="project">
{% for folder in project%}
<option value="{{folder}}">{{folder}}</option>
{% endfor %}
</select>
<br/><br/>
<div id="contentInfo">
<div id="status">
<h2>Please select one project...</h2>
</div>
<div id="branchlist">
<div class="div"></div>
<h2>Your Repository Branch</h2>
<div style="margin-left:15px;">
<label for='activebranch'>Select the active Branch here: </label>
<select name="activebranch" id="activebranch">
</select>
&nbsp;&nbsp;&nbsp;<label for='branchname'>Branch Name: </label>
<input type="text" name="branchname" id="branchname" size='20' value="Enter the branch name..." />
<input type="submit" name="addbranch" id ="addbranch" value="Add" class="button"/>
</div>
</div>
<div id="push">
<div class="div"></div>
<h2>Commit All your changes</h2>
<div style="margin-left:15px;">
<label for='commitmsg'>Enter your commit message here: </label>
<input type="text" name="commitmsg" id="commitmsg" size='40' value="Enter message..." />
<input type="submit" name="commit" id ="commit" value="Commit" class="button"/>
</div>
</div>
<br/>
</div>
</div>
</form>
{% endblock %}
{% extends "layout.html" %}
{% block body %}
<h2>Displaying log for {{ process }}</h2><br/>
<textarea cols=103 rows=40 readonly>{{ process_log }}</textarea>
{% endblock %}
{% extends "layout.html" %}
{% block title %}{% if method == "new" %}Adding new software{%else%}Open existing project{%endif%}{% endblock %}
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='scripts/project.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<form action="" method=post>
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<input type="hidden" name="subfolder" id="subfolder" value="" />
<input type="hidden" name="method" id="method" value="{{method}}" />
{% if method == "new" %}
<div id="addsoftware">
<h2>What is the name of your software?</h2>
<label for='software'>Name: </label>
<input type="text" name="software" id="software" size='30' value="Enter software name..." />
<br/><br/>
<div id="file_navigation">
<h2>Select the parent directory</h2>
<div id="fileTree" class="file_tree"></div>
<div id="file_info" class="file_info"><span id="info">Please select your parent folder into the box...</span></div>
<br/>
<input type="submit" name="create" id ="create" value="Start Project" class="button"/>
</div>
</div>
{% elif method == "open" %}
<div id="openSoftware">
<h2>Select the folder of your software into the box</h2>
<div id="fileTree" class="file_tree"></div>
<div id="file_info" class="file_info">
<img src="{{ url_for('static', filename='images/check.png') }}" class="check" id="check" alt=""/>
<span id="info">Please select your project folder into the box...</span></div>
<input type="hidden" name="path" id="path" value="" />
<input type="submit" name="open" id ="open" value="Open Software" class="button"/>
</div>
{% endif %}
</form>
{% endblock %}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}Webrunner software content{% endblock %}
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
{%if result != "" %}
<script type="text/javascript" charset="utf-8">
$(document).ready( function() {
$('#fileTree').fileTree({ root: "{{result}}", script: $SCRIPT_ROOT + "/readFolder", folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: false }, function(file) {
alert(file);
});
});
</script>
{%endif%}
{% endblock %}
{% block body %} {% block body %}
<h2>Result for {{ type }}</h2> <h2>Result for {{ type }}</h2>
<textarea cols=103 rows=40 readonly>{{ result }}</textarea> <div id="fileTree" class="file_tree"></div>
{% endblock %} {% endblock %}
{% extends "layout.html" %}
{% block title %}Your current software folder{% endblock %}
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='scripts/softwareFolder.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/ace-uncompressed.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/theme-crimson_editor.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/mode-buildout.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/mode-python.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='ace/mode-php.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<form action="" method=post>
<input type="hidden" name="project" id="project" value="{{project}}" />
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<input type="hidden" name="subfolder" id="subfolder" value="" />
<div id="file_navigation">
<h2>Current software file content</h2>
<div id="fileTree" class="file_tree_short"></div>
<div class="box_software">
<h2>Add new file or folder</h2>
<input type="text" name="file" id="file" size='25' value="Enter name here..." />
&nbsp;&nbsp;<select name="type" id="type">
<option value="file">file</option>
<option value="folder">folder</option>
</select>
&nbsp;&nbsp;<input type="submit" name="add" id ="add" value="Add" class="button"/>
<div id="file_info" class="file_info"><span id="info">Please select your file or folder into the box...</span></div>
</div>
<div class="clear"></div>
<div id="code" style="margin-top:10px">
<h2 id="edit_info">Edit your selected file</h2>
<div class="main_content">
<pre id="editor">
</pre>
</div>
<input type=submit value=Update id="save" class="button">
</div>
</div>
</form>
{% endblock %}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}Update instance profile{% endblock %}
{% block body %} {% block body %}
<form action="{{ url_for('updateInstanceProfile') }}" method=post class=add-entry> <form action="{{ url_for('updateInstanceProfile') }}" method=post class=add-entry>
<dl> <dl>
<dt><h2>Instance Profile:</h2> <dd><h2>Instance Profile:</h2></dd>
<dd><textarea name=content rows=20 cols=103>{{ profile }}</textarea> <dd> <!--<textarea name=content rows=20 cols=103 id="editor">{{ profile }}</textarea>-->
<dd><input type=submit value= Update class="button"> <div class="main_content">
<pre id="editor">
{{ profile }}
</pre>
</div>
<input type="hidden" name=content id="editor_content"/>
</dd>
<dd><input type=submit value=Update id="save" class="button"></dd>
</dl> </dl>
</form> </form>
{% endblock %} {% endblock %}
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}Update software profile{% endblock %}
{% block body %} {% block body %}
<form action="{{ url_for('updateSoftwareProfile') }}" method=post class=add-entry> <form action="{{ url_for('updateSoftwareProfile') }}" method=post class=add-entry>
<dl> <dl>
<dt><strong>Note:</strong> Url of instance.cfg is <tt>{{ instance_url }}</tt> <dt><strong>Note:</strong> Url of instance.cfg is <tt>{{ instance_url }}</tt></dt>
<dt><h2>Software Profile:</h2> <dd><h2>Software Profile:</h2></dd>
<dd><textarea name=content rows=20 cols=103>{{ profile }}</textarea> <dd> <!--<textarea name=content rows=20 cols=103 id="editor">{{ profile }}</textarea>-->
<dd><input type=submit value=Update class="button"> <div class="main_content">
<pre id="editor">
{{ profile }}
</pre>
</div>
<input type="hidden" value="{{ profile }}" name=content id="editor_content"/>
</dd>
<dd><input type=submit value=Update id="save" class="button"></dd>
</dl> </dl>
</form> </form>
{% endblock %} {% endblock %}
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
Currently running: <span class="message">{{ running }}</span><br> Currently running: <span class="message">{{ running }}</span><br>
<strong>Note:</strong> You can refresh this page from time to time to have updates.<br> <strong>Note:</strong> You can refresh this page from time to time to have updates.<br>
<h2>Result for {{ type }}</h2> <h2>Result for {{ type }}</h2>
<textarea cols=103 rows=40 readonly>{{ result }}</textarea> <div class="log_content"><textarea class="log" readonly >{{ result }}</textarea></div>
{% endblock %} {% endblock %}
...@@ -3,6 +3,11 @@ import time ...@@ -3,6 +3,11 @@ import time
import subprocess import subprocess
import os import os
from xml_marshaller import xml_marshaller from xml_marshaller import xml_marshaller
import re
import urllib
from flask import jsonify
import shutil
import string
class Popen(subprocess.Popen): class Popen(subprocess.Popen):
...@@ -21,8 +26,9 @@ def updateProxy(config): ...@@ -21,8 +26,9 @@ def updateProxy(config):
if not os.path.exists(config['instance_root']): if not os.path.exists(config['instance_root']):
os.mkdir(config['instance_root']) os.mkdir(config['instance_root'])
slap = slapos.slap.slap() slap = slapos.slap.slap()
profile = getProfilePath(config['runner_workdir'], config['software_profile'])
slap.initializeConnection(config['master_url']) slap.initializeConnection(config['master_url'])
slap.registerSupply().supply(config['software_profile'], computer_guid=config['computer_id']) slap.registerSupply().supply(profile, computer_guid=config['computer_id'])
computer = slap.registerComputer(config['computer_id']) computer = slap.registerComputer(config['computer_id'])
prefix = 'slappart' prefix = 'slappart'
slap_config = { slap_config = {
...@@ -50,7 +56,7 @@ def updateProxy(config): ...@@ -50,7 +56,7 @@ def updateProxy(config):
}) })
computer.updateConfiguration(xml_marshaller.dumps(slap_config)) computer.updateConfiguration(xml_marshaller.dumps(slap_config))
slap.registerOpenOrder().request(config['software_profile'], slap.registerOpenOrder().request(profile,
partition_reference=partition_reference) partition_reference=partition_reference)
...@@ -159,12 +165,18 @@ def runInstanceWithLock(config): ...@@ -159,12 +165,18 @@ def runInstanceWithLock(config):
return False return False
def getProfile(profile): def getProfile(peojectDir, profileName):
profile = getProfilePath(peojectDir, profileName)
if os.path.exists(profile): if os.path.exists(profile):
return open(profile).read() return open(profile).read()
else: else:
return '' return ''
def getProfilePath(peojectDir, profile):
if not os.path.exists(os.path.join(peojectDir, ".project")):
return ""
projectFolder = open(os.path.join(peojectDir, ".project")).read()
return os.path.join(projectFolder, profile)
def getSlapStatus(config): def getSlapStatus(config):
slap = slapos.slap.slap() slap = slapos.slap.slap()
...@@ -179,9 +191,129 @@ def getSlapStatus(config): ...@@ -179,9 +191,129 @@ def getSlapStatus(config):
pass pass
return partition_list return partition_list
def runBuildoutAnnotate(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-sr.pid')
if not isSoftwareRunning(config):
bin_buildout = os.path.join(config['software_root'], "bin/buildout")
if os.path.exists(bin_buildout):
logfile = open(config['annotate_log'], 'w')
buildout = Popen([bin_buildout, '-vc', config['configuration_file_path'],
"annotate"], stdout=logfile)
buildout.wait()
return True
return False
def svcStopAll(config): def svcStopAll(config):
return Popen([config['supervisor'], config['configuration_file_path'], 'shutdown']).communicate()[0] return Popen([config['supervisor'], config['configuration_file_path'],
'shutdown']).communicate()[0]
def getSvcStatus(config): def getSvcStatus(config):
return Popen([config['supervisor'], config['configuration_file_path'], 'status']).communicate()[0] result = Popen([config['supervisor'], config['configuration_file_path'],
'status']).communicate()[0]
regex = "(^unix:.+\.socket)|(^error:).*$"
supervisord = []
for item in result.split('\n'):
if item != "" and re.search(regex, item) == None:
supervisord.append(re.split('[\s,]+', item))
return supervisord
def getSvcTailProcess(config, process):
return Popen([config['supervisor'], config['configuration_file_path'],
"tail", process]).communicate()[0]
def svcStartStopProcess(config, process, action):
cmd = {"RESTART":"restart", "STOPPED":"start", "RUNNING":"stop"}
return Popen([config['supervisor'], config['configuration_file_path'],
cmd[action], process]).communicate()[0]
def getFolderContent(folder):
r=['<ul class="jqueryFileTree" style="display: none;">']
try:
r=['<ul class="jqueryFileTree" style="display: none;">']
d=urllib.unquote(folder)
for f in os.listdir(d):
if f.startswith('.'): #do not displays this file/folder
continue
ff=os.path.join(d,f)
if os.path.isdir(ff):
r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff,f))
else:
e=os.path.splitext(f)[1][1:] # get .ext and remove dot
r.append('<li class="file ext_%s"><a href="#" rel="%s">%s</a></li>' % (e,ff,f))
r.append('</ul>')
except Exception,e:
r.append('Could not load directory: %s' % str(e))
r.append('</ul>')
return jsonify(result=''.join(r))
def getFolder(folder):
r=['<ul class="jqueryFileTree" style="display: none;">']
try:
r=['<ul class="jqueryFileTree" style="display: none;">']
d=urllib.unquote(folder)
for f in os.listdir(d):
if f.startswith('.'): #do not display this file/folder
continue
ff=os.path.join(d,f)
if os.path.isdir(ff):
r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff, f))
r.append('</ul>')
except Exception,e:
r.append('Could not load directory: %s' % str(e))
r.append('</ul>')
return jsonify(result=''.join(r))
def getProjectList(folder):
project = []
for elt in os.listdir(folder):
project.append(elt)
return project
def newSoftware(folder, config, session):
json = ""
code = 0
runner_dir = config['runner_workdir']
try:
if not os.path.exists(folder):
os.mkdir(folder)
#load software.cfg and instance.cfg from http://git.erp5.org
software = "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/lamp-template/software.cfg"
instance = "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/lamp-template/instance.cfg"
softwareContent = ""
instanceContent = ""
try:
softwareContent = urllib.urlopen(software).read()
instanceContent = urllib.urlopen(instance).read()
except:
#Software.cfg and instance.cfg content will be empty
pass
open(os.path.join(folder, config['software_profile']), 'w').write(softwareContent)
open(os.path.join(folder, config['instance_profile']), 'w').write(instanceContent)
open(os.path.join(runner_dir, ".project"), 'w').write(folder)
session['title'] = getProjectTitle(config)
code = 1
else:
json = "Directory '" + folder + "' already exist, please enter a new name for your software"
except Exception, e:
json = "Can not create your software, please try again! : " + str(e)
if os.path.exists(folder):
shutil.rmtree(folder)
return jsonify(code=code, result=json)
def checkSoftwareFolder(path, config):
tmp = path.split('/')
del tmp[len(tmp) - 1]
path = string.join(tmp, '/')
if os.path.exists(os.path.join(path, config['software_profile'])) and \
os.path.exists(os.path.join(path, config['instance_profile'])):
return jsonify(result=path)
return jsonify(result="")
def getProjectTitle(config):
conf = os.path.join(config['runner_workdir'], ".project")
if os.path.exists(conf):
project = open(conf, "r").read().replace(config['workspace'] + "/", "").split("/")
software = project[len(project) - 1]
del project[len(project) - 1]
return software + "(" + string.join(project, '/') + ")"
return ""
\ No newline at end of file
from flask import Flask, request, redirect, url_for, \ from flask import Flask, request, redirect, url_for, \
render_template, flash render_template, flash, jsonify, session
from utils import getProfile, runInstanceWithLock, runSoftwareWithLock, Popen, isInstanceRunning, isSoftwareRunning, getSvcStatus, getSlapStatus, svcStopAll from utils import *
import os import os
import shutil import shutil
from gittools import cloneRepo, gitStatus
app = Flask(__name__) app = Flask(__name__)
# general views # general views
@app.route('/') @app.route('/')
def home(): def home():
if not os.path.exists(app.config['workspace']) or len(os.listdir(app.config['workspace'])) == 0:
session['title'] = "No project"
return redirect(url_for('configRepo'))
session['title'] = getProjectTitle(app.config)
return render_template('index.html') return render_template('index.html')
@app.route('/configRepo')
def configRepo():
public_key = open(app.config['public_key'], 'r').read()
return render_template('cloneRepository.html', workDir=app.config['workspace'], public_key=public_key)
# software views # software views
@app.route('/editSoftwareProfile') @app.route('/editSoftwareProfile')
def editSoftwareProfile(): def editSoftwareProfile():
profile = getProfile(app.config['runner_workdir'], app.config['software_profile'])
if profile == "":
flash('Error: can not open profile, please select your project first')
return render_template('updateSoftwareProfile.html', return render_template('updateSoftwareProfile.html',
profile=getProfile(app.config['software_profile']), instance_url=url_for('getInstance', _external=True)) profile=profile,
instance_url=url_for('getInstance', _external=True))
@app.route('/software.cfg', methods=['GET', 'POST']) @app.route('/software.cfg', methods=['GET', 'POST'])
def getSoftware(): def getSoftware():
return getProfile(app.config['software_profile']) return getProfile(app.config['runner_workdir'], app.config['software_profile'])
@app.route('/inspectSoftware', methods=['GET']) @app.route('/inspectSoftware', methods=['GET'])
def inspectSoftware(): def inspectSoftware():
if not os.path.exists(app.config['software_root']): if not os.path.exists(app.config['software_root']):
result = "Does not exists yet" result = ""
else: else:
process = Popen(['find'], cwd=app.config['software_root']) #process = Popen(['find'], cwd=app.config['software_root'])
result = process.communicate()[0] result = app.config['software_root']
return render_template('runResult.html', type='Software', return render_template('runResult.html', type='Software',
result=result) result=result)
...@@ -60,27 +74,34 @@ def viewSoftwareLog(): ...@@ -60,27 +74,34 @@ def viewSoftwareLog():
@app.route('/updateSoftwareProfile', methods=['POST']) @app.route('/updateSoftwareProfile', methods=['POST'])
def updateSoftwareProfile(): def updateSoftwareProfile():
open(app.config['software_profile'], 'w').write(request.form['content']) profile = getProfilePath(app.config['runner_workdir'], app.config['software_profile'])
if profile != "":
open(profile, 'w').write(request.form['content'])
return redirect(url_for('editSoftwareProfile')) return redirect(url_for('editSoftwareProfile'))
# instance views # instance views
@app.route('/editInstanceProfile') @app.route('/editInstanceProfile')
def editInstanceProfile(): def editInstanceProfile():
profile = getProfile(app.config['runner_workdir'], app.config['instance_profile'])
if profile == "":
flash('Error: can not open profile, please select your project first')
return render_template('updateInstanceProfile.html', return render_template('updateInstanceProfile.html',
profile=getProfile(app.config['instance_profile'])) profile=profile)
@app.route('/instance.cfg', methods=['GET', 'POST']) @app.route('/instance.cfg', methods=['GET', 'POST'])
def getInstance(): def getInstance():
return getProfile(app.config['instance_profile']) return getProfile(app.config['runner_workdir'], app.config['instance_profile'])
@app.route('/inspectInstance', methods=['GET']) @app.route('/inspectInstance', methods=['GET'])
def inspectInstance(): def inspectInstance():
file_content = 'Does not exists yet.' file_content = ''
result = ''
if os.path.exists(app.config['instance_root']): if os.path.exists(app.config['instance_root']):
process = Popen(['find'], cwd=app.config['instance_root']) file_content = app.config['instance_root']
file_content = process.communicate()[0] result = getSvcStatus(app.config)
return render_template('instanceInspect.html', return render_template('instanceInspect.html',
file_content=file_content, supervisor=getSvcStatus(app.config), slap_status=getSlapStatus(app.config)) file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config),
supervisore=result)
@app.route('/removeInstance') @app.route('/removeInstance')
def removeInstance(): def removeInstance():
...@@ -119,10 +140,121 @@ def viewInstanceLog(): ...@@ -119,10 +140,121 @@ def viewInstanceLog():
@app.route('/updateInstanceProfile', methods=['POST']) @app.route('/updateInstanceProfile', methods=['POST'])
def updateInstanceProfile(): def updateInstanceProfile():
open(app.config['instance_profile'], 'w').write(request.form['content']) profile = getProfilePath(app.config['runner_workdir'], app.config['instance_profile'])
if profile != "":
open(profile, 'w').write(request.form['content'])
return redirect(url_for('editInstanceProfile')) return redirect(url_for('editInstanceProfile'))
@app.route('/stopAllPartition', methods=['GET']) @app.route('/stopAllPartition', methods=['GET'])
def stopAllPartition(): def stopAllPartition():
svcStopAll(app.config) svcStopAll(app.config)
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@app.route('/tailProcess/name/<process>', methods=['GET'])
def tailProcess(process):
return render_template('processTail.html',
process_log=getSvcTailProcess(app.config, process), process=process)
@app.route('/startStopProccess/name/<process>/cmd/<action>', methods=['GET'])
def startStopProccess(process, action):
svcStartStopProcess(app.config, process, action)
return redirect(url_for('inspectInstance'))
@app.route('/showBuildoudAnnotate', methods=['GET'])
def showBuildoudAnnotate():
if runBuildoutAnnotate(app.config):
flash('Started.')
else:
flash('Please run software before')
return redirect(url_for('viewBuildoudAnnotate'))
@app.route('/viewBuildoudAnnotate', methods=['GET'])
def viewBuildoudAnnotate():
if os.path.exists(app.config['annotate_log']):
result = open(app.config['annotate_log'], 'r').read()
else:
result = 'Not found yet'
return render_template('viewLog.html', type='Instance',
result=result, running=isInstanceRunning(app.config))
@app.route('/openProject/<method>', methods=['GET'])
def openProject(method):
return render_template('projectFolder.html', method=method,
workDir=app.config['workspace'])
@app.route('/cloneRepository', methods=['POST'])
def cloneRepository():
data = {"repo":request.form['repo'], "user":request.form['user'],
"email":request.form['email']}
name = request.form['name']
data['path'] = os.path.join(app.config['workspace'], name)
return cloneRepo(data)
@app.route('/readFolder', methods=['POST'])
def readFolder():
return getFolderContent(request.form['dir'])
@app.route('/openFolder', methods=['POST'])
def openFolder():
return getFolder(request.form['dir'])
@app.route('/createSoftware', methods=['POST'])
def createSoftware():
return newSoftware(request.form['folder'], app.config, session)
@app.route("/checkFolder", methods=['POST'])
def checkFolder():
return checkSoftwareFolder(request.form['path'], app.config)
@app.route("/setCurentProject", methods=['POST'])
def setCurentProject():
folder = request.form['path']
if os.path.exists(folder):
open(os.path.join(app.config['runner_workdir'], ".project"), 'w').write(folder)
session['title'] = getProjectTitle(app.config)
return jsonify(code=1, result="")
else:
return jsonify(code=0, result=("Can not open '" + folder + "'"))
@app.route("/manageProject", methods=['GET'])
def manageProject():
return render_template('manageProject.html', workDir=app.config['workspace'],
project=getProjectList(app.config['workspace']))
@app.route("/getProjectStatus", methods=['POST'])
def getProjectStatus():
return gitStatus(request.form['project'])
@app.route("/curentSoftware")
def curentSoftware():
project = os.path.join(app.config['runner_workdir'], ".project")
if os.path.exists(project):
return render_template('softwareFolder.html', workDir=app.config['workspace'],
project=open(project).read())
return redirect(url_for('configRepo'))
@app.route("/createFile", methods=['POST'])
def createFile():
try:
if request.form['type'] == "file":
f = open(request.form['file'], 'w').write(" ")
else:
os.mkdir(request.form['file'])
return jsonify(code=1, result="")
except Exception, e:
return jsonify(code=0, result=str(e))
@app.route("/getFileContent", methods=['POST'])
def getFileContent():
if os.path.exists(request.form['file']):
return jsonify(code=1, result=open(request.form['file'], 'r').read())
else:
return jsonify(code=0, result="Error: No such file!")
@app.route("/saveFileContent", methods=['POST'])
def saveFileContent():
if os.path.exists(request.form['file']):
open(request.form['file'], 'w').write(request.form['content'])
return jsonify(code=1, result="")
else:
return jsonify(code=0, result="Error: No such file!")
\ No newline at end of file
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