"FS_IMAGE_ADD_TO": "ws/fs/image/add/to",
"FS_IMAGE_ADD_FINISH": "ws/fs/image/add/finish",
"FS_IMAGE_ADD_FAIL": "ws/fs/image/add/fail",
+ "FS_IMAGE_ADD_CANCEL": "ws/fs/image/add/cancel",
"FS_IMAGE_ADD_KILL": "ws/fs/image/add/kill",
"MIC_AVAILABLE_FROM": "ws/mic/available/from",
"MIC_AVAILABLE_TO": "ws/mic/available/to",
var Mic = {};
-/**
- * Process Manager
- * ObjectArray
- * processMgr = {
- * 'jobId': jobId,
- * 'jobProcessId': pid
- * });
- */
-var processMgr = [];
-
Mic.hasNextJob = function hasNextJob(callback) {
function onSuccess(rows) {
var queueCnt, hasNext;
}
Mic.kill = function kill(paramObj) {
- var strJobId, psIndex, psObj, psId;
- logger.info('MIC Kill: paramObj = ' + JSON.stringify(paramObj));
-
- strJobId = paramObj.jobId;
+ var jobId, jobPid;
+ logger.info('Mic.Kill: ' + JSON.stringify(paramObj));
- psIndex = _.findIndex(processMgr, function (o) {
- return o.jobId == strJobId;
- })
+ // set values
+ jobId = paramObj.jobId;
+ jobPid = paramObj.jobPid;
// when not exists
- if (psIndex < 0) {
+ if (!jobId || !jobPid) {
return;
}
- psObj = processMgr[psIndex];
- psId = psObj.jobProcessId;
-
- TreeKill(psId, 'SIGKILL');
- processMgr.pop(psIndex);
+ TreeKill(jobPid, 'SIGKILL');
}
Mic.process = function process(command, callback, jobId) {
+ var ps, psOptions;
// execution
- var ps = exec(command);
-
- // Process Manager - add
- processMgr.push({
- 'jobId': jobId,
- 'jobProcessId': ps.pid
- });
-
+ ps = exec(command);
ps.stdout.on('data', callback.stdout || function (out) {
process.stdout.write(out);
});
process.stdout.write(err);
});
ps.on('error', callback.error);
+ ps.on('close', callback.close);
ps.on('exit', callback.exit);
-
return ps;
};
micCommand,
{
stdout: function (out) {
- logger.info(out);
+ logger.info('MICProcess.stdout:' + out);
sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO, {
msg: out,
jobId: strJobId
});
},
stderr: function (out) {
- logger.info(out);
+ logger.info('MICProcess.stderr:' + out);
sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO, {
msg: out,
jobId: strJobId
});
},
error: function (out) {
- logger.info(out);
+ logger.error('MICProcess.error:' + out);
sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FAIL, 'Failed (' + code + ')');
},
+ close: function (code) {
+ logger.info('MICProcess.colse: all process were closed.')
+ },
exit: function (code) {
- // code is the final exit code of the process
- var psIndex = _.findIndex(processMgr, function (o) {
- return o.jobId == strJobId;
- });
- if (psIndex >= 0) {
- processMgr.pop(psIndex);
- }
-
- logger.info('Terminated (' + code + ')');
- if (code === 0) {
+ logger.info('MICProcess.exit: Terminated (' + code + ')');
+ if (!code) {
+ sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_CANCEL, {
+ msg: 'Canceled (' + code + ')',
+ jobId: strJobId
+ });
+ } else if (code === 0) {
sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH, {
msg: 'Terminated (' + code + ')',
jobId: strJobId,
});
/**
- * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM = 'ws/mic/nextjob/from'
+ * AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_FROM = 'ws/mic/nextjob/from'
*/
socket.on(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_FROM, function () {
Mic.hasNextJob(function (hasNext) {
color: #337ab7;
display: table-cell;
}
-.job-status-cancel, .job-status-failed {
+.job-status-cancel {
+ font-size: 2vh;
+ color: #2d2222;
+ display: table-cell;
+}
+.job-status-failed {
font-size: 2vh;
color: #e05151;
display: table-cell;
this.jobStatusClass = null;
this.jobImageName = null;
this.jobImageSize = null;
+ this.jobPid = null;
this.jobPath = null;
this.jobImagePath = null;
this.jobHasKsFile = false;
this.setJobStatus(obj.job_status);
this.setJobImageName(obj.job_image_name);
this.setJobImageSize(obj.job_image_size);
+ this.setJobPid(obj.job_pid);
this.setJobHasKsFile(obj.job_hasksfile);
this.setJobKs(obj.job_ks);
this.jobImageSize = value ? Util.bytesToSize(value) : '0KB';
};
+ JobModel.prototype.getJobPid = function () {
+ return this.jobPid;
+ };
+
+ JobModel.prototype.setJobPid = function (value) {
+ this.jobPid = value || null;
+ };
+
JobModel.prototype.getJobPath = function () {
return this.jobPath;
};
// const
var JOB_STATUS_DONE = 'DONE';
+ var JOB_STATUS_READY = 'READY';
var JOB_STATUS_INPROGRESS = 'INPROGRESS';
+ var JOB_STATUS_CANCELED = 'CANCELED';
var JOB_STATUS_FAILED = 'FAILED';
var USER_DEFAULT = 'GUEST';
// bind events - cancel button
$('#tic-job-table a.btncancel').on('click', function (e) {
- var msgData, jobId;
+ var msgData, jobId, jobPid, jobStatus;
+
e.preventDefault();
+ // btn disabled
$(this).addClass('btnnotactive');
+ // checks that the status of job, whether ready or inprogress or not
+ jobStatus = $(this).data('jobstatus');
+ if (!(jobStatus === JOB_STATUS_READY || jobStatus === JOB_STATUS_INPROGRESS)) {
+ return;
+ }
+
jobId = $(this).data('jobid');
+ jobPid = $(this).data('jobpid');
+
+ if (jobStatus === JOB_STATUS_INPROGRESS) {
+ if (!jobPid) {
+ return;
+ }
+ }
+
msgData = {
- jobId: jobId
+ jobId: jobId,
+ job_status: JOB_STATUS_CANCELED,
+ jobPid: jobPid,
+ job_updater: UserInfo.email
};
- client.emit(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_KILL, msgData);
+ if (jobStatus === JOB_STATUS_READY) {
+ // update job_status
+ Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + jobId, msgData)
+ .then(function () {
+ updateList();
+ });
+ } else if (jobStatus === JOB_STATUS_INPROGRESS) {
+ // kill
+ client.emit(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_KILL, msgData);
+ }
});
}
job_updater: UserInfo.email
};
logger.info('MIC_ADD_PID_JOB_TO: ' + JSON.stringify(msgObj));
- Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + dataObj.jobId, msgObj);
+ // update tic_job;
+ return Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + dataObj.jobId, msgObj);
});
/**
updateList(ModelJobPaging.getCurrentPoint());
});
});
+
+ /**
+ * when canceled
+ *
+ * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_CANCEL = 'ws/fs/image/add/cancel'
+ */
+ client.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_CANCEL, function (dataObj) {
+ var jobId, msgObj;
+
+ // jobId
+ jobId = dataObj.jobId;
+
+ // log
+ new JobLog(dataObj);
+
+ // log
+ new JobLog({
+ msg: 'Canceled to create an image.',
+ jobId: jobId
+ });
+
+ // notification popup
+ Util.showAlertDialog('Canceled to create an image. The #ID is ' + jobId + '.');
+
+ // update the status
+ msgObj = {
+ jobId: jobId,
+ job_status: JOB_STATUS_CANCELED,
+ job_updater: UserInfo.email
+ };
+ Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + jobId, msgObj)
+ .then(checksNextJob)
+ .then(function () {
+ // upate the list of jobs
+ updateList(ModelJobPaging.getCurrentPoint());
+ });
+
+ });
}
/**
'<td><a class="tic-job-list-btn btndownload <%= classJobImageDownload %>" href="<%= jobImagePath %>" title="<%= jobImageName %>">Download</a></td>',
'<td><%= jobImageSize %></td>',
'<td><%= jobUptime %></td>',
- '<td><a class="tic-job-list-btn btncancel <%= classJobCancel %>" title="Cancel">Cancel</a></td>',
+ '<td><a class="tic-job-list-btn btncancel <%= classJobCancel %>" data-jobid="<%= jobNum %>" data-jobpid="<%= jobPid %>" data-jobstatus="<%= jobStatusValue %>" title="Cancel">Cancel</a></td>',
'<td><a class="tic-job-list-btn <%= classJobKsPath %>" href="<%= jobKsPath %>" title="Kickstarter File">KS</a></td>',
'<td><a class="tic-job-list-btn btnbiglog" data-link="<%= jobLogPath %>" data-jobid="<%= jobNum %>" title="Log">Log</a></td>',
'</tr>'
'<td><a class="tic-job-list-btn btndownload btnnotactive">Download</a></td>',
'<td><%= jobImageSize %></td>',
'<td><%= jobUptime %></td>',
- '<td><a class="tic-job-list-btn btncancel <%= classJobCancel %>" data-jobid="<%= jobNum %>" title="Cancel">Cancel</a></td>',
+ '<td><a class="tic-job-list-btn btncancel <%= classJobCancel %>" data-jobid="<%= jobNum %>" data-jobpid="<%= jobPid %>" data-jobstatus="<%= jobStatusValue %>" title="Cancel">Cancel</a></td>',
'<td><a class="tic-job-list-btn <%= classJobKsPath %>" href="<%= jobKsPath %>" title="Kickstarter File">KS</a></td>',
'<td><a class="tic-job-list-btn btnbiglog btnbiglogex" data-link="<%= jobLogPath %>" data-jobid="<%= jobNum %>" title="Log">Log</a></td>',
'</tr>',
];
var JOB_STATUS_INPROGRESS = 'INPROGRESS';
+ var JOB_STATUS_READY = 'READY';
var JOB_STATUS_DONE = 'DONE';
var USER_GROUP_ADMIN = 'ADMIN';
var USER_GROUP_MASTER = 'MASTER';
userGroup = data.getJobUserGroup();
cssCancelbtn = '';
if (userGroup === USER_GROUP_ADMIN || userGroup === USER_GROUP_MASTER) {
- if (statusValue !== JOB_STATUS_INPROGRESS) {
+ // only when 'READY' or 'INPROGRESS', can cancel the job.
+ if (!(statusValue === JOB_STATUS_INPROGRESS || statusValue === JOB_STATUS_READY)) {
cssCancelbtn = 'btnnotactive';
}
} else {
'jobImageName': data.getJobImageName(),
'jobImageSize': data.getJobImageSize(),
'jobImagePath': data.getJobAbsImagePath(),
+ 'jobPid': data.getJobPid(),
+ 'jobStatusValue': data.getJobStatus(),
'classJobImageDownload': data.getJobStatus() === JOB_STATUS_DONE ? '' : 'btnnotactive',
'classJobCancel': getCssCancelbtn() ,
'classJobKsPath': data.getJobHasKsFile() === '0' ? 'btnnotactive' : '',
'jobImageName': data.getJobImageName(),
'jobImageSize': data.getJobImageSize(),
'jobImagePath': data.getJobAbsImagePath(),
+ 'jobPid': data.getJobPid(),
+ 'jobStatusValue': data.getJobStatus(),
'classJobCancel': getCssCancelbtn() ,
'classJobKsPath': data.getJobHasKsFile() === '0' ? 'btnnotactive' : '',
'jobKsPath': data.getJobAbsKsPath(),