From: Heekyoung, Oh Date: Mon, 17 Apr 2017 12:21:44 +0000 (+0900) Subject: [TIC-Web] The waiting queue added. for the image creation X-Git-Tag: v20170428~13^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a922d6e06caf35fa4524d95152266c0f47de9725;p=archive%2F20170607%2Ftools%2Ftic.git [TIC-Web] The waiting queue added. for the image creation - The waiting queue added. - The size of queue was 4. - The image creation can runned one by one. Change-Id: I5a10fceb0bec98852527f59af2cd53b97237a269 Signed-off-by: Heekyoung, Oh --- diff --git a/config.json b/config.json index 9e221cf..8485d2c 100644 --- a/config.json +++ b/config.json @@ -20,11 +20,12 @@ "HOST": "localhost", "TRACE": true, "DIALECT": "mariasql", + "PINGINACTIVE": 60000, + "PINGWAITRES": 60000, "POOL": { "MAX": 5, "MIN": 1, "IDLETIMEOUT": 500000, - "REAPINTERVAL": 500, "MAXWAITINGCLIENTS": 20 } }, @@ -36,15 +37,19 @@ "FS_IMAGE_ADD_FAIL": "ws/fs/image/add/fail", "FS_IMAGE_ADD_KILL": "ws/fs/image/add/kill", "MIC_AVAILABLE_FROM": "ws/mic/available/from", - "MIC_AVAILABLE_TO": "ws/mic/available/to" + "MIC_AVAILABLE_TO": "ws/mic/available/to", + "MIC_NEXT_JOB_FROM": "ws/mic/nextjob/from", + "MIC_NEXT_JOB_TO": "ws/mic/nextjob/to" }, "JOB": { - "JOB_GET_ALL_COUNT": "/api/job/count", + "JOB_GET_ALL_COUNT": "/api/job/count/all", + "JOB_GET_QUEUE_COUNT": "/api/job/count/queue", "JOB_GET_ALL_LISTITEM": "/api/job/list", "JOB_GET_BYID": "/api/job/", "JOB_ADD_ONE": "/api/job/add/", "JOB_EDIT_ONE": "/api/job/edit/", - "JOB_READ_LOG": "/api/job/log/" + "JOB_READ_LOG": "/api/job/log/", + "JOB_GET_NEXTJOB": "/api/job/queue/next" }, "PACKAGE": { "IMPORT": "/api/imports/", diff --git a/controller/dbpool.js b/controller/dbpool.js index 27d897d..c0e0ce0 100644 --- a/controller/dbpool.js +++ b/controller/dbpool.js @@ -23,69 +23,120 @@ var logger = JL('dbpool.js'); var AppConfig = require('../config.json'); -function dbPool () { - var self = this; +var createClient = function createClient (closeCallback) { + var configMariasql, mariasqlClient; - self.configMariasql = { + // config + configMariasql = { host: AppConfig.DATABASE.HOST, user: AppConfig.DATABASE.USERNAME, password: AppConfig.DATABASE.PASSWORD, db: AppConfig.DATABASE.DATABASE, trace: AppConfig.DATABASE.TRACE, - pingInactive: 60000, - pingWaitRes: 60000, + pingInactive: AppConfig.DATABASE.PINGINACTIVE, + pingWaitRes: AppConfig.DATABASE.PINGWAITRES, metadata: false }; - self.pool = generic_pool.createPool({ - name: AppConfig.DATABASE.DIALECT, - - create: function (callback) { - return new Promise(function (resolve, reject) { - var mariasqlClient = new mariasql(self.configMariasql); - mariasqlClient.connect(function (err) { - if (err) { - logger.error('DB Connection Error !'); - logger.error(err); - reject(err); - } - - logger.info('DB Connection Success !'); - resolve(mariasqlClient); - }); - }); - }, - - destroy: function (client) { - return new Promise(function (resolve, reject) { - client.on('end', function () { - resolve(); - }); - client.disconnect(); - client.end(); - client._handle = null; - }); - }, + mariasqlClient = new mariasql(configMariasql); - validate: function (client) { - return client.connected; - }, + mariasqlClient.on('ready', function () { + logger.info('DB Connection Success !'); + }).on('error', function (err) { + logger.error('DB Connection On Error ! (' + err.code + ') ' + err.message); + }).on('end', function () { + logger.info('DB Connection Ended !'); + }).on('close', function () { + logger.info('DB Connection Closed !'); + }); + + process.nextTick(function () { + if (typeof closeCallback === 'function') { + mariasqlClient.on('close', closeCallback); + } + mariasqlClient.on('close', function () { + mariasqlClient.end(); + }); + }) - max: AppConfig.DATABASE.POOL.MAX, + return mariasqlClient; +}; + +function DBPool () { + // pool + this.pool; + + this.init(); +}; - min: AppConfig.DATABASE.POOL.MIN, +DBPool.prototype.opts = { + name: AppConfig.DATABASE.DIALECT, - idleTimeoutMillis: AppConfig.DATABASE.POOL.IDLETIMEOUT, + max: AppConfig.DATABASE.POOL.MAX, - reapIntervalMillis: AppConfig.DATABASE.POOL.REAPINTERVAL, + min: AppConfig.DATABASE.POOL.MIN, - maxWaitingClients: AppConfig.DATABASE.POOL.MAXWAITINGCLIENTS, + idleTimeoutMillis: AppConfig.DATABASE.POOL.IDLETIMEOUT, + + maxWaitingClients: AppConfig.DATABASE.POOL.MAXWAITINGCLIENTS, + + autostart: true +}; + +DBPool.prototype.factory = { + create: function (callback) { + return new Promise(function (resolve, reject) { + var mariasqlClient; + + function closeCallback () { + reject(); + } + + // client + mariasqlClient = createClient(closeCallback); + mariasqlClient.connect(function () { + resolve(mariasqlClient); + }); + }); + }, - returnToHead: true + destroy: function (client) { + return new Promise(function (resolve, reject) { + client.on('end', function () { + resolve(); + }); + client.destroy(); + client.end(); + client._handle = null; + }); + }, + + validate: function (client) { + return client.connected; + } +}; + +DBPool.prototype.init = function init () { + this.pool = generic_pool.createPool(this.factory, this.opts); + + this.pool.on('factoryCreateError', function (err) { + if (err) { + logger.error(err.message); + throw err; + } + return; + }); + + this.pool.on('factoryDestroyError', function (err) { + if (err) { + logger.error(err.message); + throw err; + } + return; }); }; -dbPool.prototype.query = function query (query, params) { +DBPool.prototype.query = function query (query, params) { var mariaPool = this.pool; return new Promise (function (resolve, reject) { mariaPool.acquire().then(function (client) { @@ -97,21 +148,35 @@ dbPool.prototype.query = function query (query, params) { metadata: false }, function (err, rows) { if (err) { + logger.error('Error: ' + err.message); mariaPool.destroy(client); meta.result = err; - reject(meta); + return reject(meta); } meta.result = rows; mariaPool.release(client); logger.info(JSON.stringify(meta)); - resolve(meta); + return resolve(meta); }); }).catch(function (err) { logger.error(err.message); - reject(err); + return reject(err); }); }); }; -module.exports = dbPool; +DBPool.prototype.clearAll = function clearAll () { + var mariaPool = this.pool; + mariaPool.drain(function () { + mariaPool.clear(); + }); +}; + +var dbPool = new DBPool(); + +process.on('exit', function () { + dbPool.clearAll(); +}); + +module.exports = dbPool; \ No newline at end of file diff --git a/controller/dbquery.js b/controller/dbquery.js index 0049356..4898d0d 100644 --- a/controller/dbquery.js +++ b/controller/dbquery.js @@ -23,14 +23,6 @@ var _ = require('lodash'); var dbpool = require('./dbpool'); -var pool = new dbpool({}); - -process.on('exit', function () { - pool.drain(function () { - pool.clear(); - }); -}); - /** * Client */ @@ -59,17 +51,41 @@ mariadb.queries = { 'tic_image.image_name job_image_name, ', 'tic_image.image_size job_image_size, ', 'tic_job.job_hasksfile job_hasksfile, ', + 'tic_job.job_ks job_ks, ', + 'tic_job.job_arch job_arch, ', 'tic_job.job_uptime job_uptime ', 'from tic_job ', 'left join tic_image on tic_job.job_image_id = tic_image.image_id ', 'where tic_job.job_deleted = false ', - 'and job_id = <%= strJobId %>;' + 'and tic_job.job_id = <%= strJobId %>;' ], 'getJobsTotalCount': [ 'select count(job_id) as total_count ', 'from tic_job ', 'where job_deleted = false;' ], + 'getJobsQueueCount': [ + 'select count(job_id) as total_count ', + 'from tic_job ', + 'where job_deleted = false ', + 'and job_status = "INPROGRESS" OR job_status = "READY";' + ], + 'getJobsQueueNext': [ + 'select tic_job.job_id job_id, ', + 'tic_job.job_status job_status, ', + 'tic_job.job_image_id job_image_id, ', + 'tic_image.image_name job_image_name, ', + 'tic_image.image_size job_image_size, ', + 'tic_job.job_hasksfile job_hasksfile, ', + 'tic_job.job_ks job_ks, ', + 'tic_job.job_arch job_arch, ', + 'tic_job.job_uptime job_uptime ', + 'from tic_job ', + 'left join tic_image on tic_job.job_image_id = tic_image.image_id ', + 'where tic_job.job_deleted = false ', + 'and tic_job.job_status = "READY" ', + 'order by tic_job.job_id asc limit 1;' + ], 'getJobsAllList': [ 'select tic_job.job_id job_id, ', 'tic_job.job_status job_status, ', @@ -120,7 +136,7 @@ mariadb.queries = { ');' ], 'getUser': [ - 'select user_email, user_group ', + 'select user_id, user_email, user_group ', 'from tic_user ', 'where user_email = "<%= userEmail %>" and user_password = "<%= userPassword %>" ', 'limit 1;' @@ -133,7 +149,7 @@ mariadb.queries = { }; mariadb.doQuery = function doQuery(queryString) { - return pool.query(queryString, []); + return dbpool.query(queryString, []); }; /** @@ -144,7 +160,7 @@ mariadb.doQuery = function doQuery(queryString) { */ mariadb.editJob = function editJob(req, res) { var queryString, strJobId, reqParam, - job_status, job_deleted, job_hasksfile, job_image_id, job_ks, job_arch; + job_status, job_deleted, job_hasksfile, job_image_id, job_ks, job_arch, job_updater; function onSuccess(rows) { logger.info('editJob.success'); @@ -159,6 +175,7 @@ mariadb.editJob = function editJob(req, res) { job_image_id = reqParam.job_image_id; job_ks = reqParam.job_ks; job_arch = reqParam.job_arch; + job_updater = reqParam.job_updater; queryString = 'update tic_job set'; if (job_image_id) { @@ -179,7 +196,9 @@ mariadb.editJob = function editJob(req, res) { if (job_arch) { queryString += ' job_arch = "' + job_arch + '",'; } - queryString += ' job_updater = "tic",'; + if (job_updater) { + queryString += ' job_updater = "' + job_updater + '",'; + } queryString += ' job_uptime = now()'; queryString += ' where job_id = ' + strJobId + ';'; @@ -251,6 +270,18 @@ mariadb.getJobsTotalCount = function getJobsTotalCount(req, res) { }; /** + * Get Counts of Job By job_status + */ +mariadb.getJobsQueueCount = function getJobsQueueCount(callback) { + var queryString = _.join(this.queries['getJobsQueueCount'], ''); + + logger.info('getJobsQueueCount: query = ' + queryString); + + // call + this.doQuery(queryString).then(callback); +}; + +/** * Get All Jobs */ mariadb.getJobsAllList = function getJobsAllList(req, res) { @@ -275,6 +306,22 @@ mariadb.getJobsAllList = function getJobsAllList(req, res) { this.doQuery(queryString).then(onSuccess); }; +/** + * Get Next Job + */ +mariadb.getJobsQueueNext = function getJobsQueueNext(req, res) { + var queryString = _.join(this.queries['getJobsQueueNext'], ''); + + logger.info('getJobsQueueNext: query = ' + queryString); + + function onSuccess (rows) { + res.json(rows.result); + } + + // call + this.doQuery(queryString).then(onSuccess); +}; + /** * IAMGES @@ -476,42 +523,4 @@ mariadb.connectToClient = function connectToClient() { }); }; -/** - * Create the Client - */ -mariadb.createClient = function createClient() { - return new Promise(function (resolve, reject) { - logger.info('create client'); - - var mariaSqlConfig; - - // config - mariaSqlConfig = { - host: '127.0.0.1', - user: 'tic', - password: 'tic', - db: 'pdk', - timeout: 60000, - trace: true - } - - // create - mariaSqlClient = new mariaSql(mariaSqlConfig); - resolve(); - }); -}; - -/** - * Initialize - */ -mariadb.init = function init() { - logger.info('init'); - - var self = this; - self.createClient() - .then(self.connectToClient); -}; - -// mariadb.init(); - module.exports = mariadb; diff --git a/controller/mic.js b/controller/mic.js index fb15119..0b0a988 100644 --- a/controller/mic.js +++ b/controller/mic.js @@ -22,11 +22,14 @@ var TreeKill = require('tree-kill'); var util = require('util'); var JL = require('jsnlog').JL; var _ = require('lodash'); +var client = require('./dbquery'); var AppConfig = require('../config.json'); var logger = JL('mic.js'); -var PROCESS_CNT_MAX = 1; +var PROCESS_CNT_MAX = 4; +var PROCESS_CNT_MIN = 0; +var PROCESS_CNT_ONE = 1; var Mic = {}; @@ -40,11 +43,33 @@ var Mic = {}; */ var processMgr = []; -Mic.isAvailable = function isAvailable() { - if (processMgr.length < PROCESS_CNT_MAX) { - return true; +Mic.hasNextJob = function hasNextJob(callback) { + function onSuccess(rows) { + var queueCnt, hasNext; + queueCnt = Number(rows.result[0].total_count); + hasNext = false; + if (queueCnt >= PROCESS_CNT_ONE) { + hasNext = true; + } + callback(hasNext); } - return false; + client.getJobsQueueCount(onSuccess); +}; + +Mic.isAvailable = function isAvailable(callback) { + function onSuccess(rows) { + var queueCnt, isAvailable; + + queueCnt = rows.result[0].total_count; + isAvailable = false; + + if (queueCnt >= PROCESS_CNT_MIN && queueCnt < PROCESS_CNT_MAX) { + isAvailable = true; + } + + callback(isAvailable); + } + client.getJobsQueueCount(onSuccess); } Mic.kill = function kill(paramObj) { @@ -154,7 +179,7 @@ Mic.create = function create(paramObj, io) { processMgr.pop(psIndex); } - logger.error('Terminated (' + code + ')'); + logger.info('Terminated (' + code + ')'); if (code === 0) { sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH, { msg: 'Terminated (' + code + ')', diff --git a/controller/router.js b/controller/router.js index 1c2f260..1826f76 100644 --- a/controller/router.js +++ b/controller/router.js @@ -69,15 +69,27 @@ var init = function (serv) { /** * Get total Count of Jobs - * @URI /api/job/count + * @URI /api/count/all * @TYPE POST */ - router.post('/job/count', function (req, res) { - logger.info('an api called that /api/job/count'); + router.post('/job/count/all', function (req, res) { + logger.info('an api called that /api/count/all'); client.getJobsTotalCount(req, res); }); /** + * Get Status Count + * @URI /api/job/count/queue + * @TYPE POST + */ + router.post('/job/count/queue', function (req, res) { + logger.info('an api called that /api/job/count/queue'); + client.getJobsQueueCount(function (rows) { + res.json(rows.result); + }); + }) + + /** * Add New Job * @URI /api/job/add * @TYPE POST @@ -93,6 +105,9 @@ var init = function (serv) { * @TYPE POST */ router.post('/job/:id', function (req, res) { + if (!Number(req.params.id)) { + return; + } logger.info('an api called that /api/job/' + req.params.id); client.getJobById(req, res); }); @@ -103,16 +118,32 @@ var init = function (serv) { * @TYPE POST */ router.post('/job/edit/:id', function (req, res) { + if (!Number(req.params.id)) { + return; + } logger.info('an api called that /api/job/edit/' + req.params.id); client.editJob(req, res); }); /** + * Get the job for status was "READY" + * @URI /api/job/next + * @TYPE POST + */ + router.post('/job/queue/next', function (req, res) { + logger.info('an api called that /job/queue/next'); + client.getJobsQueueNext(req, res); + }); + + /** * Read the log file * @URI /api/job/log/:id * @TYPE POST */ router.post('/job/log/:id', function (req, res) { + if (!Number(req.params.id)) { + return; + } logger.info('an api called that /api/job/log/' + req.params.id); filesystem.readLogFile(req, res); }); @@ -157,6 +188,9 @@ var init = function (serv) { * @TYPE POST */ router.post('/image/edit/:id', function (req, res) { + if (!Number(req.params.id)) { + return; + } logger.info('an api called that /api/image/edit/' + req.params.id); client.editImage(req, res); }); diff --git a/controller/session.js b/controller/session.js index e04f2e0..4257321 100644 --- a/controller/session.js +++ b/controller/session.js @@ -64,6 +64,7 @@ Session.prototype.postSession = function(req, res) { // save email in session req.session.email = req.body.email; req.session.group = user.data.user_group; + req.session.userid = user.data.user_id; logger.info('login success: ' + req.body.email + ' , ' + user.data.user_group); res.json({ result: STATUS.SUCCESS, @@ -88,7 +89,8 @@ Session.prototype.getSession = function(req, res) { res.json({ status: STATUS.CONNECTED, email: req.session.email, - group: req.session.group + group: req.session.group, + id: req.session.userid }); } else { res.json({ diff --git a/controller/socketio.js b/controller/socketio.js index a79df9d..909c066 100644 --- a/controller/socketio.js +++ b/controller/socketio.js @@ -25,6 +25,13 @@ var AppConfig = require('../config.json'); var listen = function listen (server) { var io = socketio.listen(server); + function fnEmitIsImageCreationAvailable () { + Mic.isAvailable(function (isAvailable) { + logger.info('mic available: ' + isAvailable); + io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, isAvailable); + }); + } + /** * Connection with MIC */ @@ -36,7 +43,7 @@ var listen = function listen (server) { */ socket.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM, function (data) { Mic.create(data, io); - io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable()); + fnEmitIsImageCreationAvailable(); }); /** @@ -44,16 +51,26 @@ var listen = function listen (server) { */ socket.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_KILL, function (data) { Mic.kill(data); - - io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable()); + fnEmitIsImageCreationAvailable(); }); /** * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM = 'ws/mic/available/from' */ socket.on(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM, function () { - logger.info('mic available: ' + Mic.isAvailable()); - io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable()); + fnEmitIsImageCreationAvailable(); + }); + + /** + * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM = 'ws/mic/nextjob/from' + */ + socket.on(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_FROM, function () { + Mic.hasNextJob(function (hasNext) { + if (hasNext) { + logger.info('mic has a next job : ' + hasNext); + io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_TO, hasNext); + } + }); }); socket.on('disconnect', function () { diff --git a/public/src/css/style.css b/public/src/css/style.css index a66e742..f3ebd73 100644 --- a/public/src/css/style.css +++ b/public/src/css/style.css @@ -176,17 +176,17 @@ body { } .job-status-done { font-size: 2vh; - color: blue; + color: #337ab7; display: table-cell; } .job-status-cancel, .job-status-failed { font-size: 2vh; - color: red; + color: #e05151; display: table-cell; } .job-status-inprogress { font-size: 2vh; - color: green; + color: #2aa730; display: table-cell; } #tic-job-list { @@ -218,7 +218,7 @@ body { background-color: slategray; } #tic-job-list .btndownload { - background-color: lightseagreen; + background-color: #337ab7; } #tic-job-list .btnnotactive { pointer-events: none; @@ -288,6 +288,9 @@ td.extended_job_table_container > div { height: 100%; text-align: left; overflow: auto; + white-space: pre; + font-size: 1em; + text-overflow: ellipsis; } td.extended_job_table_container { height: 13vh; @@ -408,6 +411,7 @@ tr.extended_job_table_row:hover td { float: left; margin-bottom: 8px; width: 75%; + font-size: 1.18em; } .image-list-name-btndownload { float: left; @@ -420,7 +424,10 @@ tr.extended_job_table_row:hover td { text-overflow: ellipsis; white-space:nowrap; overflow: hidden; - display: table-row; +} +.image-list-detail > b { + display: inline-block; + width: 100px; } .image-list-btndownload { min-width: 10px; diff --git a/public/src/js/model/JobStatusModel.js b/public/src/js/model/JobStatusModel.js index 17d4b3c..bfb7dae 100644 --- a/public/src/js/model/JobStatusModel.js +++ b/public/src/js/model/JobStatusModel.js @@ -34,7 +34,7 @@ define([ { value: 'DONE', text: 'Done', - class: 'fa fa-circle job-status-done' + class: 'fa fa-check job-status-done' }, { value: 'CANCELED', diff --git a/public/src/js/page/job.js b/public/src/js/page/job.js index d6beb42..7525d52 100644 --- a/public/src/js/page/job.js +++ b/public/src/js/page/job.js @@ -20,8 +20,10 @@ define([ 'js/util', 'js/logger', 'js/page/image', + 'js/page/package', 'js/model/JobModel', 'js/model/JobPagingModel', + 'js/model/MicManager', 'js/widget/JobPaging', 'js/widget/JobTableItem', 'js/widget/JobTableEmptyItem', @@ -32,8 +34,10 @@ define([ Util, Logger, Image, + Package, JobModel, JobPagingModel, + MicManager, JobPaging, JobTableItem, JobTableEmptyItem, @@ -60,6 +64,7 @@ define([ // const var JOB_STATUS_DONE = 'DONE'; + var JOB_STATUS_INPROGRESS = 'INPROGRESS'; var JOB_STATUS_FAILED = 'FAILED'; var USER_DEFAULT = 'GUEST'; @@ -75,6 +80,7 @@ define([ logger.info('_updateView'); var targetTableBody = $('#tic-job-table > tbody'); targetTableBody.empty(); + var targetId; if (arrJobs.length <= 0) { targetTableBody.append(new JobTableEmptyItem().getRow()); @@ -82,6 +88,14 @@ define([ // when not empty _.forEach(arrJobs, function (value, index) { targetTableBody.append(new JobTableItem(value, index).getRow()); + if (value.getJobStatus() === JOB_STATUS_INPROGRESS) { + targetId = 'extended_job_table_row_' + value.getJobId(); + Util.POST(AppConfig.EVENT.JOB.JOB_READ_LOG + value.getJobId()) + .then(function (line) { + targetId = '#' + targetId + ' > td > div'; + $(targetId).append(line); + }); + } }); // bind events @@ -201,7 +215,16 @@ define([ } function _initSocket() { - function _btnLogBlink (jobId, bBlink) { + + function checksNextJob() { + return new Promise(function (resolve, reject) { + logger.info('checksNextJob'); + client.emit(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_FROM); + resolve(); + }); + } + + function _btnLogBlink(jobId, bBlink) { var btnLogSelector, btnLogElem; btnLogSelector = '#tic-job-list #job_table_row_' + jobId + ' .btnbiglog'; btnLogElem = $(btnLogSelector); @@ -215,6 +238,17 @@ define([ } /** + * when has the next job + * AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_TO = 'ws/mic/nextjob/to' + */ + client.on(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_TO, function (hasNext) { + logger.info(AppConfig.EVENT.SOCKET.MIC_NEXT_JOB_TO); + if (hasNext) { + doCreateAnImage(); + } + }); + + /** * when running on mic * * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO = 'ws/fs/image/add/to' @@ -232,6 +266,8 @@ define([ client.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH, function (dataObj) { var jobId, imageName; + logger.info('IMAGE_ADD_FINISH: ' + AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH); + // jobId jobId = dataObj.jobId; @@ -248,7 +284,6 @@ define([ jobId: jobId }); - logger.info(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH); _btnLogBlink(dataObj.jobId, false); function onError(err) { @@ -261,8 +296,7 @@ define([ function updateJobListView() { logger.info('IMAGE_ADD_FINISH.updateJobListView'); - // upate the list of jobs - updateList(ModelJobPaging.getCurrentPoint()); + updateList(); Image.updateList(); @@ -271,10 +305,16 @@ define([ } function updateJobInfo(data) { + /** + * TODO + * Change the value + * from UserInfo.email to UserInfo.id + */ // update the status and image_id var msgObj = { job_status: JOB_STATUS_DONE, - job_image_id: data.image_id + job_image_id: data.image_id, + job_updater: UserInfo.email }; logger.info('IMAGE_ADD_FINISH.updateJobInfo: ' + JSON.stringify(msgObj)); @@ -303,7 +343,6 @@ define([ */ imageInfo = _.find(arrFileInfo, {name: imageName}); logger.info('IMAGE_ADD_FINISH.addAnImage: ' + JSON.stringify(imageInfo)); - if (imageInfo && imageInfo.type === 'file') { msgObj = { image_name: imageInfo.name, @@ -328,6 +367,7 @@ define([ return getAnImageInfo() .then(addAnImage) .then(updateJobInfo) + .then(checksNextJob) .then(updateJobListView) .catch(onError); }); @@ -358,9 +398,11 @@ define([ // update the status msgObj = { - job_status: JOB_STATUS_FAILED + job_status: JOB_STATUS_FAILED, + 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()); @@ -370,28 +412,77 @@ define([ /** * @name doCreateAnImage - * @param paramObj { - * jobId: '1', - * pathKsFile: '/var/tmp/tic-web/1/default.ks', - * pathOutput: '/var/tmp/tic-web/1/', - * imageName: 'default', - * imageArch: 'armv7l' - * } */ - function doCreateAnImage(paramObj) { - var msgData; - + function doCreateAnImage() { logger.info('doCreateAnImage'); - msgData = { - jobId: paramObj.jobId, - pathKsFile: paramObj.pathKsFile, - pathOutput: paramObj.pathOutput, - imageName: paramObj.pathOutput + paramObj.imageName, - imageArch: paramObj.imageArch - }; - client.emit(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM, msgData); - updateList(); + function onError(err) { + logger.error('doCreateAnImage.onError: ' + err.message); + throw err; + } + + function doUpdateJobView (jobModel) { + logger.info('doCreateAnImage.doUpdateJobView'); + Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + jobModel.getJobId(), { + job_status: JOB_STATUS_INPROGRESS, + job_updater: UserInfo.email + }).then(function () { + // scroll + $('html, body').animate({ + scrollTop: $('#tic-job-section').offset().top + }, 500); + updateList(); + }); + } + + function doCreate (jobModel) { + return new Promise(function (resolve, reject) { + var pathKsFile, imageName, msgData, msgObj; + + logger.info('doCreateAnImage.doCreate'); + + pathKsFile = jobModel.getJobKsPath(); + imageName = pathKsFile.substring(pathKsFile.lastIndexOf('/')+1, pathKsFile.lastIndexOf('.')); + + // options for the creation + msgData = { + jobId: jobModel.getJobId(), + pathKsFile: pathKsFile, + pathOutput: jobModel.getJobPath(), + imageName: imageName + '.tar.gz', + imageArch: jobModel.getJobArch() + }; + + // to create + client.emit(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM, msgData); + resolve(jobModel); + }); + } + + function createNextJobModel (res) { + return new Promise(function (resolve, reject) { + var nextJobInfo, nextJobModel; + + logger.info('doCreateAnImage.createNextJobModel'); + + nextJobInfo = res[0]; + nextJobInfo['job_usergroup'] = _.isEmpty(UserInfo) ? USER_DEFAULT : UserInfo.group; + + nextJobModel = new JobModel(nextJobInfo); + resolve(nextJobModel); + }); + } + + function getNextJob () { + logger.info('doCreateAnImage.getNextJob'); + return Util.POST(AppConfig.EVENT.JOB.JOB_GET_NEXTJOB); + } + + getNextJob() + .then(createNextJobModel) + .then(doCreate) + .then(doUpdateJobView) + .catch(onError); } /** diff --git a/public/src/js/page/package.js b/public/src/js/page/package.js index ca9ace0..6a7990b 100644 --- a/public/src/js/page/package.js +++ b/public/src/js/page/package.js @@ -49,6 +49,14 @@ define([ var groups = null; var groupId = 0; + //To manage that the image creation + var micMgr = []; + + // reason for reject (not on error) + var MIC_CNT_MAX = 4; + var MIC_CNT_ONE = 1; + + // status var JOB_STATUS_INPROGRESS = 'INPROGRESS'; // AppConfig @@ -68,51 +76,41 @@ define([ return; } - function doCreateAnImage() { - var pathKsFile, imageName; - logger.info('onClickHandlerForImgCreationBtn.doCreateAnImage'); - - // scroll - $('html, body').animate({ - scrollTop: $('#tic-job-section').offset().top - }, 500); + function onError(err) { + logger.info('onClickHandlerForImgCreationBtn.onError'); + if (err) { + logger.error(err.message); + } + } - // get the name of image - pathKsFile = newJobModel.getJobKsPath(); - imageName = pathKsFile.substring(pathKsFile.lastIndexOf('/')+1, pathKsFile.lastIndexOf('.')); + function checksAvailable () { + return new Promise (function (resolve, reject) { + logger.info('onClickHandlerForImgCreationBtn.checksAvailable'); - // options for the creation - var msgData = { - jobId: newJobModel.getJobId(), - pathKsFile: pathKsFile, - pathOutput: newJobModel.getJobPath(), - imageName: imageName + '.tar.gz', - imageArch: newJobModel.getJobArch() - }; + function doChecking (res) { + var isPossible, length; + isPossible = false; + length = Number(res[0].total_count); + if (length === MIC_CNT_ONE) { + isPossible = true; + } + resolve(isPossible); + } - // create - Job.doCreateAnImage(msgData); + return Util.POST(AppConfig.EVENT.JOB.JOB_GET_QUEUE_COUNT) + .then(doChecking); + }); } - function getRecipeFile() { - var msgData; - - logger.info('onClickHandlerForImgCreationBtn.getRecipeFile: job_path = ' + newJobModel.getJobPath()); - - /** - * FIXME - * - * filename will be removed. - * filenmae generated by ticcore - */ - msgData = { + function getRecipeFile(newJobModel) { + var msgData = { recipes: Settings.getRecipeStore(), packages: _.map(checkedPackagesList, 'name'), outdir: newJobModel.getJobPath() }; function onErrorGetRecipeFile(err) { - logger.info('onClickHandlerForImgCreationBtn.onErrorGetRecipeFile'); + logger.info('startExecutingJob.onErrorGetRecipeFile'); logger.error(err); throw err; } @@ -132,9 +130,8 @@ define([ newJobModel.setJobKs(strKsName); newJobModel.setJobArch(strArch); - logger.info('onClickHandlerForImgCreationBtn.onSuccessGetRecipeFile: ' + responseObj.data.kspath); + logger.info('startExecutingJob.onSuccessGetRecipeFile: ' + responseObj.data.kspath); msgObj = { - job_status: JOB_STATUS_INPROGRESS, job_hasksfile: true, job_ks: strKsName, job_arch: strArch @@ -142,7 +139,11 @@ define([ return Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + newJobModel.getJobId(), msgObj); } - return Util.POST(AppConfig.EVENT.PACKAGE.EXPORT, msgData) + function getKickStartFile () { + return Util.POST(AppConfig.EVENT.PACKAGE.EXPORT, msgData); + } + + return getKickStartFile() .then(onSuccessGetRecipeFile) .catch(onErrorGetRecipeFile); } @@ -155,13 +156,13 @@ define([ }); } - function getJobId(jobItem) { - logger.info('onClickHandlerForImgCreationBtn.getJobId'); + function getJobInfo(jobItem) { var jobId = jobItem.job_id; + logger.info('onClickHandlerForImgCreationBtn.getJobInfo : ' + JSON.stringify(jobItem)); return Util.POST(AppConfig.EVENT.JOB.JOB_GET_BYID + jobId); } - function doConfirmOk() { + function addJob(cnt) { logger.info('onClickHandlerForImgCreationBtn.addJob'); return Util.POST(AppConfig.EVENT.JOB.JOB_ADD_ONE); } @@ -173,11 +174,23 @@ define([ } return showConfirmDialog() - .then(doConfirmOk) - .then(getJobId) + .then(addJob) + .then(getJobInfo) .then(setJobModel) .then(getRecipeFile) - .then(doCreateAnImage); + .then(checksAvailable) + .then(function (isPossible) { + if (isPossible) { + Job.doCreateAnImage(); + } else { + // scroll + $('html, body').animate({ + scrollTop: $('#tic-job-section').offset().top + }, 500); + Job.updateList(); + } + }) + .catch(onError); } function _getChecked() {