Added stop job option

This commit is contained in:
itsikkes 2016-07-07 08:56:06 +03:00
parent 5d1a3680b2
commit 1449f1ef93
5 changed files with 138 additions and 21 deletions

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Monkeys Admin</title> <title>Monkeys Business</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<!-- js --> <!-- js -->
@ -93,29 +93,35 @@
Configure Auto Tester Configure Auto Tester
</button> </button>
</span> </span>
<br/>
<!-- General options --> <!-- General options -->
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<a href="#newJob" data-toggle="collapse">New Job</a> <a href="#newJob" data-toggle="collapse">Job Properties</a>
</div> </div>
<div id="newJob" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true"> <div id="newJob" style="overflow: visible" class="panel-body panel-collapse collapse in" aria-expanded="true">
<div id="job-config-section"> <div id="job-config-section">
<div id="job-config"> <div id="job-config">
</div> </div>
<button id="btnSendJob" class="btn btn-default" type="button" <button id="btnSendJob" class="btn btn-default" type="button"
onclick="sendJob()" style="margin-top:-4px; visibility: hidden"> onclick="sendJob()" style="margin-top:-4px; visibility: hidden">
Update Update
</button> </button>
<button id="btnDeleteJob" class="btn btn-default" type="button" <button id="btnDeleteJob" class="btn btn-default" type="button"
onclick="deleteJob()" style="margin-top:-4px; visibility: hidden"> onclick="deleteJob()" style="margin-top:-4px; visibility: hidden">
Delete Delete
</button>
<button id="btnStopJob" class="btn btn-default" type="button"
onclick="stopJob()" style="margin-top:-4px; visibility: hidden">
Stop
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- /.General options --> <!-- /.General options -->
</div> </div>
</div> </div>
</div> </div>

View File

@ -71,13 +71,37 @@ function updateJobs() {
var jobsList = json.objects; var jobsList = json.objects;
for (var i = 0; i < jobsList.length; i++) { for (var i = 0; i < jobsList.length; i++) {
jobsTable.row.add([jobsList[i].id, jobsList[i].creation_time, jobsList[i].type,jobsList[i].state, JSON.stringify(jobsList[i].properties)]); r = jobsTable.row.add([jobsList[i].id, jobsList[i].creation_time, jobsList[i].type,jobsList[i].state, JSON.stringify(jobsList[i].properties)]);
$(this).addClass('selected');
if (jobsList[i].id == selectedJob) {
jobsTable.row(r[0]).nodes().to$().addClass( 'selected' );
}
} }
jobsTable.draw(); jobsTable.draw();
}); });
} }
function stopJob() {
$.ajax({
headers : {
'Accept' : 'application/json',
},
url : '/job?action=stop&id=' + selectedJob,
type : 'GET',
success : function(response, textStatus, jqXhr) {
console.log("Stopped job");
},
error : function(jqXHR, textStatus, errorThrown) {
// log the error to the console
console.log("The following error occured: " + textStatus, errorThrown);
},
complete : function() {
console.log("Trying to stop job...");
}
});
}
function loadConnectorsConfig() { function loadConnectorsConfig() {
elem = document.getElementById('connectors-config'); elem = document.getElementById('connectors-config');
elem.innerHTML = "" elem.innerHTML = ""
@ -134,8 +158,8 @@ function updateConnectorConfig() {
} }
function emptySelection() { function emptySelection() {
showLog();
selectedJob = undefined; selectedJob = undefined;
showLog();
jobsTable.$('tr.selected').removeClass('selected'); jobsTable.$('tr.selected').removeClass('selected');
} }
@ -146,6 +170,9 @@ function createNewJob(id, state) {
elem = document.getElementById('job-config'); elem = document.getElementById('job-config');
elem.innerHTML = "" elem.innerHTML = ""
document.getElementById("btnSendJob").style.visibility = "hidden";
document.getElementById("btnDeleteJob").style.visibility = "hidden";
document.getElementById("btnStopJob").style.visibility = "hidden";
jobCfg = new JSONEditor(elem,{ jobCfg = new JSONEditor(elem,{
schema: { schema: {
type: "object", type: "object",
@ -170,8 +197,10 @@ function createNewJob(id, state) {
jobCfg.on('ready',function() { jobCfg.on('ready',function() {
if (id && state != "pending") { if (id && state != "pending") {
jobCfg.disable(); jobCfg.disable();
document.getElementById("btnSendJob").style.visibility = "hidden"; if (state == "running") {
document.getElementById("btnDeleteJob").style.visibility = "hidden"; document.getElementById("btnStopJob").style.visibility = "visible";
}
} }
else { else {
jobCfg.enable(); jobCfg.enable();
@ -179,9 +208,6 @@ function createNewJob(id, state) {
if (id) { if (id) {
document.getElementById("btnDeleteJob").style.visibility = "visible"; document.getElementById("btnDeleteJob").style.visibility = "visible";
} }
else {
document.getElementById("btnDeleteJob").style.visibility = "hidden";
}
} }
}); });
} }

View File

@ -59,8 +59,11 @@ class VCenterConnector(NetControllerConnector):
objview.Destroy() objview.Destroy()
return self._cache["vlans"] return self._cache["vlans"]
def get_entities_on_vlan(self, vlanid): def get_vm(self, vmname):
return [] if not self.is_connected():
self.connect()
vcontent = self._service_instance.RetrieveContent() # get updated vsphare state
return self._get_obj(vcontent, [vim.VirtualMachine], vmname)
def deploy_monkey(self, vm_name): def deploy_monkey(self, vm_name):
if not self._properties["monkey_template_name"]: if not self._properties["monkey_template_name"]:
@ -99,6 +102,14 @@ class VCenterConnector(NetControllerConnector):
task = vm_obj.PowerOnVM_Task() task = vm_obj.PowerOnVM_Task()
return self._wait_for_task(task) return self._wait_for_task(task)
def power_off(self, vm_obj):
task = vm_obj.PowerOffVM_Task()
return self._wait_for_task(task)
def destroy(self, vm_obj):
task = vm_obj.Destroy_Task()
return self._wait_for_task(task)
def disconnect(self): def disconnect(self):
Disconnect(self._service_instance) Disconnect(self._service_instance)
self._service_instance = None self._service_instance = None
@ -242,3 +253,19 @@ class VCenterJob(NetControllerJob):
return True return True
def stop(self):
if not self._connector:
return False
if not self._vm_obj:
self._vm_obj = self._connector.get_vm(self._properties["vm_name"])
if not self._vm_obj:
self.log("Error: Couldn't find VM %s" % self._properties["vm_name"])
return False
self.log("Stopping: %s" % self._properties["vm_name"])
self._connector.power_off(self._vm_obj)
self._connector.destroy(self._vm_obj)
return True

View File

@ -30,11 +30,18 @@ class Job(restful.Resource):
if action == "log": if action == "log":
return {"log": get_job_log(id)} return {"log": get_job_log(id)}
elif action == "stop":
job = mongo.db.job.find_one_or_404({"_id": bson.ObjectId(id)})
if "running" == job.get("state"):
tasks_manager.stop_task.delay(bson.ObjectId(id))
return {'status': 'ok'}
else:
return {'status': 'failed'}
result = {} result = {}
if id: if id:
return mongo.db.job.find_one_or_404({"_id": id}) return mongo.db.job.find_one_or_404({"_id": bson.ObjectId(id)})
else: else:
result['timestamp'] = datetime.now().isoformat() result['timestamp'] = datetime.now().isoformat()
@ -49,7 +56,7 @@ class Job(restful.Resource):
if job_json.has_key('pk'): if job_json.has_key('pk'):
job = mongo.db.job.find_one_or_404({"pk": job_json["pk"]}) job = mongo.db.job.find_one_or_404({"pk": job_json["pk"]})
if "pending" != job.get("status"): if "pending" != job.get("state"):
res = {"status": "cannot change job at this state", "res" : 0} res = {"status": "cannot change job at this state", "res" : 0}
return res return res
if "delete" == job_json["action"]: if "delete" == job_json["action"]:

View File

@ -96,12 +96,31 @@ class JobExecution(object):
self._log_resutls(res) self._log_resutls(res)
return True return True
def stop(self):
self.log("Trying to stop...")
res = None
try:
res = self._job.stop()
except Exception, e:
self.log("Exception raised while running: %s" % e)
self.update_job_state("error")
return False
if res:
self.log("Done stop job")
self.update_job_state("ended")
else:
self.log("Job stopping error")
self.update_job_state("error")
return res
@celery.task @celery.task
def run_task(jobid): def run_task(jobid):
print "searching for ", jobid acquire_task = mongo.db.job.update({"_id": jobid, "state": "pending"}, {"$set": {"state": "processing"}})
aquire_task = mongo.db.job.update({"_id": jobid, "state": "pending"}, {"$set": {"state": "processing"}}) if acquire_task["nModified"] != 1:
if aquire_task["nModified"] != 1:
return False return False
job_info = mongo.db.job.find_one({"_id": jobid}) job_info = mongo.db.job.find_one({"_id": jobid})
@ -128,6 +147,38 @@ def run_task(jobid):
return "done task: " + run_task.request.id return "done task: " + run_task.request.id
@celery.task
def stop_task(jobid):
acquire_task = mongo.db.job.update({"_id": jobid, "state": "running"}, {"$set": {"state": "stopping"}})
if acquire_task["nModified"] != 1:
print "could not acquire lock on job"
return False
job_info = mongo.db.job.find_one({"_id": jobid})
if not job_info:
print "could not get job info"
return False
job_exec = None
try:
job_exec = JobExecution(mongo, job_info)
except Exception, e:
print "init JobExecution exception - ", e
return False
if not job_exec.get_job():
job_exec.update_job_state("error")
return False
job_exec.get_results()
if not job_exec.stop():
print "error stopping"
return False
return "done stop_task"
@celery.task @celery.task
def update_cache(connector): def update_cache(connector):
time.sleep(30) time.sleep(30)