Commit f6f2435f authored by Alain Takoudjou's avatar Alain Takoudjou

add slapgrid process control and log management

parent b2c4d3fa
*{margin: 0px;padding: 0px;}
*
{
margin: 0px;
padding: 0px;
}
a{ a{
text-decoration: none; text-decoration: none;
...@@ -47,11 +42,12 @@ body { ...@@ -47,11 +42,12 @@ body {
background: #7195c2 url('../images/cloud_bg.jpg') repeat-x; background: #7195c2 url('../images/cloud_bg.jpg') repeat-x;
font: 13px 'Helvetica Neue', Helvetica, Arial, sans-serif; font: 13px 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #000000; color: #000000;
font-size: normal;
} }
#page #page
{ {
margin: 5px auto; margin: 20px auto;
width: 841px; width: 841px;
} }
...@@ -72,12 +68,9 @@ body { ...@@ -72,12 +68,9 @@ body {
height: 30px; height: 30px;
} }
#header .text{ #header .run{
font-weight: bold; margin-right: 30px;
font-size: 14px; float: right;
padding-top: 6px;
margin-left: 5px;
float: left;
} }
#header .info{ #header .info{
...@@ -85,7 +78,7 @@ body { ...@@ -85,7 +78,7 @@ body {
font-weight: normal; font-weight: normal;
padding-top: 3px; padding-top: 3px;
float: left; float: left;
width: 700px; width: 690px;
height: 22px; height: 22px;
text-align: center; text-align: center;
color: #4c6172; color: #4c6172;
...@@ -175,7 +168,7 @@ body { ...@@ -175,7 +168,7 @@ body {
padding-left: 6px; padding-left: 6px;
} }
.wmenu ul li a:focus, .wmenu ul li a:hover, .wmenu ul li a.active{ .wmenu ul li a:hover, .wmenu ul li a.active{
color:#0271BF; color:#0271BF;
background:url(../images/menu_hover.png) bottom repeat-x; background:url(../images/menu_hover.png) bottom repeat-x;
} }
...@@ -274,6 +267,7 @@ body { ...@@ -274,6 +267,7 @@ body {
color:#000; color:#000;
padding:5px; padding:5px;
outline:none; outline:none;
font: 13px 'Helvetica Neue', Helvetica, Arial, sans-serif;
} }
.idleField{ .idleField{
background:#fff; background:#fff;
...@@ -281,6 +275,11 @@ body { ...@@ -281,6 +275,11 @@ body {
border: solid 1px #678dad; border: solid 1px #678dad;
padding:5px; padding:5px;
outline:none; outline:none;
font: 13px 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
input[type="radio"], input[type="checkbox"]{
margin: 4px;
} }
.flash{ .flash{
...@@ -479,6 +478,8 @@ body { ...@@ -479,6 +478,8 @@ body {
background: #e4e4e4 url(../images/arrow_down.png) 97% 50% no-repeat; background: #e4e4e4 url(../images/arrow_down.png) 97% 50% no-repeat;
} }
.gradient{border:1px solid #D4D4D4;background-color:#f4f4f4;background:-moz-linear-gradient(#f4f4f4,#ececec);background:-webkit-linear-gradient(#f4f4f4,#ececec);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4',endColorstr='#ececec')";background:linear-gradient(#f4f4f4,#ececec);}
h2.hight:hover{ h2.hight:hover{
cursor: pointer; cursor: pointer;
} }
...@@ -498,8 +499,10 @@ h2.hight:hover{ ...@@ -498,8 +499,10 @@ h2.hight:hover{
color: #000; color: #000;
width: 754px; width: 754px;
padding: 2px; padding: 2px;
height: 600px; height: 450px;
} }
.log_btn{border: 1px solid #678dad; border-top:none; height: 22px; width: 654px; margin: 0 40px 10px 40px;
padding:4px 10px 4px 10px; font-size: 16px; color: #4c6172;}
.waitting{ .waitting{
margin-left: 10px; margin-left: 10px;
...@@ -519,6 +522,7 @@ h2.hight:hover{ ...@@ -519,6 +522,7 @@ h2.hight:hover{
margin-bottom: 9px; margin-bottom: 9px;
font-size: 14px; font-size: 14px;
cursor:default; cursor:default;
word-wrap: break-word
} }
#check{ #check{
...@@ -533,7 +537,7 @@ h2.hight:hover{ ...@@ -533,7 +537,7 @@ h2.hight:hover{
overflow: auto; overflow: auto;
height: 95px; height: 95px;
padding: 5px; padding: 5px;
width: 754px; width: 604px;
background:#fff; background:#fff;
margin-bottom: 10px; margin-bottom: 10px;
color: #3A494F; color: #3A494F;
...@@ -572,16 +576,17 @@ a.lshare{ ...@@ -572,16 +576,17 @@ a.lshare{
height: 18px; height: 18px;
font-size: 15px; font-size: 15px;
border: solid 1px #678dad; border: solid 1px #678dad;
color: #000; color: #666666;
margin-right: 10px; margin-right: 10px;
-webkit-border-radius: 3px; -webkit-border-radius: 3px;
-moz-border-radius: 3px; -moz-border-radius: 3px;
text-shadow: 0px 1px #F0F1F2; text-shadow: 0px 1px #F0F1F2;
text-align:center;
font-weight:bold;
} }
a.lshare:hover{ a.lshare:hover{
background:#D9D9D9 url(../images/button_highlight.png) 50% repeat-x; background:#D9D9D9 url(../images/button_highlight.png) 50% repeat-x;
color: #000;
border:solid 1px #73A6FF; border:solid 1px #73A6FF;
} }
a.lshare:focus{ a.lshare:focus{
...@@ -643,3 +648,30 @@ a.lshare img{ ...@@ -643,3 +648,30 @@ a.lshare img{
#pClose:hover{background:url(../images/close_hover.png) no-repeat 0px 0px;} #pClose:hover{background:url(../images/close_hover.png) no-repeat 0px 0px;}
.md5sum {margin:10px; font-size:15px;} .md5sum {margin:10px; font-size:15px;}
.title{background: #e4e4e4; width: 100%; height: 25px; padding-top:2px; text-indent: 5px; color: #737373; text-shadow: 0px 1px #FFF;} .title{background: #e4e4e4; width: 100%; height: 25px; padding-top:2px; text-indent: 5px; color: #737373; text-shadow: 0px 1px #FFF;}
.clone-box-left{float:left; width: 120px; font-size:14px; background: #e4e4e4; padding:5px 0 5px 5px; margin-top:10px;
font-size:14px; border-radius: 4px 0 0 4px;}
.clone-box-right{background: #e4e4e4; padding: 5px; float:right; width: 634px; margin-left: -5px;
margin-top:10px; box-shadow: 1px 1px 1px #888888;}
.clone-box-left ul{margin:0px; list-style:none}
.clone-box-left li{padding: 2px; padding-left:10px; padding-right:10px;}
.clone-box-left li:hover{background:#F0F2F2; border-radius: 4px 0 0 4px;}
.clone-box-left li.checked{background:#fff; border-radius: 4px 0 0 4px;}
.clone-box-right h2{text-align:center}
/* Bubble pop-up */
.popup {position: absolute; display: none; z-index: 50;}
.popup table, .popup td, .popup th{margin:0; padding:0; background:none; border:0; border-collapse:collapse;}
.popup td.corner {height: 15px;width: 19px;}
.popup td#topleft { background-image: url(../images/bubble-8.png); }
.popup td.top { background-image: url(../images/bubble-7.png);}
.popup td#topright { background-image: url(../images/bubble-6.png); }
.popup td.left { background-image: url(../images/bubble-4.png); }
.popup td.right { background-image: url(../images/bubble-5.png); }
.popup td#bottomleft { background-image: url(../images/bubble-3.png); }
.popup td.bottom { background-image: url(../images/bubble-2.png);}
.popup td.top img { display: block; }
.popup td#bottomright { background-image: url(../images/bubble-1.png); }
.popup-contents {background: #fff; color: #666666;}
.popup a{display: block; font-weight:bold; color: #4DA0C6;}
.popup a:hover{color: #666666;}
.popup ul{margin:0; padding:0; list-style:none;}
.popup li{border-bottom: 1px dashed #666666; padding:5px; padding-top:5px;}
...@@ -55,18 +55,18 @@ if(jQuery) (function($){ ...@@ -55,18 +55,18 @@ if(jQuery) (function($){
$(this).parent().find('UL').remove(); // cleanup $(this).parent().find('UL').remove(); // cleanup
showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) ); showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) );
$(this).parent().removeClass('collapsed').addClass('expanded'); $(this).parent().removeClass('collapsed').addClass('expanded');
if(o.selectFolder){
h($(this).attr('rel'));
}
} else { } else {
// Collapse // Collapse
$(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing }); $(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
$(this).parent().removeClass('expanded').addClass('collapsed'); $(this).parent().removeClass('expanded').addClass('collapsed');
} }
if(o.selectFolder){
h($(this).attr('rel'));
}
} else { } else {
h($(this).attr('rel')); h($(this).attr('rel'));
} }
return false;
}); });
// Prevent A from triggering the # on non-click events // Prevent A from triggering the # on non-click events
if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; }); if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
......
/*Common javascript function*/
String.prototype.toHtmlChar = function(){
c = {'<':'&lt;', '>':'&gt;', '&':'&amp;', '"':'&quot;', "'":'&#039;',
'#':'&#035;' };
return this.replace( /[<&>'"#]/g, function(s) { return c[s]; } );
}
/**************************/
/*Cookies Management*/
function setCookie(name,value,expires,path,domain,secure){
if (!expires){
var today = new Date();
expires = new Date(today.getTime() + 365 * 24 * 60 * 60 * 1000);
}
document.cookie = name + "=" + escape(value) +
"; expires=" + expires.toGMTString() +
((path) ? "; path=" + path : "/") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
}
function deleteCookie(name,path,domain) {
if (getCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "/") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}
function getCookie(name) {
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++){
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==name){
var result = unescape(y);
if (result != "" && result != null){
return result;
}
return null;
}
}
return null;
}
/**************************/
...@@ -7,8 +7,10 @@ $(document).ready( function() { ...@@ -7,8 +7,10 @@ $(document).ready( function() {
editor.getSession().setTabSize(2); editor.getSession().setTabSize(2);
editor.getSession().setUseSoftTabs(true); editor.getSession().setUseSoftTabs(true);
editor.renderer.setHScrollBarAlwaysVisible(false); editor.renderer.setHScrollBarAlwaysVisible(false);
$("#editor").css("font-size", "14px");
var file = $("input#profile").val(); var file = $("input#profile").val();
var workdir = $("input#workdir").val();
var edit = false; var edit = false;
var send = false; var send = false;
selectFile(file); selectFile(file);
...@@ -40,6 +42,20 @@ $(document).ready( function() { ...@@ -40,6 +42,20 @@ $(document).ready( function() {
getmd5sum(); getmd5sum();
return false; return false;
}); });
$("#adddevelop").click(function(){
var developList = new Array();
var i=0;
$("#plist li").each(function(index){
var elt = $(this).find("input:checkbox");
if (elt.is(":checked")){
developList[i] = workdir+"/"+elt.val();
i++;
elt.attr("checked", false);
}
});
if (developList.length > 0){setDevelop(developList);}
return false;
});
function selectFile(file){ function selectFile(file){
edit = false; edit = false;
...@@ -79,4 +95,33 @@ $(document).ready( function() { ...@@ -79,4 +95,33 @@ $(document).ready( function() {
} }
}); });
} }
function setDevelop(developList){
if (developList==null || developList.length <= 0) return;
editor.navigateFileStart();
editor.find('buildout',{caseSensitive: true,wholeWord: true});
if(!editor.getSelectionRange().isEmpty()){
//editor.find("",{caseSensitive: true,wholeWord: true,regExp: true});
//if(!editor.getSelectionRange().isEmpty()){
//alert("found");
//}
//else{alert("no found");
//}
}
else{
$("#error").Popup("Can not found part [buildout]! Please make sure that you have a cfg file", {type:'alert', duration:3000});
return;
}
editor.navigateLineEnd();
$.post($SCRIPT_ROOT+"/getPath", {file:developList.join("#")}, function(data) {
if(data.code==1){
var result = data.result.split('#');
editor.insert("\ndevelop =\n\t" + result[0] + "\n");
for(var i=1; i<result.length; i++)
editor.insert("\t" + result[i] + "\n");
}
})
.error(function() { })
.complete(function(){});
editor.insert("\n");
}
}); });
\ No newline at end of file
...@@ -4,6 +4,16 @@ $(document).ready( function() { ...@@ -4,6 +4,16 @@ $(document).ready( function() {
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) { $('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
selectFile(file); selectFile(file);
}); });
configRadio();
$("input#nothing").change(function(){
configRadio();
});
$("input#ssh").change(function(){
configRadio();
});
$("input#https").change(function(){
configRadio();
});
$("#clone").click(function(){ $("#clone").click(function(){
if(send){ if(send){
cloneRequest.abort(); cloneRequest.abort();
...@@ -35,6 +45,31 @@ $(document).ready( function() { ...@@ -35,6 +45,31 @@ $(document).ready( function() {
} }
email = $("input#email").val(); email = $("input#email").val();
} }
if($("input#https").is(':checked')){
if($("input#username").val() == "" || !$("input#username").val().match(/^[\w\d\._-]+$/)){
$("#error").Popup("Please enter a correct username", {type:'alert', duration:3000});
return false;
}
if($("input#password").val() != ""){
if(repo_url.indexOf("https://") != -1){
repo_url = "https://" + $("input#username").val() +
":" + $("input#password").val() +
"@" + repo_url.substring(8);
}
else{
$("#error").Popup("The URL of your repository should start with 'https://'", {type:'alert', duration:3000});
return false;
}
}
else{
$("#error").Popup("Please enter your password", {type:'alert', duration:3000});
return false;
}
}
else if(repo_url.indexOf("https://") != -1){
$("#error").Popup("Please select HTTPS Security Mode for this repository", {type:'alert', duration:3000});
return false;
}
$("#imgwaitting").fadeIn('normal'); $("#imgwaitting").fadeIn('normal');
$("#clone").empty(); $("#clone").empty();
$("#clone").append("Stop"); $("#clone").append("Stop");
...@@ -42,8 +77,9 @@ $(document).ready( function() { ...@@ -42,8 +77,9 @@ $(document).ready( function() {
cloneRequest = $.ajax({ cloneRequest = $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/cloneRepository', url: $SCRIPT_ROOT + '/cloneRepository',
data: "repo=" + repo_url + "&name=" + $("input#name").val() + "&email=" + email + data: {repo: repo_url, name: ($("input#workdir").val() + "/"
"&user=" + name, + $("input#name").val()), email:email,
user:name},
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
$("#file_navigation").fadeIn('normal'); $("#file_navigation").fadeIn('normal');
...@@ -65,6 +101,24 @@ $(document).ready( function() { ...@@ -65,6 +101,24 @@ $(document).ready( function() {
}); });
return false; return false;
}); });
function configRadio(){
$("#modelist li").each(function(index) {
var boxselector = "#box" + index;
if($(this).hasClass('checked')){
$(this).removeClass('checked');
$(boxselector).slideUp("normal");
}
if($(this).find("input:radio").is(':checked')){
$(this).addClass('checked');
//change content here
$(boxselector).slideDown("normal");
}
if(index != 2){
$("input#password").val("");
$("input#cpassword").val("");
}
});
}
function selectFile(file){ function selectFile(file){
//nothing //nothing
......
$(document).ready( function() { $(document).ready( function() {
var basedir = $("input#basedir").val();
var editor; var editor;
setupFileTree(); setupFileTree();
...@@ -17,11 +16,10 @@ $(document).ready( function() { ...@@ -17,11 +16,10 @@ $(document).ready( function() {
function viewFile(file){ function viewFile(file){
//User have double click on file in to the fileTree //User have double click on file in to the fileTree
var name = file.replace(basedir, ""); loadFileContent(file);
loadFileContent(file, name);
} }
function loadFileContent(file, filename){ function loadFileContent(file){
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/checkFileType', url: $SCRIPT_ROOT + '/checkFileType',
...@@ -36,8 +34,8 @@ $(document).ready( function() { ...@@ -36,8 +34,8 @@ $(document).ready( function() {
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
$("#inline_content").empty(); $("#inline_content").empty();
$("#inline_content").append('<h2 style="color: #4c6172; font: 18px \'Helvetica Neue\', Helvetica, Arial, sans-serif;">Inspect Software Content: ' + $("#inline_content").append('<h2 style="color: #4c6172; font: 18px \'Helvetica Neue\', Helvetica, Arial, sans-serif;">Inspect Instance Content: ' +
filename +'</h2>'); file +'</h2>');
$("#inline_content").append('<br/><div class="main_content"><pre id="editor"></pre></div>'); $("#inline_content").append('<br/><div class="main_content"><pre id="editor"></pre></div>');
setupEditor(); setupEditor();
$(".inline").colorbox({inline:true, width: "847px", onComplete:function(){ $(".inline").colorbox({inline:true, width: "847px", onComplete:function(){
......
...@@ -17,7 +17,7 @@ $(document).ready( function() { ...@@ -17,7 +17,7 @@ $(document).ready( function() {
return; return;
} }
function fillContent(selectedElt){ function fillContent(){
var folder = $("#softwarelist").val(); var folder = $("#softwarelist").val();
var elt = $("option:selected", $("#softwarelist")); var elt = $("option:selected", $("#softwarelist"));
$('#fileTree').fileTree({ root: runnerDir + "/" + folder, script: $SCRIPT_ROOT + '/readFolder', $('#fileTree').fileTree({ root: runnerDir + "/" + folder, script: $SCRIPT_ROOT + '/readFolder',
...@@ -32,7 +32,7 @@ $(document).ready( function() { ...@@ -32,7 +32,7 @@ $(document).ready( function() {
var elt = $("option:selected", $("#softwarelist")); var elt = $("option:selected", $("#softwarelist"));
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/setCurentProject', url: $SCRIPT_ROOT + '/setCurrentProject',
data: "path=" + elt.attr('rel'), data: "path=" + elt.attr('rel'),
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
......
//Global Traitment!!!
var url = $SCRIPT_ROOT + "/slapgridResult"
var currentState = false;
var running = true;
var $current;
var processType = "";
var currentProcess;
var sendStop = false;
var processState = "Checking"; //define slapgrid running state
var openedlogpage = ""; //content software or instance if the current page is software or instance log, otherwise nothing
var logReadingPosition = 0;
var speed = 5000;
var isRunning = function(){
if (running){
$("#error").Popup("Slapgrid is currently under execution!", {type:'alert', duration:3000});
}
return running;
}
function setSpeed(value){
if (openedlogpage == ""){
speed = 5000;
}
else{ speed=value;}
}
function getRunningState(){
var param = {position:logReadingPosition, log:(processState!="Checking" && openedlogpage==processType.toLowerCase())? openedlogpage:""}
var jqxhr = $.post(url, param, function(data) {
setRunningState(data)
logReadingPosition = data.content.position;
if(data.content.content != ""){
$("#salpgridLog").append(data.content.content.toHtmlChar());
$("#salpgridLog")
.scrollTop($("#salpgridLog")[0].scrollHeight - $("#salpgridLog")
.height());
}
processState = (running && processState != "Running")?"Running":"Stopped";
})
.error(function() { clearAll(false); })
.complete(function() {
if (running){
setTimeout(function(){
getRunningState();
}, speed);
}
});
}
function clearAll(setStop){
currentState = false;
running = setStop;
}
function bindRun(){
$("#softrun").click(function(){
if($("#softrun").text() == "Stop"){
stopProcess();
}
else{
if(!isRunning()){
setCookie("slapgridCMD", "Software");
location.href = $SCRIPT_ROOT + "/viewSoftwareLog";
}
}
return false;
});
$("#instrun").click(function(){
if($("#instrun").text() == "Stop"){
stopProcess();
}
else{
if(!isRunning()){
setCookie("slapgridCMD", "Instance");
location.href = $SCRIPT_ROOT + "/viewInstanceLog";
}
}
return false;
});
}
function setRunningState(data){
if (data.result){
if(!currentState){
$("#running").show();
running = true;
//change run menu title and style
if(data.software){
$("#softrun").empty();
$("#softrun").append("Stop");
$("#softrun").css("color", "#0271BF");
$current = $("#softrun");
processType = "Software";
}
if(data.instance){
$("#instrun").empty();
$("#instrun").append("Stop");
$("#instrun").css("color", "#0271BF");
$current = $("#instrun");
processType = "Instance";
}
}
}
else{
$("#running").hide();
running = false; //nothing is currently running
if ($current != undefined){
$current.empty();
$current.append("Run");
$current.css("color", "#000");
$current = undefined;
currentState = false;
$("#error").Popup("Successfully run " + processType + " Profile", {type:'info', duration:3000});
}
}
currentState = data.result;
}
function runProcess(urlfor, data){
if(!isRunning()){
running = true;
processState = "Running";
currentProcess = $.post(urlfor)
.error(function() {
$("#error").Popup("Failled to run Slapgrid", {type:'error', duration:3000}); });
setRunningState(data);
setTimeout("getRunningState()", 5000);
}
}
function stopProcess(){
if (sendStop) return;
if (running){
sendStop = true;
var urlfor = $SCRIPT_ROOT + "stopSlapgrid"
var type = "slapgrid-sr.pid";
if($("#instrun").text() == "Stop"){
type = "slapgrid-cp.pid";
}
$.post(urlfor, {type:type}, function(data){
//if (data.result){
//$("#error").Popup("Failled to run Slapgrid", {type:'error', duration:3000}); });
//}
})
.error(function() {
$("#error").Popup("Failled to stop Slapgrid process", {type:'error', duration:3000}); })
.complete(function() {sendStop = false;processState="Stopped";});
}
}
function checkSavedCmd(){
var result = getCookie("slapgridCMD");
if (!result) return false;
if (result == "Software"){
running = false;
runProcess(($SCRIPT_ROOT + "/runSoftwareProfile"),
{result: true, instance:false, software:true});
}
else if(result == "Instance"){
running = false;
runProcess(($SCRIPT_ROOT + "/runInstanceProfile"),
{result: true, instance:true, software:false});
}
deleteCookie("slapgridCMD");
return (result != null);
}
\ No newline at end of file
...@@ -45,7 +45,7 @@ $(document).ready( function() { ...@@ -45,7 +45,7 @@ $(document).ready( function() {
} }
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/setCurentProject', url: $SCRIPT_ROOT + '/setCurrentProject',
data: "path=" + $("input#path").val(), data: "path=" + $("input#path").val(),
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
...@@ -60,20 +60,19 @@ $(document).ready( function() { ...@@ -60,20 +60,19 @@ $(document).ready( function() {
}); });
function selectFile(file){ function selectFile(file){
var relativeFile = file.replace(workdir, "");
$("#info").empty(); $("#info").empty();
$("input#subfolder").val(file); $("input#subfolder").val(file);
path = ""; path = "";
if(method == "open"){ if(method == "open"){
$("#info").append("Selection: " + relativeFile); $("#info").append("Selection: " + file);
checkFolder(file); checkFolder(file);
} }
else{ else{
if($("input#software").val() != "" && $("input#software").val().match(/^[\w\d._-]+$/)){ if($("input#software").val() != "" && $("input#software").val().match(/^[\w\d._-]+$/)){
$("#info").append("New Software in: " + relativeFile + $("input#software").val()); $("#info").append("New Software in: " + file + $("input#software").val());
} }
else{ else{
$("#info").append("Selection: " + relativeFile); $("#info").append("Selection: " + file);
} }
} }
return; return;
......
...@@ -29,7 +29,7 @@ $(document).ready( function() { ...@@ -29,7 +29,7 @@ $(document).ready( function() {
$("#addbranch").click(function(){ $("#addbranch").click(function(){
if($("input#branchname").val() == "" || if($("input#branchname").val() == "" ||
$("input#branchname").val() == "Enter the branch name..."){ $("input#branchname").val() == "Enter the branch name..."){
$("#error").Popup("Please Enter your branch name", {type:'alert', duration:3000}); $("#error").Popup("Please Enter the new branch name", {type:'alert', duration:3000});
return false; return false;
} }
var project = $("#project").val(); var project = $("#project").val();
...@@ -37,10 +37,34 @@ $(document).ready( function() { ...@@ -37,10 +37,34 @@ $(document).ready( function() {
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/newBranch', url: $SCRIPT_ROOT + '/newBranch',
data: "project=" + $("input#workdir").val() + "/" + project + "&name=" + branch, data: {project:$("input#workdir").val() + "/" + project, name:branch, create:'1'},
success: function(data){
if(data.code == 1){
$("input#branchname").val("Enter the branch name...");
gitStatus();
}
else{
$("#error").Popup(data.result, {type:'error'});
}
}
});
return false;
});
$("#docheckout").click(function(){
if($("input#checkout").val() == "" ||
$("input#checkout").val() == "Existing branch name..."){
$("#error").Popup("Please Enter your branch name", {type:'alert', duration:3000});
return false;
}
var project = $("#project").val();
var branch = $("input#checkout").val();
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/newBranch',
data: {project:$("input#workdir").val() + "/" + project, name:branch, create:'0'},
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
$("input#branchname").val(""); $("input#checkout").val("Existing branch name...");
gitStatus(); gitStatus();
} }
else{ else{
......
...@@ -7,6 +7,7 @@ $(document).ready( function() { ...@@ -7,6 +7,7 @@ $(document).ready( function() {
editor.getSession().setTabSize(2); editor.getSession().setTabSize(2);
editor.getSession().setUseSoftTabs(true); editor.getSession().setUseSoftTabs(true);
editor.renderer.setHScrollBarAlwaysVisible(false); editor.renderer.setHScrollBarAlwaysVisible(false);
$("#editor").css("font-size", "14px");
var script = "/readFolder"; var script = "/readFolder";
var softwareDisplay = true; var softwareDisplay = true;
...@@ -102,15 +103,34 @@ $(document).ready( function() { ...@@ -102,15 +103,34 @@ $(document).ready( function() {
switchContent(); switchContent();
return false; return false;
}); });
$("#getmd5").click(function(){
getmd5sum();
return false;
});
$("#clearselect").click(function(){ $("#clearselect").click(function(){
$("#info").empty(); $("#info").empty();
$("#info").append("Select parent directory or nothing for root..."); $("#info").append("Select directory or nothing for root directory...");
$("input#subfolder").val(""); $("input#subfolder").val("");
$("#edit_info").empty(); $("#edit_info").empty();
$("#edit_info").append("No file selected"); $("#edit_info").append("No file selected");
editor.getSession().setValue(""); editor.getSession().setValue("");
$("#md5sum").empty(); $("#md5sum").empty();
$("a#option").hide();
return false;
});
$("#adddevelop").click(function(){
var developList = new Array();
var i=0;
$("#plist li").each(function(index){
var elt = $(this).find("input:checkbox");
if (elt.is(":checked")){
developList[i] = workdir+"/"+elt.val();
i++;
elt.attr("checked", false);
}
});
if (developList.length > 0){setDevelop(developList);}
return false; return false;
}); });
...@@ -150,7 +170,7 @@ $(document).ready( function() { ...@@ -150,7 +170,7 @@ $(document).ready( function() {
selectFile(file); selectFile(file);
}); });
$("#info").empty(); $("#info").empty();
$("#info").append("Select parent directory or nothing for root..."); $("#info").append("Select directory or nothing for root directory...");
$("input#subfolder").val(""); $("input#subfolder").val("");
} }
...@@ -169,9 +189,8 @@ $(document).ready( function() { ...@@ -169,9 +189,8 @@ $(document).ready( function() {
} }
function selectFile(file){ function selectFile(file){
relativeFile = file.replace(workdir, "");
$("#info").empty(); $("#info").empty();
$("#info").append(relativeFile); $("#info").append(file);
$("input#subfolder").val(file); $("input#subfolder").val(file);
$("#md5sum").empty(); $("#md5sum").empty();
path = ""; path = "";
...@@ -181,20 +200,21 @@ $(document).ready( function() { ...@@ -181,20 +200,21 @@ $(document).ready( function() {
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: $SCRIPT_ROOT + '/getFileContent', url: $SCRIPT_ROOT + '/getFileContent',
data: "file=" + file, data: {file: file},
success: function(data){ success: function(data){
if(data.code == 1){ if(data.code == 1){
md5link = " <a href='#' id='getmd5' title='Show or Update md5sum value'>[md5]</a>"
$("#edit_info").empty(); $("#edit_info").empty();
var name = file.split('/'); var name = file.split('/');
if(file.length > 65){
//substring title.
var start = file.length - 65;
file = "..." + file.substring(file.indexOf("/", (start + 1)));
}
$("#edit_info").append("Current file: " + $("#edit_info").append("Current file: " +
relativeFile + md5link); file);
$("a#option").show();
editor.getSession().setValue(data.result); editor.getSession().setValue(data.result);
setEditMode(name[name.length - 1]); setEditMode(name[name.length - 1]);
$("#getmd5").click(function(){
getmd5sum();
return false;
});
edit = true; edit = true;
} }
else{ else{
...@@ -207,6 +227,7 @@ $(document).ready( function() { ...@@ -207,6 +227,7 @@ $(document).ready( function() {
else{ else{
$("#edit_info").empty(); $("#edit_info").empty();
$("#edit_info").append("No file selected"); $("#edit_info").append("No file selected");
$("a#option").hide();
editor.getSession().setValue(""); editor.getSession().setValue("");
} }
return; return;
...@@ -223,4 +244,33 @@ $(document).ready( function() { ...@@ -223,4 +244,33 @@ $(document).ready( function() {
} }
} }
} }
function setDevelop(developList){
if (developList==null || developList.length <= 0) return;
editor.navigateFileStart();
editor.find('buildout',{caseSensitive: true,wholeWord: true});
if(!editor.getSelectionRange().isEmpty()){
//editor.find("",{caseSensitive: true,wholeWord: true,regExp: true});
//if(!editor.getSelectionRange().isEmpty()){
//alert("found");
//}
//else{alert("no found");
//}
}
else{
$("#error").Popup("Can not found part [buildout]! Please make sure that you have a cfg file", {type:'alert', duration:3000});
return;
}
editor.navigateLineEnd();
$.post($SCRIPT_ROOT+"/getPath", {file:developList.join("#")}, function(data) {
if(data.code==1){
var result = data.result.split('#');
editor.insert("\ndevelop =\n\t" + result[0] + "\n");
for(var i=1; i<result.length; i++)
editor.insert("\t" + result[i] + "\n");
}
})
.error(function() { })
.complete(function(){});
editor.insert("\n");
}
}); });
\ No newline at end of file
$(document).ready( function() {
openedlogpage = $("input#type").val();
updatelogBox();
var state = getCookie("autoUpdate");
$("#logheader").click(function(){
setupBox();
});
$("#manual").change(function(){
setCookie("autoUpdate", "manual");
if ($("input#type").val() == "instance"){location.href = $SCRIPT_ROOT + "/viewInstanceLog";}
else{location.href = $SCRIPT_ROOT + "/viewSoftwareLog";}
});
$("#live").change(function(){
updatelogBox();$("#logconfigbox").find("input:radio").attr('checked', false);$("#live").attr('checked', true);
setSpeed(500);setCookie("autoUpdate", "live");openedlogpage = $("input#type").val();});
$("#slow").change(function(){
updatelogBox();$("#logconfigbox").find("input:radio").attr('checked', false);$("#slow").attr('checked', true);
setSpeed(5000);setCookie("autoUpdate", "slow");openedlogpage = $("input#type").val();});
if(state){
$("#"+state).attr('checked', true);
updatelogBox();
if (state == "manual"){
openedlogpage = ""; setSpeed(0);
}
else{setSpeed((state=="live")?500:5000);}
}
else{$("#slow").attr('checked', true);}
function setupBox(){
var state = $("#logconfigbox").css("display");
if (state == "none"){
$("#logconfigbox").slideDown("normal");
$("#logheader").removeClass("hide");
$("#logheader").addClass("show");
}
else{
$("#logconfigbox").slideUp("normal");
$("#logheader").removeClass("show");
$("#logheader").addClass("hide");
}
}
function updatelogBox(){
if(processState=="Stopped" || processState=="Checking" || $("#manual").is(":checked")){
$("#salpgridLog").hide();
$("#manualLog").show();
$("#manualLog")
.scrollTop($("#manualLog")[0].scrollHeight - $("#manualLog")
.height());
}
else{
$("#salpgridLog").show();
$("#manualLog").hide();
}
}
});
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div id="home_box"> <div id="home_box">
<div class="inner_box"> <div class="inner_box">
<div class="lmenu"> <div class="lmenu">
<h2><a href="{{ url_for('configRepo')}}">Create a new Project from your repository</a></h2> <h2><a href="{{ url_for('configRepo')}}">Clone an Repository into your local Workspace</a></h2>
<p>Your repository will be cloned into your project folder, you will need the url of the repository. <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. This allows you to open and edit your local project copy and synchonize content with online repository.
</p> </p>
...@@ -18,15 +18,15 @@ ...@@ -18,15 +18,15 @@
<div class="clear"></div> <div class="clear"></div>
</div> </div>
<div class="sright_menu"> <div class="sright_menu">
<h2><a href="{{ url_for('manageProject')}}">Manage your Projects</a></h2> <h2><a href="{{ url_for('manageProject')}}">Manage Repositories</a></h2>
<p>You can view details of all projects and commit your Software Release here.</p> <p>You can view details of all repositories and commit your Software Release here.</p>
<img src="{{ url_for('static', filename='images/manage_repo.png') }}" /> <img src="{{ url_for('static', filename='images/manage_repo.png') }}" />
</div> </div>
<div class="clear"></div> <div class="clear"></div>
<div class="lmenu"> <div class="lmenu">
<h2><a href="{{ url_for('openProject', method='new')}}">Create your new Software Release</a></h2> <h2><a href="{{ url_for('openProject', method='new')}}">Create your new Software Release</a></h2>
<p>To create a new Software Release, choose the project directory in which you want to create your software. You will then be able to edit and <p>To create a new Software Release, choose the project directory in which you want to create your software. You will then be able to edit and
run the new software on SlapOs, using webrunner tools. run the new software release on SlapOS using slapgrid.
</p> </p>
<img src="{{ url_for('static', filename='images/folder_blue.png') }}" /> <img src="{{ url_for('static', filename='images/folder_blue.png') }}" />
<div class="clear"></div> <div class="clear"></div>
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<input type='hidden' name='root' id='root' value='{%if file_path != "" %}{{file_path}}{%endif%}' /> <input type='hidden' name='root' id='root' value='{%if file_path != "" %}{{file_path}}{%endif%}' />
<input type='hidden' name='basedir' id='basedir' value='{{base_dir}}' />
<h2>Instance inspection</h2><br/> <h2>Instance inspection</h2><br/>
<div id="tabContaier"> <div id="tabContaier">
<ul> <ul>
...@@ -24,7 +23,7 @@ ...@@ -24,7 +23,7 @@
</ul><!-- //Tab buttons --> </ul><!-- //Tab buttons -->
<div class="tabDetails"> <div class="tabDetails">
<div id="tab1" class="tabContents"> <div id="tab1" class="tabContents">
<p>This tab show all process generated by slapgrid for your application. You can click on the process name to display logs.</p> <p>This tab show all process generated by slapgrid for your application. You can click on the process name to display log.</p>
{% if supervisor != []%} {% if supervisor != []%}
<table cellpadding="0" cellspacing="0" width="100%"> <table cellpadding="0" cellspacing="0" width="100%">
<tr> <tr>
...@@ -40,7 +39,7 @@ ...@@ -40,7 +39,7 @@
{% endfor %} {% endfor %}
</table> </table>
{% else %} {% else %}
<h2>Please run the software instance before displaying process</h2> <h2>No process to display, please run your instance</h2>
{%endif%} {%endif%}
</div><!-- end tab1 --> </div><!-- end tab1 -->
<div id="tab2" class="tabContents"> <div id="tab2" class="tabContents">
......
...@@ -15,9 +15,13 @@ ...@@ -15,9 +15,13 @@
<link href="{{ url_for('static', filename='css/styles.css', _external=False) }}" 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='js/jquery/jquery-1.6.2.min.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/jquery-1.6.2.min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/popup.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/popup.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jqueryToolTip.js') }}" type="text/javascript" charset="utf-8"></script>
<script type=text/javascript> <script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }}; $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script> </script>
<script src="{{ url_for('static', filename='js/scripts/process.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/cookies.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/common.js') }}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$('input[type="text"]').addClass("idleField"); $('input[type="text"]').addClass("idleField");
...@@ -37,7 +41,11 @@ ...@@ -37,7 +41,11 @@
} }
}); });
if($("input#fmsg").val() != ""){ if($("input#fmsg").val() != ""){
$("#error").Popup($("input#fmsg").val(), {type:'info', duration:10000, load:true}); $("#error").Popup($("input#fmsg").val(), {type:'info', duration:5000, load:true});
}
bindRun();
if(!checkSavedCmd()){
getRunningState();
} }
}); });
</script> </script>
...@@ -47,29 +55,31 @@ ...@@ -47,29 +55,31 @@
<div id="error"></div> <div id="error"></div>
<div id="page"> <div id="page">
<input type="hidden" name="fmsg" value="{{ get_flashed_messages()[0] }}" id="fmsg" /> <input type="hidden" name="fmsg" value="{{ get_flashed_messages()[0] }}" id="fmsg" />
<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;" title="Home"><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>
<div class="line"></div> <div class="line"></div>
<a href="{{ url_for('curentSoftware') }}" style="float:left" title="Edit current software release"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a> <a href="{{ url_for('editCurrentProject') }}" style="float:left" title="Edit your current project"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a>
<div class="line"></div> <div class="line"></div>
<h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2> <h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2>
<div class="run"><span id="running" style="display:none"><img alt="" src="{{ url_for('static', filename='images/ajax_roller.gif') }}"
height='26' title="slapgrid is currently running"/></span></div>
</div> </div>
<div class="wmenu"> <div class="wmenu">
<ul> <ul>
<li><span class="title_software">Software</span></li> <li><span class="title_software">Software</span></li>
<li><a href="{{ url_for('editSoftwareProfile') }}">Edit</a></li> <li><a href="{{ url_for('editSoftwareProfile') }}">Edit</a></li>
<li><a href="{{ url_for('runSoftwareProfile') }}">Run</a></li> <li><a href="{{ url_for('runSoftwareProfile') }}" id="softrun">Run</a></li>
<li><a href="{{ url_for('viewSoftwareLog') }}">Build log</a></li> <li><a href="{{ url_for('viewSoftwareLog') }}">Build log</a></li>
<li><a href="{{ url_for('inspectSoftware') }}">Inspect</a></li> <li><a href="{{ url_for('inspectSoftware') }}">Inspect</a></li>
<li><a href="{{ url_for('removeSoftware') }}">Remove</a></li> <li><a href="{{ url_for('removeSoftware') }}">Remove</a></li>
<li class="space"><span class="title_instance">Instance</span></li> <li class="space"><span class="title_instance">Instance</span></li>
<li><a href="{{ url_for('editInstanceProfile') }}">Edit</a></li> <li><a href="{{ url_for('editInstanceProfile') }}">Edit</a></li>
<li><a href="{{ url_for('runInstanceProfile') }}">Run</a></li> <li><a href="{{ url_for('runInstanceProfile') }}" id="instrun">Run</a></li>
<li><a href="{{ url_for('viewInstanceLog') }}">Build log</a></li> <li><a href="{{ url_for('viewInstanceLog') }}">Build log</a></li>
<li><a href="{{ url_for('inspectInstance') }}">Inspect</a></li> <li><a href="{{ url_for('inspectInstance') }}">Inspect</a></li>
<li><a href="{{ url_for('stopAllPartition') }}">Stop all</a></li> <li><a href="{{ url_for('stopAllPartition') }}">Stop all</a></li>
......
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}Log for {{ process }}{% endblock %} {% block title %}Log for {{ process }}{% endblock %}
{% block body %} {% block body %}
<h2>Displaying log for {{ process }}</h2><br/> <h2 class='title'>Supervisord tail for "{{ process }}"</h2><br/>
<textarea cols=103 rows=40 readonly>{{ process_log }}</textarea> <textarea cols=103 rows=30 readonly style="background:#000; color:#fff;">{{ process_log }}</textarea>
{% endblock %} {% endblock %}
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<input type="hidden" name="method" id="method" value="{{method}}" /> <input type="hidden" name="method" id="method" value="{{method}}" />
{% if method == "new" %} {% if method == "new" %}
<div id="addsoftware"> <div id="addsoftware">
<h2>What is the name of your software release?</h2> <h2>Create your software release</h2>
<label for='software'>Name: </label> <label for='software'>Name: </label>
<input type="text" name="software" id="software" size='30' value="Enter software name..." /> <input type="text" name="software" id="software" size='30' value="Enter software name..." />
<br/><br/> <br/><br/>
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<div id="fileTree" class="file_tree"></div> <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> <div id="file_info" class="file_info"><span id="info">Please select your parent folder into the box...</span></div>
<br/> <br/>
<input type="submit" name="create" id ="create" value="Start Project" class="button"/> <input type="submit" name="create" id ="create" value="Create" class="button"/>
</div> </div>
</div> </div>
{% elif method == "open" %} {% elif method == "open" %}
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
&nbsp;&nbsp;<button id ="delete" class="button" title="Remove this software">Remove</button> &nbsp;&nbsp;<button id ="delete" class="button" title="Remove this software">Remove</button>
&nbsp;&nbsp;<button id ="open" class="button" title="Set this software as current software release">Open</button> &nbsp;&nbsp;<button id ="open" class="button" title="Set this software as current software release">Open</button>
<br/><br/> <br/><br/>
<p><strong><u>Notes:</u> </strong> You can open any software release in the list by cliking on the "Open" button. Now compiling this software will take a very short time</p>
<br/>
<h2 id="softcontent">No content to displays</h2> <h2 id="softcontent">No content to displays</h2>
<div id="fileTree" class="file_tree" style='height:200px;'></div> <div id="fileTree" class="file_tree" style='height:200px;'></div>
<div id="file_info" class="file_info"> <div id="file_info" class="file_info">
......
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %}View {{ type }} log{% endblock %} {% block title %}View {{ type }} log{% endblock %}
{% block head %}
{{ super() }}
<script src="{{ url_for('static', filename='js/scripts/viewlog.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %} {% block body %}
<strong>Note:</strong> You can refresh this page from time to time to have updates.<br> <input type="hidden" name="type" value="{{type}}" id="type" />
<h2>Currently running: <span class="message">{{ running }}</span></h2><br> <h2 class="hight hide" id="logheader">Slapgrid result for {{ type }}</h2>
<h2>Result for {{ type }}</h2> <div class="log_btn" id="logconfigbox" style="display:none">
<div class="log_content"><textarea class="log" readonly >{{ result }}</textarea></div> <span style="margin-left:15px; font-size: 18px;"> Update parameters </span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="radio" name="liveupdate" id="manual" value="manual" />
<label for="manual">Manualy update</label>&nbsp;
<input type="radio" name="liveupdate" id="live" value="live" />
<label for="live">Live update</label>&nbsp;
<input type="radio" name="liveupdate" id="slow" value="slow" />
<label for="slow">From time to time</label>
</div>
<br/>
<div class="log_content"><textarea class="log" readonly id="salpgridLog"></textarea>
<textarea class="log" readonly id="manualLog" style="display:none">{{result}}</textarea></div>
{% endblock %} {% endblock %}
...@@ -9,6 +9,7 @@ from flask import jsonify ...@@ -9,6 +9,7 @@ from flask import jsonify
import shutil import shutil
import string import string
import hashlib import hashlib
import signal
class Popen(subprocess.Popen): class Popen(subprocess.Popen):
...@@ -27,7 +28,15 @@ def updateProxy(config): ...@@ -27,7 +28,15 @@ 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']) #Get current software release profile
try:
software_folder = open(os.path.join(config['runner_workdir'],
".project")).read()
profile = realpath(config, os.path.join(software_folder,
config['software_profile']))
except:
return False
slap.initializeConnection(config['master_url']) slap.initializeConnection(config['master_url'])
slap.registerSupply().supply(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'])
...@@ -59,7 +68,7 @@ def updateProxy(config): ...@@ -59,7 +68,7 @@ def updateProxy(config):
computer.updateConfiguration(xml_marshaller.dumps(slap_config)) computer.updateConfiguration(xml_marshaller.dumps(slap_config))
slap.registerOpenOrder().request(profile, slap.registerOpenOrder().request(profile,
partition_reference=partition_reference) partition_reference=partition_reference)
return True
def readPid(file): def readPid(file):
if os.path.exists(file): if os.path.exists(file):
...@@ -130,12 +139,13 @@ def runSoftwareWithLock(config): ...@@ -130,12 +139,13 @@ def runSoftwareWithLock(config):
removeProxyDb(config) removeProxyDb(config)
startProxy(config) startProxy(config)
logfile = open(config['software_log'], 'w') logfile = open(config['software_log'], 'w')
updateProxy(config) if not updateProxy(config):
return False
slapgrid = Popen([config['slapgrid_sr'], '-vc', config['configuration_file_path']], stdout=logfile) slapgrid = Popen([config['slapgrid_sr'], '-vc', config['configuration_file_path']], stdout=logfile)
writePid(slapgrid_pid, slapgrid.pid) writePid(slapgrid_pid, slapgrid.pid)
slapgrid.wait() slapgrid.wait()
#Saves the current compile software for re-use #Saves the current compile software for re-use
#This uses the new software create by slapgrid (if not exits yet) #This uses the new folder create by slapgrid (if not exits yet)
data = loadSoftwareData(config['runner_workdir']) data = loadSoftwareData(config['runner_workdir'])
md5 = "" md5 = ""
for path in os.listdir(config['software_root']): for path in os.listdir(config['software_root']):
...@@ -171,30 +181,50 @@ def isInstanceRunning(config): ...@@ -171,30 +181,50 @@ def isInstanceRunning(config):
running = False running = False
return running return running
def killRunningSlapgrid(config, ptype):
slapgrid_pid = os.path.join(config['runner_workdir'], ptype)
pid = readPid(slapgrid_pid)
if pid:
recursifKill([pid])
else:
return False
def recursifKill(pids):
"""Try to kill a list of proccess by the given pid list"""
if pids == []:
return
else:
for pid in pids:
ppids = pidppid(pid)
try:
os.kill(pid, signal.SIGKILL) #kill current process
except Exception:
pass
recursifKill(ppids) #kill all children of this process
def pidppid(pid):
"""get the list of the children pids of a process `pid`"""
proc = Popen('ps -o pid,ppid ax | grep "%d"' % pid, shell=True,
stdout=subprocess.PIPE)
ppid = [x.split() for x in proc.communicate()[0].split("\n") if x]
return list(int(p) for p, pp in ppid if int(pp) == pid)
def runInstanceWithLock(config): def runInstanceWithLock(config):
slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid') slapgrid_pid = os.path.join(config['runner_workdir'], 'slapgrid-cp.pid')
if not isInstanceRunning(config): if not isInstanceRunning(config):
startProxy(config) startProxy(config)
logfile = open(config['instance_log'], 'w') logfile = open(config['instance_log'], 'w')
updateProxy(config) if not updateProxy(config):
return False
slapgrid = Popen([config['slapgrid_cp'], '-vc', config['configuration_file_path']], stdout=logfile) slapgrid = Popen([config['slapgrid_cp'], '-vc', config['configuration_file_path']], stdout=logfile)
writePid(slapgrid_pid, slapgrid.pid) writePid(slapgrid_pid, slapgrid.pid)
slapgrid.wait() slapgrid.wait()
return True return True
return False return False
def getProfile(peojectDir, profileName):
profile = getProfilePath(peojectDir, profileName)
if os.path.exists(profile):
return open(profile).read()
else:
return None
def getProfilePath(peojectDir, profile): def getProfilePath(peojectDir, profile):
if not os.path.exists(os.path.join(peojectDir, ".project")): if not os.path.exists(os.path.join(peojectDir, ".project")):
return "" return False
projectFolder = open(os.path.join(peojectDir, ".project")).read() projectFolder = open(os.path.join(peojectDir, ".project")).read()
return os.path.join(projectFolder, profile) return os.path.join(projectFolder, profile)
...@@ -224,10 +254,6 @@ def runBuildoutAnnotate(config): ...@@ -224,10 +254,6 @@ def runBuildoutAnnotate(config):
return False return False
def svcStopAll(config): def svcStopAll(config):
#stop all process running in supervisord
request = Popen([config['supervisor'], config['configuration_file_path'],
'stop', 'all'])
request.wait()
return Popen([config['supervisor'], config['configuration_file_path'], return Popen([config['supervisor'], config['configuration_file_path'],
'shutdown']).communicate()[0] 'shutdown']).communicate()[0]
...@@ -261,39 +287,51 @@ def svcStartStopProcess(config, process, action): ...@@ -261,39 +287,51 @@ def svcStartStopProcess(config, process, action):
return Popen([config['supervisor'], config['configuration_file_path'], return Popen([config['supervisor'], config['configuration_file_path'],
cmd[action], process]).communicate()[0] cmd[action], process]).communicate()[0]
def getFolderContent(folder): def getFolderContent(config, folder):
r=['<ul class="jqueryFileTree" style="display: none;">'] r=['<ul class="jqueryFileTree" style="display: none;">']
try: try:
folder = str(folder)
r=['<ul class="jqueryFileTree" style="display: none;">'] r=['<ul class="jqueryFileTree" style="display: none;">']
d=urllib.unquote(folder) d=urllib.unquote(folder)
ldir = sorted(os.listdir(d), key=unicode.lower) realdir = realpath(config, d)
if not realdir:
r.append('Could not load directory: Permission denied')
ldir = []
else:
ldir = sorted(os.listdir(realdir), key=str.lower)
for f in ldir: for f in ldir:
if f.startswith('.'): #do not displays this file/folder if f.startswith('.'): #do not displays this file/folder
continue continue
ff=os.path.join(d,f) ff=os.path.join(d,f)
if os.path.isdir(ff): if os.path.isdir(os.path.join(realdir,f)):
r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff,f)) r.append('<li class="directory collapsed"><a href="#%s" rel="%s/">%s</a></li>' % (ff, ff,f))
else: else:
e=os.path.splitext(f)[1][1:] # get .ext and remove dot e=os.path.splitext(f)[1][1:] # get .ext and remove dot
r.append('<li class="file ext_%s"><a href="#" rel="%s">%s</a></li>' % (e,ff,f)) r.append('<li class="file ext_%s"><a href="#%s" rel="%s">%s</a></li>' % (e, ff,ff,f))
r.append('</ul>') r.append('</ul>')
except Exception,e: except Exception,e:
r.append('Could not load directory: %s' % str(e)) r.append('Could not load directory: %s' % str(e))
r.append('</ul>') r.append('</ul>')
return jsonify(result=''.join(r)) return jsonify(result=''.join(r))
def getFolder(folder): def getFolder(config, folder):
r=['<ul class="jqueryFileTree" style="display: none;">'] r=['<ul class="jqueryFileTree" style="display: none;">']
try: try:
folder = str(folder)
r=['<ul class="jqueryFileTree" style="display: none;">'] r=['<ul class="jqueryFileTree" style="display: none;">']
d=urllib.unquote(folder) d=urllib.unquote(folder)
ldir = sorted(os.listdir(d), key=unicode.lower) realdir = realpath(config, d)
if not realdir:
r.append('Could not load directory: Permission denied')
ldir = []
else:
ldir = sorted(os.listdir(realdir), key=str.lower)
for f in ldir: for f in ldir:
if f.startswith('.'): #do not display this file/folder if f.startswith('.'): #do not display this file/folder
continue continue
ff=os.path.join(d,f) ff=os.path.join(d,f)
if os.path.isdir(ff): if os.path.isdir(os.path.join(realdir,f)):
r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff, f)) r.append('<li class="directory collapsed"><a href="#%s" rel="%s/">%s</a></li>' % (ff, ff, f))
r.append('</ul>') r.append('</ul>')
except Exception,e: except Exception,e:
r.append('Could not load directory: %s' % str(e)) r.append('Could not load directory: %s' % str(e))
...@@ -307,13 +345,18 @@ def getProjectList(folder): ...@@ -307,13 +345,18 @@ def getProjectList(folder):
project.append(elt) project.append(elt)
return project return project
def configNewSR(config, project): def configNewSR(config, projectpath):
if os.path.exists(project): folder = realpath(config, projectpath)
if folder:
if isInstanceRunning(config):
killRunningSlapgrid(config, "slapgrid-cp.pid")
if isSoftwareRunning(config):
killRunningSlapgrid(config, "slapgrid-sr.pid")
stopProxy(config) stopProxy(config)
removeProxyDb(config) removeProxyDb(config)
startProxy(config) startProxy(config)
removeInstanceRoot(config) removeInstanceRoot(config)
open(os.path.join(config['runner_workdir'], ".project"), 'w').write(project) open(os.path.join(config['runner_workdir'], ".project"), 'w').write(projectpath)
return True return True
else: else:
return False return False
...@@ -323,8 +366,9 @@ def newSoftware(folder, config, session): ...@@ -323,8 +366,9 @@ def newSoftware(folder, config, session):
code = 0 code = 0
runner_dir = config['runner_workdir'] runner_dir = config['runner_workdir']
try: try:
if not os.path.exists(folder): folderPath = realpath(config, folder, check_exist=False)
os.mkdir(folder) if folderPath and not os.path.exists(folderPath):
os.mkdir(folderPath)
#load software.cfg and instance.cfg from http://git.erp5.org #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" 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" instance = "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/lamp-template/instance.cfg"
...@@ -336,34 +380,32 @@ def newSoftware(folder, config, session): ...@@ -336,34 +380,32 @@ def newSoftware(folder, config, session):
except: except:
#Software.cfg and instance.cfg content will be empty #Software.cfg and instance.cfg content will be empty
pass pass
open(os.path.join(folder, config['software_profile']), 'w').write(softwareContent) open(os.path.join(folderPath, config['software_profile']), 'w').write(softwareContent)
open(os.path.join(folder, config['instance_profile']), 'w').write(instanceContent) open(os.path.join(folderPath, config['instance_profile']), 'w').write(instanceContent)
open(os.path.join(runner_dir, ".project"), 'w').write(folder) open(os.path.join(runner_dir, ".project"), 'w').write(folder + "/")
session['title'] = getProjectTitle(config) session['title'] = getProjectTitle(config)
code = 1 code = 1
else: else:
json = "Directory '" + folder + "' already exist, please enter a new name for your software" json = "Bad folder or Directory '" + folder + \
"' already exist, please enter a new name for your software"
except Exception, e: except Exception, e:
json = "Can not create your software, please try again! : " + str(e) json = "Can not create your software, please try again! : " + str(e)
if os.path.exists(folder): if os.path.exists(folderPath):
shutil.rmtree(folder) shutil.rmtree(folderPath)
return jsonify(code=code, result=json) return jsonify(code=code, result=json)
def checkSoftwareFolder(path, config): def checkSoftwareFolder(path, config):
tmp = path.split('/') realdir = realpath(config, path)
del tmp[len(tmp) - 1] if realdir and os.path.exists(os.path.join(realdir, config['software_profile'])):
path = string.join(tmp, '/')
if os.path.exists(os.path.join(path, config['software_profile'])):
return jsonify(result=path) return jsonify(result=path)
return jsonify(result="") return jsonify(result="")
def getProjectTitle(config): def getProjectTitle(config):
conf = os.path.join(config['runner_workdir'], ".project") conf = os.path.join(config['runner_workdir'], ".project")
if os.path.exists(conf): if os.path.exists(conf):
project = open(conf, "r").read().replace(config['workspace'] + "/", "").split("/") project = open(conf, "r").read().split("/")
software = project[len(project) - 1] software = project[len(project) - 2]
del project[len(project) - 1] return software + " (" + string.join(project[:(len(project) - 2)], '/') + ")"
return software + "(SR in /" + string.join(project, '/') + ")"
return "No Profile" return "No Profile"
def loadSoftwareData(runner_dir): def loadSoftwareData(runner_dir):
...@@ -430,6 +472,38 @@ def tail(f, lines=20): ...@@ -430,6 +472,38 @@ def tail(f, lines=20):
block -= 1 block -= 1
return string.join(''.join(data).splitlines()[-lines:], '\n') return string.join(''.join(data).splitlines()[-lines:], '\n')
def readFileFrom(f, lastPosition):
"""
Returns the last lines of file `f`, from position lastPosition.
and the last position
"""
BUFSIZ = 1024
f.seek(0, 2)
bytes = f.tell()
block = -1
data = ""
length = bytes
if lastPosition <= 0 and length > 50000:
lastPosition = 50000
size = bytes - lastPosition
while bytes > lastPosition:
if abs(block*BUFSIZ) <= size:
# Seek back one whole BUFSIZ
f.seek(block * BUFSIZ, 2)
data = f.read(BUFSIZ) + data
else:
margin = abs(block*BUFSIZ) - size
if length < BUFSIZ:
f.seek(0,0)
else:
seek = block * BUFSIZ + margin
f.seek(seek, 2)
data = f.read(BUFSIZ - margin) + data
bytes -= BUFSIZ
block -= 1
f.close()
return {"content":data, "position":length}
def isText(file): def isText(file):
"""Return True if the mimetype of file is Text""" """Return True if the mimetype of file is Text"""
if not os.path.exists(file): if not os.path.exists(file):
...@@ -456,3 +530,22 @@ def md5sum(file): ...@@ -456,3 +530,22 @@ def md5sum(file):
return m.hexdigest() return m.hexdigest()
except: except:
return False return False
def realpath(config, path, check_exist=True):
"""Get realpath of path or return False if user is not allowed to access to
this file"""
split_path = path.split('/')
key = split_path[0]
allow_list = {'software_root':config['software_root'], 'instance_root':
config['instance_root'], 'workspace': config['workspace']}
if allow_list.has_key(key):
del split_path[0]
path = os.path.join(allow_list[key], string.join(split_path, '/'))
if check_exist:
if os.path.exists(path):
return path
else:
return False
else:
return path
return False
\ No newline at end of file
...@@ -4,7 +4,7 @@ from utils import * ...@@ -4,7 +4,7 @@ from utils import *
import os import os
import shutil import shutil
import md5 import md5
from gittools import cloneRepo, gitStatus, switchBranch, createBranch, getDiff, \ from gittools import cloneRepo, gitStatus, switchBranch, addBranch, getDiff, \
gitPush, gitPull gitPush, gitPull
app = Flask(__name__) app = Flask(__name__)
...@@ -23,7 +23,7 @@ def home(): ...@@ -23,7 +23,7 @@ def home():
@app.route('/configRepo') @app.route('/configRepo')
def configRepo(): def configRepo():
public_key = open(app.config['public_key'], 'r').read() public_key = open(app.config['public_key'], 'r').read()
return render_template('cloneRepository.html', workDir=app.config['workspace'], public_key=public_key) return render_template('cloneRepository.html', workDir='workspace', public_key=public_key)
# software views # software views
@app.route('/editSoftwareProfile') @app.route('/editSoftwareProfile')
...@@ -31,12 +31,8 @@ def editSoftwareProfile(): ...@@ -31,12 +31,8 @@ def editSoftwareProfile():
profile = getProfilePath(app.config['runner_workdir'], app.config['software_profile']) profile = getProfilePath(app.config['runner_workdir'], app.config['software_profile'])
if profile == "": if profile == "":
flash('Error: can not open profile, please select your project first') flash('Error: can not open profile, please select your project first')
return render_template('updateSoftwareProfile.html', return render_template('updateSoftwareProfile.html', workDir='workspace',
profile=profile) profile=profile, projectList=getProjectList(app.config['workspace']))
@app.route('/software.cfg', methods=['GET', 'POST'])
def getSoftware():
return getProfile(app.config['runner_workdir'], app.config['software_profile'])
@app.route('/inspectSoftware', methods=['GET']) @app.route('/inspectSoftware', methods=['GET'])
def inspectSoftware(): def inspectSoftware():
...@@ -44,7 +40,7 @@ def inspectSoftware(): ...@@ -44,7 +40,7 @@ def inspectSoftware():
result = "" result = ""
else: else:
result = app.config['software_root'] result = app.config['software_root']
return render_template('runResult.html', softwareRoot=app.config['software_root'], return render_template('runResult.html', softwareRoot='software_root',
softwares=loadSoftwareData(app.config['runner_workdir'])) softwares=loadSoftwareData(app.config['runner_workdir']))
@app.route('/removeSoftware') @app.route('/removeSoftware')
...@@ -59,13 +55,12 @@ def removeSoftware(): ...@@ -59,13 +55,12 @@ def removeSoftware():
flash('Software removed') flash('Software removed')
return redirect(url_for('inspectSoftware')) return redirect(url_for('inspectSoftware'))
@app.route('/runSoftwareProfile', methods=['GET']) @app.route('/runSoftwareProfile', methods=['POST'])
def runSoftwareProfile(): def runSoftwareProfile():
if runSoftwareWithLock(app.config): if runSoftwareWithLock(app.config):
flash('Started.') return jsonify(result = True)
else: else:
flash('Already running.') return jsonify(result = False)
return redirect(url_for('viewSoftwareLog'))
@app.route('/viewSoftwareLog', methods=['GET']) @app.route('/viewSoftwareLog', methods=['GET'])
def viewSoftwareLog(): def viewSoftwareLog():
...@@ -73,8 +68,8 @@ def viewSoftwareLog(): ...@@ -73,8 +68,8 @@ def viewSoftwareLog():
result = tail(open(app.config['software_log'], 'r'), lines=1500) result = tail(open(app.config['software_log'], 'r'), lines=1500)
else: else:
result = 'Not found yet' result = 'Not found yet'
return render_template('viewLog.html', type='Software', return render_template('viewLog.html', type='software',
result=result, running=isSoftwareRunning(app.config)) result=result)
# instance views # instance views
@app.route('/editInstanceProfile') @app.route('/editInstanceProfile')
...@@ -82,25 +77,21 @@ def editInstanceProfile(): ...@@ -82,25 +77,21 @@ def editInstanceProfile():
profile = getProfilePath(app.config['runner_workdir'], app.config['instance_profile']) profile = getProfilePath(app.config['runner_workdir'], app.config['instance_profile'])
if profile == "": if profile == "":
flash('Error: can not open instance profile for this Software Release') flash('Error: can not open instance profile for this Software Release')
return render_template('updateInstanceProfile.html', return render_template('updateInstanceProfile.html', workDir='workspace',
profile=profile) profile=profile, projectList=getProjectList(app.config['workspace']))
@app.route('/instance.cfg', methods=['GET', 'POST'])
def getInstance():
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 = '' file_content = ''
result = '' result = ''
if os.path.exists(app.config['instance_root']): if os.path.exists(app.config['instance_root']):
file_content = app.config['instance_root'] file_content = 'instance_root'
result = getSvcStatus(app.config) result = getSvcStatus(app.config)
if len(result) == 0: if len(result) == 0:
result = [] result = []
return render_template('instanceInspect.html', return render_template('instanceInspect.html',
file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config), file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config),
supervisore=result, base_dir=app.config['runner_workdir']) supervisore=result)
@app.route('/removeInstance') @app.route('/removeInstance')
def removeInstance(): def removeInstance():
...@@ -111,15 +102,14 @@ def removeInstance(): ...@@ -111,15 +102,14 @@ def removeInstance():
flash('Instance removed') flash('Instance removed')
return redirect(url_for('inspectInstance')) return redirect(url_for('inspectInstance'))
@app.route('/runInstanceProfile', methods=['GET']) @app.route('/runInstanceProfile', methods=['POST'])
def runInstanceProfile(): def runInstanceProfile():
if not os.path.exists(app.config['instance_root']): if not os.path.exists(app.config['instance_root']):
os.mkdir(app.config['instance_root']) os.mkdir(app.config['instance_root'])
if runInstanceWithLock(app.config): if runInstanceWithLock(app.config):
flash('Started.') return jsonify(result = True)
else: else:
flash('Already running.') return jsonify(result = False)
return redirect(url_for('viewInstanceLog'))
@app.route('/viewInstanceLog', methods=['GET']) @app.route('/viewInstanceLog', methods=['GET'])
def viewInstanceLog(): def viewInstanceLog():
...@@ -127,8 +117,8 @@ def viewInstanceLog(): ...@@ -127,8 +117,8 @@ def viewInstanceLog():
result = open(app.config['instance_log'], 'r').read() result = open(app.config['instance_log'], 'r').read()
else: else:
result = 'Not found yet' result = 'Not found yet'
return render_template('viewLog.html', type='Instance', return render_template('viewLog.html', type='instance',
result=result, running=isInstanceRunning(app.config)) result=result)
@app.route('/stopAllPartition', methods=['GET']) @app.route('/stopAllPartition', methods=['GET'])
def stopAllPartition(): def stopAllPartition():
...@@ -165,23 +155,22 @@ def viewBuildoudAnnotate(): ...@@ -165,23 +155,22 @@ def viewBuildoudAnnotate():
@app.route('/openProject/<method>', methods=['GET']) @app.route('/openProject/<method>', methods=['GET'])
def openProject(method): def openProject(method):
return render_template('projectFolder.html', method=method, return render_template('projectFolder.html', method=method,
workDir=app.config['workspace']) workDir='workspace')
@app.route('/cloneRepository', methods=['POST']) @app.route('/cloneRepository', methods=['POST'])
def cloneRepository(): def cloneRepository():
path = realpath(app.config, request.form['name'], False)
data = {"repo":request.form['repo'], "user":request.form['user'], data = {"repo":request.form['repo'], "user":request.form['user'],
"email":request.form['email']} "email":request.form['email'], "path":path}
name = request.form['name']
data['path'] = os.path.join(app.config['workspace'], name)
return cloneRepo(data) return cloneRepo(data)
@app.route('/readFolder', methods=['POST']) @app.route('/readFolder', methods=['POST'])
def readFolder(): def readFolder():
return getFolderContent(request.form['dir']) return getFolderContent(app.config, request.form['dir'])
@app.route('/openFolder', methods=['POST']) @app.route('/openFolder', methods=['POST'])
def openFolder(): def openFolder():
return getFolder(request.form['dir']) return getFolder(app.config, request.form['dir'])
@app.route('/createSoftware', methods=['POST']) @app.route('/createSoftware', methods=['POST'])
def createSoftware(): def createSoftware():
...@@ -191,10 +180,9 @@ def createSoftware(): ...@@ -191,10 +180,9 @@ def createSoftware():
def checkFolder(): def checkFolder():
return checkSoftwareFolder(request.form['path'], app.config) return checkSoftwareFolder(request.form['path'], app.config)
@app.route("/setCurentProject", methods=['POST']) @app.route("/setCurrentProject", methods=['POST'])
def setCurentProject(): def setCurrentProject():
folder = request.form['path'] if configNewSR(app.config, request.form['path']):
if configNewSR(app.config, folder):
session['title'] = getProjectTitle(app.config) session['title'] = getProjectTitle(app.config)
return jsonify(code=1, result="") return jsonify(code=1, result="")
else: else:
...@@ -202,28 +190,37 @@ def setCurentProject(): ...@@ -202,28 +190,37 @@ def setCurentProject():
@app.route("/manageProject", methods=['GET']) @app.route("/manageProject", methods=['GET'])
def manageProject(): def manageProject():
return render_template('manageProject.html', workDir=app.config['workspace'], return render_template('manageProject.html', workDir='workspace',
project=getProjectList(app.config['workspace'])) project=getProjectList(app.config['workspace']))
@app.route("/getProjectStatus", methods=['POST']) @app.route("/getProjectStatus", methods=['POST'])
def getProjectStatus(): def getProjectStatus():
return gitStatus(request.form['project']) path = realpath(app.config, request.form['project'])
if path:
return gitStatus(path)
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@app.route("/curentSoftware") @app.route("/editCurrentProject")
def curentSoftware(): def editCurrentProject():
project = os.path.join(app.config['runner_workdir'], ".project") project = os.path.join(app.config['runner_workdir'], ".project")
if os.path.exists(project): if os.path.exists(project):
return render_template('softwareFolder.html', workDir=app.config['workspace'], return render_template('softwareFolder.html', workDir='workspace',
project=open(project).read()) project=open(project).read(),
projectList=getProjectList(app.config['workspace']))
return redirect(url_for('configRepo')) return redirect(url_for('configRepo'))
@app.route("/createFile", methods=['POST']) @app.route("/createFile", methods=['POST'])
def createFile(): def createFile():
path = realpath(app.config, request.form['file'], False)
if not path:
return jsonify(code=0, result="Error when creating your " + \
request.form['type'] + ": Permission Denied")
try: try:
if request.form['type'] == "file": if request.form['type'] == "file":
f = open(request.form['file'], 'w').write(" ") f = open(path, 'w').write(" ")
else: else:
os.mkdir(request.form['file']) os.mkdir(path)
return jsonify(code=1, result="") return jsonify(code=1, result="")
except Exception, e: except Exception, e:
return jsonify(code=0, result=str(e)) return jsonify(code=0, result=str(e))
...@@ -245,30 +242,43 @@ def removeSoftwareDir(): ...@@ -245,30 +242,43 @@ def removeSoftwareDir():
@app.route("/getFileContent", methods=['POST']) @app.route("/getFileContent", methods=['POST'])
def getFileContent(): def getFileContent():
if os.path.exists(request.form['file']): file_path = realpath(app.config, request.form['file'])
if file_path:
if not request.form.has_key('truncate'): if not request.form.has_key('truncate'):
return jsonify(code=1, result=open(request.form['file'], 'r').read()) return jsonify(code=1, result=open(file_path, 'r').read())
else: else:
content = tail(open(request.form['file'], 'r'), int(request.form['truncate'])) content = tail(open(file_path, 'r'), int(request.form['truncate']))
return jsonify(code=1, result=content) return jsonify(code=1, result=content)
else: else:
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@app.route("/saveFileContent", methods=['POST']) @app.route("/saveFileContent", methods=['POST'])
def saveFileContent(): def saveFileContent():
if os.path.exists(request.form['file']): file_path = realpath(app.config, request.form['file'])
open(request.form['file'], 'w').write(request.form['content']) if file_path:
open(file_path, 'w').write(request.form['content'])
return jsonify(code=1, result="") return jsonify(code=1, result="")
else: else:
return jsonify(code=0, result="Error: No such file!") return jsonify(code=0, result="Error: No such file!")
@app.route("/changeBranch", methods=['POST']) @app.route("/changeBranch", methods=['POST'])
def changeBranch(): def changeBranch():
return switchBranch(request.form['project'], request.form['name']) path = realpath(app.config, request.form['project'])
if path:
return switchBranch(path, request.form['name'])
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@app.route("/newBranch", methods=['POST']) @app.route("/newBranch", methods=['POST'])
def newBranch(): def newBranch():
return createBranch(request.form['project'], request.form['name']) path = realpath(app.config, request.form['project'])
if path:
if request.form['create'] == '1':
return addBranch(path, request.form['name'])
else:
return addBranch(path, request.form['name'], True)
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@app.route("/getProjectDiff/<project>", methods=['GET']) @app.route("/getProjectDiff/<project>", methods=['GET'])
def getProjectDiff(project): def getProjectDiff(project):
...@@ -278,24 +288,73 @@ def getProjectDiff(project): ...@@ -278,24 +288,73 @@ def getProjectDiff(project):
@app.route("/pushProjectFiles", methods=['POST']) @app.route("/pushProjectFiles", methods=['POST'])
def pushProjectFiles(): def pushProjectFiles():
return gitPush(request.form['project'], request.form['msg']) path = realpath(app.config, request.form['project'])
if path:
return gitPush(path, request.form['msg'])
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@app.route("/pullProjectFiles", methods=['POST']) @app.route("/pullProjectFiles", methods=['POST'])
def pullProjectFiles(): def pullProjectFiles():
return gitPull(request.form['project']) path = realpath(app.config, request.form['project'])
if path:
return gitPull(path)
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
@app.route("/checkFileType", methods=['POST']) @app.route("/checkFileType", methods=['POST'])
def checkFileType(): def checkFileType():
path = request.form['path'] path = realpath(app.config, request.form['path'])
if not path:
return jsonify(code=0, result="Can not open file: Permission Denied!")
if isText(path): if isText(path):
return jsonify(code=1, result="text") return jsonify(code=1, result="text")
else: else:
return jsonify(code=0, result="You can only open text files!") return jsonify(code=0, result="Can not open a binary file, please select a text file!")
@app.route("/getmd5sum", methods=['POST']) @app.route("/getmd5sum", methods=['POST'])
def getmd5sum(): def getmd5sum():
md5 = md5sum(request.form['file']) realfile = realpath(app.config, request.form['file'])
if not realfile:
return jsonify(code=0, result="Can not open file: Permission Denied!")
md5 = md5sum(realfile)
if md5: if md5:
return jsonify(code=1, result=md5) return jsonify(code=1, result=md5)
else: else:
return jsonify(code=0, result="Can not get md5sum for this file!") return jsonify(code=0, result="Can not get md5sum for this file!")
@app.route("/slapgridResult", methods=['POST'])
def slapgridResult():
software_state = isSoftwareRunning(app.config)
instance_state = isInstanceRunning(app.config)
log_result = {"content":"", "position":0}
if request.form['log'] == "software" or\
request.form['log'] == "instance":
log_file = request.form['log'] + "_log"
if os.path.exists(app.config[log_file]):
log_result = readFileFrom(open(app.config[log_file], 'r'),
int(request.form['position']))
return jsonify(software=software_state, instance=instance_state,
result=(instance_state or software_state), content=log_result)
@app.route("/stopSlapgrid", methods=['POST'])
def stopSlapgrid():
result = killRunningSlapgrid(app.config, request.form['type'])
return jsonify(result=result)
@app.route("/getPath", methods=['POST'])
def getPath():
files = request.form['file'].split('#')
list = []
for p in files:
path = realpath(app.config, p)
if not p:
list = []
break
else:
list.append(path)
realfile = string.join(list, "#")
if not realfile:
return jsonify(code=0, result="Can not access to this file: Permission Denied!")
else:
return jsonify(code=1, result=realfile)
\ 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