var express = require('express');
var bodyParser = require('body-parser');
-var FileSystem = require('./server/fs/ws.filesystem');
+var FileSystem = require('./server/fs/filesystem');
+var Mic = require('./server/fs/mic');
+var Router = require('./server/routes/router');
var app = express();
var server = http.createServer(app);
app.use(bodyParser.urlencoded());
app.use(express.static(path.join(__dirname, '/public/src'))); //module directory
-
-/**
- * TODO
- *
- * apply router
- *
- * var AppRouter = require('./routes');
- * app.use(mount('/', AppRouter));
- */
+app.use('/api', Router);
server.listen(app.get('port'), process.env.IP || "0.0.0.0", function () {
var addr = server.address();
socket.emit('ws/fs/image/list/to', msgData);
});
+ socket.on('ws/fs/image/add/from', function (data) {
+ console.log(data);
+ var msgData, ans;
+
+ msgData = {};
+
+ function sendMsg(msg) {
+ // send
+ socket.emit('ws/fs/image/add/to', msg);
+ }
+
+ // get the list of file
+ Mic.create(data, socket);
+ });
+
+ socket.on('ws/fs/image/download/from', function (data) {
+ console.log(data);
+
+ });
+
socket.on('disconnect', function () {
console.log('socket disconnect');
});
position: relative;
overflow: auto;
}
+#tic-image-list {
+ margin-top: 3px;
+}
+
+.image-list-time {
+ padding-left: 10px;
+}
+
+.image-item {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.infobox {
+ padding: 20px;
+ margin: 20px 0;
+ border: 1px solid #eee;
+ border-radius: 3px;
+ margin-top: 3px;
+ height: 25vh;
+ overflow: auto;
+ font-size: 14px;
+}
+
+.infoboxheader {
+ padding-left: 15px;
+ border: 1px solid #eee;
+ border-left-width: 5px;
+ border-radius: 3px;
+ margin-top: -5px;
+ height: 5vh;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ border-left-color: #1b809e;
+}
+.infoboxheader h4 {
+ color: #1b809e;
+}
+
@media (min-width: 992px) {
#tic-image-summary {
height: 70vh;
<div class="panel panel-primary">
<div class="panel-heading">Image List</div>
<div class="panel-body">
- <h1>Image list and download</h1>
- <table id="tic-image-list"></table>
+ <div class="infoboxheader">
+ <h4>create a image</h4>
+ </div>
+ <div class="infobox info" id="tic-image-new">
+ <div id="tic-image-new-log">
+ </div>
+ </div>
+ <div class="infoboxheader">
+ <h4>image list</h4>
+ </div>
+ <ul class="list-group" id="tic-image-list"></ul>
</div>
</div>
</div><!-- /End Image List Column -->
</div>
</div><!-- /.container -->
+ <!-- modal -->
+ <div class="modal fade" id="confirmModalCreateImage" role="dialog">
+ <div class="modal-dialog modal-sm">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Create a new Image</h4>
+ </div>
+ <div class="modal-body">
+ <p>Are you sure ?</p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary">Ok</button>
+ </div>
+ </div>
+ </div>
+ </div>
</section>
) {
'use strict';
- var client;
+ // connected socket object
+ var client,
+
+ // the list of checked pakages
+ checkedPackagesList,
+
+ // template for the URL
+ URL_EXPORTS = '<%= protocol %>//<%= hostname %>:<%= port %>/exports',
+
+ // the path for ks
+ PATH_TIC_KS = '/tmp/tic/ks/',
+
+ // the path for images
+ PATH_TIC_IMAGES = '/tmp/tic/images/';
+
+
function updateList(socket) {
- /**
- * FIXME
- *
- * changed to be set the path dynamically
- */
var msgData = {
- path: './resource/images/'
+ path: PATH_TIC_IMAGES
};
- /**
- * TODO
- * checks
- */
client = socket;
client.emit('ws/fs/image/list/from', msgData);
list = data.list;
tableDomElem = $('#tic-image-list');
- /**
- * FIXME
- */
list.forEach(function (file) {
- tableDomElem.append(file.name + ' (size:' + file.size + ')' + '</br>');
+ /**
+ * @info
+ *
+ * file = {
+ * name: '',
+ * size: ''
+ * }
+ */
+ var liElem, aElem, spanElem, fileName, hrefPath;
+
+ fileName = file.name;
+
+ hrefPath = '/api/fs/download/' + fileName;
+
+ liElem = document.createElement('li');
+ liElem.innerText = fileName;
+ liElem.setAttribute('class', 'list-group-item image-item');
+
+ spanElem = document.createElement('span');
+ spanElem.innerText = '(' + file.size + 'B / ' + file.mtime + ')';
+ spanElem.setAttribute('class', 'image-list-time');
+
+ aElem = document.createElement('a');
+ aElem.innerText = 'Download';
+ aElem.setAttribute('class', 'badge');
+ aElem.setAttribute('href', hrefPath);
+ aElem.setAttribute('data-name', fileName);
+ aElem.setAttribute('download', 'download');
+
+ liElem.appendChild(spanElem);
+ liElem.appendChild(aElem);
+ tableDomElem.append(liElem);
});
});
var packageCount = $('#tic-image-package-count').empty();
var packageList = $('#tic-image-package-list').empty();
- var list = require('js/page/package').getCheckedPackages();
- var count = _.size(list);
- var imageSize = _.sumBy(list, function getImageSize(item) {
+ checkedPackagesList = require('js/page/package').getCheckedPackages();
+ var count = _.size(checkedPackagesList);
+ var imageSize = _.sumBy(checkedPackagesList, function getImageSize(item) {
return _.toNumber(item.size);
});
- var imageInstalledSize = _.sumBy(list, function getImageInstalled(item) {
+ var imageInstalledSize = _.sumBy(checkedPackagesList, function getImageInstalled(item) {
return _.toNumber(item.installed);
});
if (_.isNumber(count)) {
packageCount.html(count);
}
- if (!_.isEmpty(list)) {
- packageList.html(_.orderBy(_.map(list, 'text')).join('<br>'));
+ if (!_.isEmpty(checkedPackagesList)) {
+ packageList.html(_.orderBy(_.map(checkedPackagesList, 'text')).join('<br>'));
}
$('#tic-image-create').prop('disabled', count === 0);
}
+ function confirmCreateImage() {
+ var isOk;
+
+ $('#tic-image-create').prop('disabled', true);
+
+ // when packages are checked nothing
+ if (_.isEmpty(checkedPackagesList)) {
+ $('#tic-image-create').prop('disabled', true);
+ return;
+ }
+
+ function createImage(pathKsFile) {
+ /**
+ * TODO - checks the msgData
+ */
+ var msgData, tableDomElem;
+ msgData = {
+ pathKsFile: pathKsFile,
+ pathOutput: PATH_TIC_IMAGES
+ };
+
+ tableDomElem = $('#tic-image-new-log');
+
+ client.emit('ws/fs/image/add/from', msgData);
+
+ client.on('ws/fs/image/add/to', function (data) {
+ console.log(data);
+ var elem = document.createElement('p');
+ elem.innerText = data;
+ tableDomElem.append(elem);
+ });
+
+ // when finished
+ client.on('ws/fs/image/add/finished', function (data) {
+ $('#tic-image-create').prop('disabled', false);
+ $('#tic-image-new').empty();
+ updateList();
+ });
+ }
+
+ function getExportsUrl() {
+ return _.template(URL_EXPORTS)({
+ protocol: location.protocol,
+ hostname: location.hostname,
+ port: parseInt(location.port) + 1
+ });
+ }
+
+ function getKickstartRecipeFile() {
+ return new Promise(function (resolve, reject) {
+ var msgData = {
+ recipe: {
+ name: 'default'
+ },
+ packages: _.map(checkedPackagesList, 'name'),
+ output: PATH_TIC_KS
+ };
+
+ console.log('url = ' + getExportsUrl());
+ console.log(msgData);
+
+ $.ajax({
+ type: 'POST',
+ contentType: 'text/plain',
+ data: JSON.stringify(msgData),
+ dataType: 'json',
+ url: getExportsUrl(),
+ success: function (res) {
+ console.log(res);
+ resolve(res.data);
+ },
+ error: function (err) {
+ reject(err.responseText);
+ }
+ });
+ });
+ }
+
+ /**
+ * FIXME
+ * using modal
+ *
+ * $('#confirmModalCreateImage').modal('show');
+ */
+ // confirm
+ isOk = window.confirm('Are you sure?');
+ if (isOk) {
+ getKickstartRecipeFile()
+ .then(createImage)
+ .catch(function (err) {
+ console.log(err);
+ Util.showLoadingDialog(false);
+ Util.showAlertDialog('Failed to create a image.<br>Please check the ks file.');
+ });
+ } else {
+ $('#tic-image-create').prop('disabled', false);
+ }
+ }
+
+ /**
+ * Initiation for the all widgets
+ */
+ function _initWidgets() {
+ // button
+ $('#tic-image-create').prop('disabled', true);
+ $('#tic-image-create').click(confirmCreateImage);
+
+ /**
+ * FIXME
+ * chanage 'confirm' to 'modal'
+ *
+ * modal
+ * $('#confirmModalCreateImage').modal({
+ * keyboard: false,
+ * backdrop: true
+ * });
+ */
+
+ }
+
function init() {
console.log('image: init');
- $('#tic-image-create').prop('disabled', true);
+
+ _initWidgets();
}
init();
* @method updateSummary
*/
updateSummary: updateSummary,
+
+ /**
+ * Update list in image page
+ * @method updateList
+ */
updateList: updateList
}
--- /dev/null
+'use strict';
+/**
+ * using websocket
+ */
+
+var fs = require('fs');
+var path = require('path');
+
+var FileSystem = {};
+
+FileSystem.list = function (dirPath) {
+ console.log('filesystem.list called');
+ var results, info, list;
+
+ results = [];
+
+ if(!fs.existsSync(dirPath)) {
+ fs.mkdirSync(dirPath);
+ }
+
+ list = fs.readdirSync(dirPath);
+ list.forEach(function(file) {
+ var fileStat, filePath;
+
+ filePath = dirPath + file;
+
+ fileStat = fs.statSync(filePath);
+
+ if (fileStat && fileStat.isDirectory()) {
+ results = results.concat(FileSystem.list(filePath))
+ } else {
+ /**
+ * TODO
+ * to be extended ..
+ */
+ info = {
+ name: file,
+ size: fileStat['size'],
+ atime: fileStat['atime'],
+ mtime: fileStat['mtime'],
+ ctime: fileStat['ctime'],
+ birthtime: fileStat['birthtime']
+ }
+ results.push(info);
+ }
+ });
+ return results;
+};
+
+FileSystem.remove = function () {
+ console.log('filesystem.remove called');
+};
+
+FileSystem.download = function () {
+ console.log('filesystem.download called');
+};
+
+module.exports = FileSystem;
\ No newline at end of file
--- /dev/null
+'use strict';
+/**
+ * using websocket
+ */
+
+var fs = require('fs');
+var path = require('path');
+var exec = require('child_process').exec;
+var util = require('util');
+
+var Mic = {};
+
+Mic.subprocess = function (processname, arg, cb) {
+ var p = exec(processname, arg);
+ p.on('exit', cb.exit);
+ p.stdout.on('data', cb.stdout || function (out) {
+ process.stdout.write(out);
+ });
+ p.stderr.on('data', cb.stderr || function (err) {
+ process.stdout.write(err);
+ });
+};
+
+Mic.create = function (paramObj, client) {
+ console.log('Mic.create called');
+ var micProcess, micProcessArgs, mic, child, stdoutPath, exitPath;
+
+ stdoutPath = 'ws/fs/image/add/to';
+ exitPath = 'ws/fs/image/add/finished';
+
+ micProcess = 'sudo mic cr loop ' + paramObj.pathKsFile;
+ micProcessArgs = [];
+ micProcessArgs.push(util.format('-A %s', 'x86_64'));
+ micProcessArgs.push(util.format('-o %s', paramObj.pathOutput));
+
+ function sendMsg(path, msg) {
+ client.emit(path, msg);
+ }
+
+ Mic.subprocess(micProcess, micProcessArgs, {
+ stdout: function (out) {
+ console.log('stdout' + out);
+ sendMsg(stdoutPath, 'stdout: ' + out);
+ },
+ stderr: function (out) {
+ console.log('stderr' + out);
+ sendMsg(stdoutPath, 'stderr: ' + out);
+ },
+ exit: function (out) {
+ console.log('exit: ' + out);
+ sendMsg(exitPath, 'exit: ' + out);
+ }
+ });
+};
+
+module.exports = Mic;
\ No newline at end of file
var FileSystem = {};
FileSystem.list = function (dirPath) {
+ console.log('FileSystem.list called');
var results, info, list;
results = [];
+ if(!fs.existsSync(dirPath)) {
+ fs.mkdirSync(dirPath);
+ }
+
list = fs.readdirSync(dirPath);
list.forEach(function(file) {
var fileStat, filePath;
* to be extended ..
*/
info = {
- name: filePath,
+ name: file,
size: fileStat['size']
}
results.push(info);
--- /dev/null
+var express = require('express');
+var router = express.Router();
+var mime = require('mime');
+var fs = require('fs');
+var path = require('path');
+
+router.use(function timeLog(req, res, next) {
+ var time = new Date();
+ console.log('Time: ', time.toISOString());
+ next();
+});
+
+/**
+ * API
+ *
+ * path : /api/fs/download
+ * request body : {
+ * filename: 'filename.ks'
+ * }
+ */
+router.get('/fs/download/:filename', function (req, res) {
+ var fileName, filePath, fileOptions, fileMimetype, fileStream;
+ console.log('>> file download called');
+
+ fileName = req.params.filename;
+ filePath = '/tmp/tic/images/' + fileName;
+ fileMimetype = mime.lookup(filePath);
+ console.log('>> filename: ' + req.params.filename + ', mime: ' + fileMimetype);
+
+ res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
+ res.setHeader('Content-type', fileMimetype);
+
+ fileStream = fs.createReadStream(filePath);
+ fileStream.pipe(res);
+});
+
+module.exports = router;
\ No newline at end of file