wf_node_api 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +66 -0
- data/LICENSE +340 -0
- data/Makefile +19 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/Vagrantfile +102 -0
- data/_docs/api/Api/NodeApi.html +123 -0
- data/_docs/api/Api.html +149 -0
- data/_docs/api/Config/Check.html +331 -0
- data/_docs/api/Config.html +115 -0
- data/_docs/api/ConfigCheck.html +365 -0
- data/_docs/api/ContainerManager.html +1632 -0
- data/_docs/api/ContainerManagerAdapter/Lxc.html +1352 -0
- data/_docs/api/ContainerManagerAdapter/Vserver.html +1358 -0
- data/_docs/api/ContainerManagerAdapter.html +151 -0
- data/_docs/api/Error/NotFound.html +134 -0
- data/_docs/api/Error.html +115 -0
- data/_docs/api/NotFoundError.html +157 -0
- data/_docs/api/OS.html +234 -0
- data/_docs/api/ResourceManager.html +322 -0
- data/_docs/api/ResourceManagerAdapter/Linux.html +326 -0
- data/_docs/api/ResourceManagerAdapter.html +149 -0
- data/_docs/api/WfNodeApi.html +163 -0
- data/_docs/api/_index.html +239 -0
- data/_docs/api/class_list.html +58 -0
- data/_docs/api/css/common.css +1 -0
- data/_docs/api/css/full_list.css +57 -0
- data/_docs/api/css/style.css +339 -0
- data/_docs/api/file.README.html +146 -0
- data/_docs/api/file_list.html +60 -0
- data/_docs/api/frames.html +26 -0
- data/_docs/api/index.html +146 -0
- data/_docs/api/js/app.js +219 -0
- data/_docs/api/js/full_list.js +181 -0
- data/_docs/api/js/jquery.js +4 -0
- data/_docs/api/method_list.html +273 -0
- data/_docs/api/top-level-namespace.html +244 -0
- data/_docs/rest/api_data.js +1 -0
- data/_docs/rest/api_data.json +1 -0
- data/_docs/rest/api_project.js +1 -0
- data/_docs/rest/api_project.json +1 -0
- data/_docs/rest/css/style.css +538 -0
- data/_docs/rest/header.md +3 -0
- data/_docs/rest/img/favicon.ico +0 -0
- data/_docs/rest/img/glyphicons-halflings-white.png +0 -0
- data/_docs/rest/img/glyphicons-halflings.png +0 -0
- data/_docs/rest/index.html +658 -0
- data/_docs/rest/locales/de.js +25 -0
- data/_docs/rest/locales/fr.js +25 -0
- data/_docs/rest/locales/locale.js +43 -0
- data/_docs/rest/locales/nl.js +25 -0
- data/_docs/rest/locales/pl.js +25 -0
- data/_docs/rest/locales/pt_br.js +25 -0
- data/_docs/rest/locales/ru.js +25 -0
- data/_docs/rest/locales/zh.js +25 -0
- data/_docs/rest/main.js +691 -0
- data/_docs/rest/utils/handlebars_helper.js +327 -0
- data/_docs/rest/utils/send_sample_request.js +158 -0
- data/_docs/rest/vendor/bootstrap-responsive.min.css +9 -0
- data/_docs/rest/vendor/bootstrap.min.css +9 -0
- data/_docs/rest/vendor/bootstrap.min.js +6 -0
- data/_docs/rest/vendor/diff_match_patch.min.js +49 -0
- data/_docs/rest/vendor/handlebars.min.js +28 -0
- data/_docs/rest/vendor/jquery.min.js +4 -0
- data/_docs/rest/vendor/lodash.min.js +61 -0
- data/_docs/rest/vendor/path-to-regexp/LICENSE +21 -0
- data/_docs/rest/vendor/path-to-regexp/index.js +205 -0
- data/_docs/rest/vendor/polyfill.js +100 -0
- data/_docs/rest/vendor/prettify/lang-apollo.js +2 -0
- data/_docs/rest/vendor/prettify/lang-basic.js +3 -0
- data/_docs/rest/vendor/prettify/lang-clj.js +18 -0
- data/_docs/rest/vendor/prettify/lang-css.js +2 -0
- data/_docs/rest/vendor/prettify/lang-dart.js +3 -0
- data/_docs/rest/vendor/prettify/lang-erlang.js +2 -0
- data/_docs/rest/vendor/prettify/lang-go.js +1 -0
- data/_docs/rest/vendor/prettify/lang-hs.js +2 -0
- data/_docs/rest/vendor/prettify/lang-lisp.js +3 -0
- data/_docs/rest/vendor/prettify/lang-llvm.js +1 -0
- data/_docs/rest/vendor/prettify/lang-lua.js +2 -0
- data/_docs/rest/vendor/prettify/lang-matlab.js +6 -0
- data/_docs/rest/vendor/prettify/lang-ml.js +2 -0
- data/_docs/rest/vendor/prettify/lang-mumps.js +2 -0
- data/_docs/rest/vendor/prettify/lang-n.js +4 -0
- data/_docs/rest/vendor/prettify/lang-pascal.js +3 -0
- data/_docs/rest/vendor/prettify/lang-proto.js +1 -0
- data/_docs/rest/vendor/prettify/lang-r.js +2 -0
- data/_docs/rest/vendor/prettify/lang-rd.js +1 -0
- data/_docs/rest/vendor/prettify/lang-scala.js +2 -0
- data/_docs/rest/vendor/prettify/lang-sql.js +2 -0
- data/_docs/rest/vendor/prettify/lang-tcl.js +3 -0
- data/_docs/rest/vendor/prettify/lang-tex.js +1 -0
- data/_docs/rest/vendor/prettify/lang-vb.js +2 -0
- data/_docs/rest/vendor/prettify/lang-vhdl.js +3 -0
- data/_docs/rest/vendor/prettify/lang-wiki.js +2 -0
- data/_docs/rest/vendor/prettify/lang-xq.js +3 -0
- data/_docs/rest/vendor/prettify/lang-yaml.js +2 -0
- data/_docs/rest/vendor/prettify/prettify.css +1 -0
- data/_docs/rest/vendor/prettify/prettify.js +30 -0
- data/_docs/rest/vendor/prettify/run_prettify.js +34 -0
- data/_docs/rest/vendor/prettify.css +101 -0
- data/_docs/rest/vendor/require.min.js +36 -0
- data/apidoc.json +23 -0
- data/bin/wf_node_api +80 -0
- data/lib/wf_node_api/api/node_api.rb +360 -0
- data/lib/wf_node_api/config/config_template.erb +50 -0
- data/lib/wf_node_api/config_check.rb +50 -0
- data/lib/wf_node_api/container_manager.rb +286 -0
- data/lib/wf_node_api/container_manager_adapter/lxc.rb +431 -0
- data/lib/wf_node_api/container_manager_adapter/vserver.rb +448 -0
- data/lib/wf_node_api/error/not_found.rb +27 -0
- data/lib/wf_node_api/os.rb +32 -0
- data/lib/wf_node_api/resource_manager.rb +49 -0
- data/lib/wf_node_api/resource_manager_adapter/linux.rb +53 -0
- data/lib/wf_node_api/translations.rb +38 -0
- data/lib/wf_node_api/version.rb +28 -0
- data/lib/wf_node_api.rb +57 -0
- data/manifests/files/dhozac-vserver.repo +4 -0
- data/wf-node-api.gemspec +53 -0
- metadata +221 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* Pretty printing styles. Used with prettify.js. */
|
|
2
|
+
/* Vim sunburst theme by David Leibovic */
|
|
3
|
+
pre .str {
|
|
4
|
+
color: #65B042;
|
|
5
|
+
}
|
|
6
|
+
/* string - green */
|
|
7
|
+
pre .kwd {
|
|
8
|
+
color: #E28964;
|
|
9
|
+
}
|
|
10
|
+
/* keyword - dark pink */
|
|
11
|
+
pre .com {
|
|
12
|
+
color: #AEAEAE;
|
|
13
|
+
font-style: italic;
|
|
14
|
+
}
|
|
15
|
+
/* comment - gray */
|
|
16
|
+
pre .typ {
|
|
17
|
+
color: #89bdff;
|
|
18
|
+
}
|
|
19
|
+
/* type - light blue */
|
|
20
|
+
pre .lit {
|
|
21
|
+
color: #3387CC;
|
|
22
|
+
}
|
|
23
|
+
/* literal - blue */
|
|
24
|
+
pre .pun {
|
|
25
|
+
color: #fff;
|
|
26
|
+
}
|
|
27
|
+
/* punctuation - white */
|
|
28
|
+
pre .pln {
|
|
29
|
+
color: #fff;
|
|
30
|
+
}
|
|
31
|
+
/* plaintext - white */
|
|
32
|
+
pre .tag {
|
|
33
|
+
color: #89bdff;
|
|
34
|
+
}
|
|
35
|
+
/* html/xml tag - light blue */
|
|
36
|
+
pre .atn {
|
|
37
|
+
color: #bdb76b;
|
|
38
|
+
}
|
|
39
|
+
/* html/xml attribute name - khaki */
|
|
40
|
+
pre .atv {
|
|
41
|
+
color: #65B042;
|
|
42
|
+
}
|
|
43
|
+
/* html/xml attribute value - green */
|
|
44
|
+
pre .dec {
|
|
45
|
+
color: #3387CC;
|
|
46
|
+
}
|
|
47
|
+
/* decimal - blue */
|
|
48
|
+
/* Specify class=linenums on a pre to get line numbering */
|
|
49
|
+
ol.linenums {
|
|
50
|
+
margin-top: 0;
|
|
51
|
+
margin-bottom: 0;
|
|
52
|
+
color: #AEAEAE;
|
|
53
|
+
}
|
|
54
|
+
/* IE indents via margin-left */
|
|
55
|
+
li.L0,
|
|
56
|
+
li.L1,
|
|
57
|
+
li.L2,
|
|
58
|
+
li.L3,
|
|
59
|
+
li.L5,
|
|
60
|
+
li.L6,
|
|
61
|
+
li.L7,
|
|
62
|
+
li.L8 {
|
|
63
|
+
list-style-type: none;
|
|
64
|
+
}
|
|
65
|
+
/* Alternate shading for lines */
|
|
66
|
+
@media print {
|
|
67
|
+
pre .str {
|
|
68
|
+
color: #060;
|
|
69
|
+
}
|
|
70
|
+
pre .kwd {
|
|
71
|
+
color: #006;
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
}
|
|
74
|
+
pre .com {
|
|
75
|
+
color: #600;
|
|
76
|
+
font-style: italic;
|
|
77
|
+
}
|
|
78
|
+
pre .typ {
|
|
79
|
+
color: #404;
|
|
80
|
+
font-weight: bold;
|
|
81
|
+
}
|
|
82
|
+
pre .lit {
|
|
83
|
+
color: #044;
|
|
84
|
+
}
|
|
85
|
+
pre .pun {
|
|
86
|
+
color: #440;
|
|
87
|
+
}
|
|
88
|
+
pre .pln {
|
|
89
|
+
color: #000;
|
|
90
|
+
}
|
|
91
|
+
pre .tag {
|
|
92
|
+
color: #006;
|
|
93
|
+
font-weight: bold;
|
|
94
|
+
}
|
|
95
|
+
pre .atn {
|
|
96
|
+
color: #404;
|
|
97
|
+
}
|
|
98
|
+
pre .atv {
|
|
99
|
+
color: #060;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
RequireJS 2.1.15 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
|
|
3
|
+
Available via the MIT or new BSD license.
|
|
4
|
+
see: http://github.com/jrburke/requirejs for details
|
|
5
|
+
*/
|
|
6
|
+
var requirejs,require,define;
|
|
7
|
+
(function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function T(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function t(b,c){return fa.call(b,c)}function m(b,c){return t(b,c)&&b[c]}function B(b,c){for(var d in b)if(t(b,d)&&c(b[d],d))break}function U(b,c,d,e){c&&B(c,function(c,g){if(d||!t(b,g))e&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof
|
|
8
|
+
RegExp)?(b[g]||(b[g]={}),U(b[g],c,d,e)):b[g]=c});return b}function u(b,c){return function(){return c.apply(b,arguments)}}function ca(b){throw b;}function da(b){if(!b)return b;var c=ba;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,e){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=e;d&&(c.originalError=d);return c}function ga(b){function c(a,k,b){var f,l,c,d,e,g,i,p,k=k&&k.split("/"),h=j.map,n=h&&h["*"];if(a){a=a.split("/");l=a.length-1;j.nodeIdCompat&&
|
|
9
|
+
Q.test(a[l])&&(a[l]=a[l].replace(Q,""));"."===a[0].charAt(0)&&k&&(l=k.slice(0,k.length-1),a=l.concat(a));l=a;for(c=0;c<l.length;c++)if(d=l[c],"."===d)l.splice(c,1),c-=1;else if(".."===d&&!(0===c||1==c&&".."===l[2]||".."===l[c-1])&&0<c)l.splice(c-1,2),c-=2;a=a.join("/")}if(b&&h&&(k||n)){l=a.split("/");c=l.length;a:for(;0<c;c-=1){e=l.slice(0,c).join("/");if(k)for(d=k.length;0<d;d-=1)if(b=m(h,k.slice(0,d).join("/")))if(b=m(b,e)){f=b;g=c;break a}!i&&(n&&m(n,e))&&(i=m(n,e),p=c)}!f&&i&&(f=i,g=p);f&&(l.splice(0,
|
|
10
|
+
g,f),a=l.join("/"))}return(f=m(j.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(k){if(k.getAttribute("data-requiremodule")===a&&k.getAttribute("data-requirecontext")===i.contextName)return k.parentNode.removeChild(k),!0})}function e(a){var k=m(j.paths,a);if(k&&H(k)&&1<k.length)return k.shift(),i.require.undef(a),i.makeRequire(null,{skipMap:!0})([a]),!0}function n(a){var k,c=a?a.indexOf("!"):-1;-1<c&&(k=a.substring(0,c),a=a.substring(c+1,a.length));return[k,a]}function p(a,
|
|
11
|
+
k,b,f){var l,d,e=null,g=k?k.name:null,j=a,p=!0,h="";a||(p=!1,a="_@r"+(K+=1));a=n(a);e=a[0];a=a[1];e&&(e=c(e,g,f),d=m(r,e));a&&(e?h=d&&d.normalize?d.normalize(a,function(a){return c(a,g,f)}):-1===a.indexOf("!")?c(a,g,f):a:(h=c(a,g,f),a=n(h),e=a[0],h=a[1],b=!0,l=i.nameToUrl(h)));b=e&&!d&&!b?"_unnormalized"+(O+=1):"";return{prefix:e,name:h,parentMap:k,unnormalized:!!b,url:l,originalName:j,isDefine:p,id:(e?e+"!"+h:h)+b}}function s(a){var k=a.id,b=m(h,k);b||(b=h[k]=new i.Module(a));return b}function q(a,
|
|
12
|
+
k,b){var f=a.id,c=m(h,f);if(t(r,f)&&(!c||c.defineEmitComplete))"defined"===k&&b(r[f]);else if(c=s(a),c.error&&"error"===k)b(c.error);else c.on(k,b)}function w(a,b){var c=a.requireModules,f=!1;if(b)b(a);else if(v(c,function(b){if(b=m(h,b))b.error=a,b.events.error&&(f=!0,b.emit("error",a))}),!f)g.onError(a)}function x(){R.length&&(ha.apply(A,[A.length,0].concat(R)),R=[])}function y(a){delete h[a];delete V[a]}function F(a,b,c){var f=a.map.id;a.error?a.emit("error",a.error):(b[f]=!0,v(a.depMaps,function(f,
|
|
13
|
+
d){var e=f.id,g=m(h,e);g&&(!a.depMatched[d]&&!c[e])&&(m(b,e)?(a.defineDep(d,r[e]),a.check()):F(g,b,c))}),c[f]=!0)}function D(){var a,b,c=(a=1E3*j.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],l=[],g=!1,h=!0;if(!W){W=!0;B(V,function(a){var i=a.map,j=i.id;if(a.enabled&&(i.isDefine||l.push(a),!a.error))if(!a.inited&&c)e(j)?g=b=!0:(f.push(j),d(j));else if(!a.inited&&(a.fetched&&i.isDefine)&&(g=!0,!i.prefix))return h=!1});if(c&&f.length)return a=C("timeout","Load timeout for modules: "+f,null,
|
|
14
|
+
f),a.contextName=i.contextName,w(a);h&&v(l,function(a){F(a,{},{})});if((!c||b)&&g)if((z||ea)&&!X)X=setTimeout(function(){X=0;D()},50);W=!1}}function E(a){t(r,a[0])||s(p(a[0],null,!0)).init(a[1],a[2])}function I(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!Y?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=i.onScriptError;(!a.detachEvent||Y)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function J(){var a;
|
|
15
|
+
for(x();A.length;){a=A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var W,Z,i,L,X,j={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},h={},V={},$={},A=[],r={},S={},aa={},K=1,O=1;L={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?r[a.map.id]=a.exports:a.exports=r[a.map.id]={}},module:function(a){return a.module?
|
|
16
|
+
a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m(j.config,a.map.id)||{}},exports:a.exports||(a.exports={})}}};Z=function(a){this.events=m($,a.id)||{};this.map=a;this.shim=m(j.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};Z.prototype={init:function(a,b,c,f){f=f||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=u(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=
|
|
17
|
+
c;this.inited=!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],u(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
|
|
18
|
+
this.map.url;S[a]||(S[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var f=this.exports,l=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||g.onError!==ca)try{f=i.execCb(c,l,b,f)}catch(d){a=d}else f=i.execCb(c,l,b,f);this.map.isDefine&&void 0===f&&((b=this.module)?f=b.exports:this.usingExports&&
|
|
19
|
+
(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(r[c]=f,g.onResourceLoad))g.onResourceLoad(i,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
|
|
20
|
+
this.map,b=a.id,d=p(a.prefix);this.depMaps.push(d);q(d,"defined",u(this,function(f){var l,d;d=m(aa,this.map.id);var e=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,n=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(e=f.normalize(e,function(a){return c(a,P,!0)})||""),f=p(a.prefix+"!"+e,this.map.parentMap),q(f,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=m(h,f.id)){this.depMaps.push(f);
|
|
21
|
+
if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=i.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(h,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,e=p(d),P=M;c&&(f=c);P&&(M=!1);s(e);t(j.config,b)&&(j.config[d]=j.config[b]);try{g.exec(f)}catch(h){return w(C("fromtexteval",
|
|
22
|
+
"fromText eval for "+b+" failed: "+h,h,[b]))}P&&(M=!0);this.depMaps.push(e);i.completeLoad(d);n([d],l)}),f.load(a.name,n,l,j))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=p(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=m(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",u(this,function(a){this.defineDep(b,
|
|
23
|
+
a);this.check()}));this.errback&&q(a,"error",u(this,this.errback))}c=a.id;f=h[c];!t(L,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,u(this,function(a){var b=m(h,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:j,contextName:b,registry:h,defined:r,urlFetched:S,defQueue:A,Module:Z,makeModuleMap:p,
|
|
24
|
+
nextTick:g.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=j.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(j[b]||(j[b]={}),U(j[b],a,!0,!0)):j[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(aa[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),j.shim=b);a.packages&&v(a.packages,function(a){var b,
|
|
25
|
+
a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(j.paths[b]=a.location);j.pkgs[b]=a.name+"/"+(a.main||"main").replace(ia,"").replace(Q,"")});B(h,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=p(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,e){function j(c,d,m){var n,q;e.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild=
|
|
26
|
+
!0);if("string"===typeof c){if(G(d))return w(C("requireargs","Invalid require call"),m);if(a&&t(L,c))return L[c](h[a.id]);if(g.get)return g.get(i,c,a,j);n=p(c,a,!1,!0);n=n.id;return!t(r,n)?w(C("notloaded",'Module name "'+n+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[n]}J();i.nextTick(function(){J();q=s(p(null,a));q.skipMap=e.skipMap;q.init(c,d,m,{enabled:!0});D()});return j}e=e||{};U(j,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),k=b.split("/")[0];if(-1!==
|
|
27
|
+
e&&(!("."===k||".."===k)||1<e))d=b.substring(e,b.length),b=b.substring(0,e);return i.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return t(r,p(b,a,!1,!0).id)},specified:function(b){b=p(b,a,!1,!0).id;return t(r,b)||t(h,b)}});a||(j.undef=function(b){x();var c=p(b,a,!0),e=m(h,b);d(b);delete r[b];delete S[c.url];delete $[b];T(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&($[b]=e.events),y(b))});return j},enable:function(a){m(h,a.id)&&s(a).enable()},completeLoad:function(a){var b,
|
|
28
|
+
c,d=m(j.shim,a)||{},g=d.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=m(h,a);if(!b&&!t(r,a)&&c&&!c.inited){if(j.enforceDefine&&(!g||!da(g)))return e(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,d.deps||[],d.exportsFn])}D()},nameToUrl:function(a,b,c){var d,e,h;(d=m(j.pkgs,a))&&(a=d);if(d=m(aa,a))return i.nameToUrl(d,b,c);if(g.jsExtRegExp.test(a))d=a+(b||"");else{d=j.paths;a=a.split("/");for(e=a.length;0<e;e-=1)if(h=a.slice(0,
|
|
29
|
+
e).join("/"),h=m(d,h)){H(h)&&(h=h[0]);a.splice(0,e,h);break}d=a.join("/");d+=b||(/^data\:|\?/.test(d)||c?"":".js");d=("/"===d.charAt(0)||d.match(/^[\w\+\.\-]+:/)?"":j.baseUrl)+d}return j.urlArgs?d+((-1===d.indexOf("?")?"?":"&")+j.urlArgs):d},load:function(a,b){g.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ja.test((a.currentTarget||a.srcElement).readyState))N=null,a=I(a),i.completeLoad(a.id)},onScriptError:function(a){var b=I(a);if(!e(b.id))return w(C("scripterror",
|
|
30
|
+
"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var g,x,y,D,I,E,N,J,s,O,ka=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,la=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,Q=/\.js$/,ia=/^\.\//;x=Object.prototype;var K=x.toString,fa=x.hasOwnProperty,ha=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),ea=!z&&"undefined"!==typeof importScripts,ja=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,
|
|
31
|
+
Y="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},q={},R=[],M=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(q=require,require=void 0);g=requirejs=function(b,c,d,e){var n,p="_";!H(b)&&"string"!==typeof b&&(n=b,H(c)?(b=c,c=d,d=e):b=[]);n&&n.context&&(p=n.context);(e=m(F,p))||(e=F[p]=g.s.newContext(p));n&&e.configure(n);return e.require(b,c,d)};g.config=function(b){return g(b)};
|
|
32
|
+
g.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version="2.1.15";g.jsExtRegExp=/^\/|:|\?|\.js$/;g.isBrowser=z;x=g.s={contexts:F,newContext:ga};g({});v(["toUrl","undef","defined","specified"],function(b){g[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;g.onError=ca;g.createNode=function(b){var c=
|
|
33
|
+
b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};g.load=function(b,c,d){var e=b&&b.config||{};if(z)return e=g.createNode(e,c,d),e.setAttribute("data-requirecontext",b.contextName),e.setAttribute("data-requiremodule",c),e.attachEvent&&!(e.attachEvent.toString&&0>e.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,e.attachEvent("onreadystatechange",b.onScriptLoad)):
|
|
34
|
+
(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)),e.src=d,J=e,D?y.insertBefore(e,D):y.appendChild(e),J=null,e;if(ea)try{importScripts(d),b.completeLoad(c)}catch(m){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,m,[c]))}};z&&!q.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return s=I,q.baseUrl||(E=s.split("/"),s=E.pop(),O=E.length?E.join("/")+"/":"./",q.baseUrl=
|
|
35
|
+
O),s=s.replace(Q,""),g.jsExtRegExp.test(s)&&(s=I),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ka,"").replace(la,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b||
|
|
36
|
+
(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}(g?g.defQueue:R).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(q)}})(this);
|
data/apidoc.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "WhiteFuse Node API",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Virtualization node RESTful API documentation",
|
|
5
|
+
"url" : "https://mynode.local:1357/v1",
|
|
6
|
+
"header": {
|
|
7
|
+
"filename": "_docs/rest/header.md"
|
|
8
|
+
},
|
|
9
|
+
"order": [
|
|
10
|
+
"GetContainers",
|
|
11
|
+
"GetContainer",
|
|
12
|
+
"CreateContainer",
|
|
13
|
+
"DeleteContainer",
|
|
14
|
+
"StartContainer",
|
|
15
|
+
"StopContainer",
|
|
16
|
+
"KillContainer",
|
|
17
|
+
"NodeInfo"
|
|
18
|
+
],
|
|
19
|
+
"template": {
|
|
20
|
+
"withCompare": true,
|
|
21
|
+
"withGenerator": true
|
|
22
|
+
}
|
|
23
|
+
}
|
data/bin/wf_node_api
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
=begin
|
|
3
|
+
__ ___ _ _ _____ ____ __ __
|
|
4
|
+
\ \ / / |__ (_) |_ ___| ___| _ ___ ___ / ___| \/ |
|
|
5
|
+
\ \ /\ / /| '_ \| | __/ _ \ |_ | | | / __|/ _ \ | | |\/| |
|
|
6
|
+
\ V V / | | | | | || __/ _|| |_| \__ \ __/ |___| | | |
|
|
7
|
+
\_/\_/ |_| |_|_|\__\___|_| \__,_|___/\___|\____|_| |_|
|
|
8
|
+
Container Manager
|
|
9
|
+
|
|
10
|
+
Copyright (C) 2015 David Prandzioch <kontakt@davidprandzioch.de>
|
|
11
|
+
|
|
12
|
+
This program is free software; you can redistribute it and/or
|
|
13
|
+
modify it under the terms of the GNU General Public License
|
|
14
|
+
as published by the Free Software Foundation; either version 2
|
|
15
|
+
of the License, or (at your option) any later version.
|
|
16
|
+
|
|
17
|
+
This program is distributed in the hope that it will be useful,
|
|
18
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20
|
+
GNU General Public License for more details.
|
|
21
|
+
|
|
22
|
+
You should have received a copy of the GNU General Public License
|
|
23
|
+
along with this program; if not, write to the Free Software
|
|
24
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
25
|
+
=end
|
|
26
|
+
|
|
27
|
+
THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
|
28
|
+
THIS_PATH = "#{File.dirname(THIS_FILE)}/../"
|
|
29
|
+
require File.join(THIS_PATH, 'lib/wf_node_api.rb')
|
|
30
|
+
|
|
31
|
+
config_template = File.read(File.join(THIS_PATH, 'lib/wf_node_api/config/config_template.erb'))
|
|
32
|
+
|
|
33
|
+
if Process.uid != 0
|
|
34
|
+
raise 'wf_node_api must be started as root user'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @todo bsd: /usr/local/etc/wf_node_api.conf
|
|
38
|
+
config_path = '/etc/wf_node_api.conf'
|
|
39
|
+
|
|
40
|
+
if false == File.exists?(config_path)
|
|
41
|
+
puts 'No config file exists. Trying to create...'
|
|
42
|
+
|
|
43
|
+
@api_token = SecureRandom.uuid
|
|
44
|
+
|
|
45
|
+
tpl = ERB.new(config_template)
|
|
46
|
+
File.write(config_path, tpl.result(binding()))
|
|
47
|
+
|
|
48
|
+
puts "Configuration has been written to #{config_path}"
|
|
49
|
+
puts "You can now execute 'wf_node_api start' to run in daemon mode."
|
|
50
|
+
|
|
51
|
+
exit 0
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
load config_path
|
|
55
|
+
ConfigCheck.run
|
|
56
|
+
|
|
57
|
+
$logger = Logger.new($log_file)
|
|
58
|
+
$logger.level = $log_level
|
|
59
|
+
|
|
60
|
+
if ARGV[0] == "check"
|
|
61
|
+
ContainerManager.new($container_type).check
|
|
62
|
+
exit 0
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if ARGV.empty?
|
|
66
|
+
webrick_options = {
|
|
67
|
+
:Host => $http_bind_addr,
|
|
68
|
+
:Port => 1357,
|
|
69
|
+
:Logger => WEBrick::Log::new($stderr, WEBrick::Log::DEBUG),
|
|
70
|
+
:SSLEnable => true,
|
|
71
|
+
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
|
|
72
|
+
:SSLCertName => [ [ 'CN', WEBrick::Utils::getservername ] ],
|
|
73
|
+
:RequestTimeout => 600
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Rack::Handler::WEBrick.run Api::NodeApi, webrick_options
|
|
77
|
+
exit 0
|
|
78
|
+
else
|
|
79
|
+
Daemons.run(__FILE__)
|
|
80
|
+
end
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
__ ___ _ _ _____ ____ __ __
|
|
3
|
+
\ \ / / |__ (_) |_ ___| ___| _ ___ ___ / ___| \/ |
|
|
4
|
+
\ \ /\ / /| '_ \| | __/ _ \ |_ | | | / __|/ _ \ | | |\/| |
|
|
5
|
+
\ V V / | | | | | || __/ _|| |_| \__ \ __/ |___| | | |
|
|
6
|
+
\_/\_/ |_| |_|_|\__\___|_| \__,_|___/\___|\____|_| |_|
|
|
7
|
+
Container Manager
|
|
8
|
+
|
|
9
|
+
Copyright (C) 2015 David Prandzioch <kontakt@davidprandzioch.de>
|
|
10
|
+
|
|
11
|
+
This program is free software; you can redistribute it and/or
|
|
12
|
+
modify it under the terms of the GNU General Public License
|
|
13
|
+
as published by the Free Software Foundation; either version 2
|
|
14
|
+
of the License, or (at your option) any later version.
|
|
15
|
+
|
|
16
|
+
This program is distributed in the hope that it will be useful,
|
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19
|
+
GNU General Public License for more details.
|
|
20
|
+
|
|
21
|
+
You should have received a copy of the GNU General Public License
|
|
22
|
+
along with this program; if not, write to the Free Software
|
|
23
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
24
|
+
=end
|
|
25
|
+
|
|
26
|
+
module Api
|
|
27
|
+
class NodeApi < Grape::API
|
|
28
|
+
format :json
|
|
29
|
+
version 'v1'
|
|
30
|
+
|
|
31
|
+
=begin
|
|
32
|
+
@apiDefine NotFoundError
|
|
33
|
+
@apiError (Not Found 404) error Object was not found
|
|
34
|
+
|
|
35
|
+
@apiErrorExample 404 Not Found
|
|
36
|
+
HTTP/1.1 404 Not Found
|
|
37
|
+
{
|
|
38
|
+
"error": "Not Found"
|
|
39
|
+
}
|
|
40
|
+
=end
|
|
41
|
+
|
|
42
|
+
=begin
|
|
43
|
+
@apiDefine ArgumentError
|
|
44
|
+
@apiError (Bad Request 400) error Invalid arguments supplied
|
|
45
|
+
|
|
46
|
+
@apiErrorExample 400 Bad Request
|
|
47
|
+
HTTP/1.1 400 Bad Request
|
|
48
|
+
{
|
|
49
|
+
"error": "The supplied container name is invalid"
|
|
50
|
+
}
|
|
51
|
+
=end
|
|
52
|
+
|
|
53
|
+
=begin
|
|
54
|
+
@apiDefine UnauthorizedError
|
|
55
|
+
@apiError (Unauthorized 401) error No valid API token was supplied
|
|
56
|
+
|
|
57
|
+
@apiErrorExample 401 Unauthorized
|
|
58
|
+
HTTP/1.1 401 Unauthorized
|
|
59
|
+
{
|
|
60
|
+
"error": "Unauthorized"
|
|
61
|
+
}
|
|
62
|
+
=end
|
|
63
|
+
before do
|
|
64
|
+
error!('Unauthorized', 401) unless headers['X-Api-Token'] == $api_token
|
|
65
|
+
|
|
66
|
+
@man = ContainerManager.new($container_type)
|
|
67
|
+
@resman = ResourceManager.new('linux')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
=begin
|
|
71
|
+
@apiDefine InternalError
|
|
72
|
+
@apiError (Internal Server Error 500) error The process could not be requested due to an internal error
|
|
73
|
+
|
|
74
|
+
@apiErrorExample 500 Internal Server Error
|
|
75
|
+
HTTP/1.1 500 Internal Server Error
|
|
76
|
+
{
|
|
77
|
+
"error": "Unknown error occured"
|
|
78
|
+
}
|
|
79
|
+
=end
|
|
80
|
+
rescue_from :all do |e|
|
|
81
|
+
error_response(message: e.message, status: 500)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
get '/' do
|
|
85
|
+
{}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
=begin
|
|
89
|
+
@api {get} /info Request node information
|
|
90
|
+
@apiVersion 1.0.0
|
|
91
|
+
@apiName NodeInfo
|
|
92
|
+
@apiGroup Node
|
|
93
|
+
|
|
94
|
+
@apiDescription Returns an array containing useful information about the node itself
|
|
95
|
+
and the resources available on it.
|
|
96
|
+
|
|
97
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
98
|
+
|
|
99
|
+
@apiSuccess {String} container_type The configured container type (lxc or vserver)
|
|
100
|
+
@apiSuccess {String} hostname The hostname of the system
|
|
101
|
+
@apiSuccess {String} api_version The version number of the node api
|
|
102
|
+
@apiSuccess {Integer} total_cpu_cores The number of cpu cores available totally
|
|
103
|
+
@apiSuccess {Integer} free_cpu_cores The number of free cpu cores
|
|
104
|
+
|
|
105
|
+
@apiUse UnauthorizedError
|
|
106
|
+
|
|
107
|
+
@apiUse InternalError
|
|
108
|
+
=end
|
|
109
|
+
get '/info' do
|
|
110
|
+
info = {}
|
|
111
|
+
|
|
112
|
+
info['container_type'] = $container_type
|
|
113
|
+
info['hostname'] = `#{$cmd_hostname}`.strip
|
|
114
|
+
info['api_version'] = WfNodeApi::VERSION
|
|
115
|
+
info['total_cpu_cores'] = @resman.total_cpu_cores
|
|
116
|
+
info['free_cpu_cores'] = @man.free_cpu_core_count(@resman)
|
|
117
|
+
|
|
118
|
+
info
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
=begin
|
|
122
|
+
@api {get} /containers Request container list
|
|
123
|
+
@apiVersion 1.0.0
|
|
124
|
+
@apiName GetContainers
|
|
125
|
+
@apiGroup Container
|
|
126
|
+
|
|
127
|
+
@apiDescription Returns an array of containers which are available on the node.
|
|
128
|
+
|
|
129
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
130
|
+
|
|
131
|
+
@apiSuccess {Object[]} containers List of available containers
|
|
132
|
+
@apiSuccess {String} containers.name Name of the container
|
|
133
|
+
@apiSuccess {String} containers.state State of the container (either 'RUNNING' or 'STOPPED')
|
|
134
|
+
@apiSuccess {String} containers.ip_address IP address assigned to the container
|
|
135
|
+
@apiSuccess {Integer} containers.cpu_cores Number of Vcores
|
|
136
|
+
@apiSuccess {Integer} containers.memory_limit_bytes Memory limit in bytes
|
|
137
|
+
@apiSuccess {Integer} containers.memory_usage_bytes Current amount of memory usage in bytes
|
|
138
|
+
@apiSuccess {Integer} containers.disk_space_gb Available disk space in GB
|
|
139
|
+
@apiSuccess {Integer} containers.disk_usage_gb Current amount of disk usage in GB
|
|
140
|
+
@apiSuccess {String} containers.container_type Container type, could be either 'lxc' or 'vserver'
|
|
141
|
+
|
|
142
|
+
@apiUse UnauthorizedError
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@apiUse InternalError
|
|
146
|
+
=end
|
|
147
|
+
get '/containers' do
|
|
148
|
+
@man.containers
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
=begin
|
|
152
|
+
@api {post} /containers Create a container
|
|
153
|
+
@apiVersion 1.0.0
|
|
154
|
+
@apiName CreateContainer
|
|
155
|
+
@apiGroup Container
|
|
156
|
+
|
|
157
|
+
@apiDescription Creates a container. Returns 201 on success!
|
|
158
|
+
|
|
159
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
160
|
+
|
|
161
|
+
@apiParam {String} name Name of the container (must be unique per node)
|
|
162
|
+
@apiParam {String} ip_address Valid IPv4 address
|
|
163
|
+
@apiParam {Integer} disk_size_gb Container disk size in GB
|
|
164
|
+
@apiParam {Integer} memory_limit_mb Memory limt in MB
|
|
165
|
+
@apiParam {Integer} cpu_core_count Amount of Vcores assigned to the container
|
|
166
|
+
|
|
167
|
+
@apiSuccess {String} success Success message
|
|
168
|
+
@apiSuccess {String} output STDOUT from container creation
|
|
169
|
+
|
|
170
|
+
@apiUse UnauthorizedError
|
|
171
|
+
@apiUse ArgumentError
|
|
172
|
+
@apiUse InternalError
|
|
173
|
+
=end
|
|
174
|
+
params do
|
|
175
|
+
requires :name, type: String
|
|
176
|
+
requires :ip_address, type: String
|
|
177
|
+
requires :disk_size_gb, type: Integer
|
|
178
|
+
requires :memory_limit_mb, type: Integer
|
|
179
|
+
requires :cpu_core_count, type: Integer
|
|
180
|
+
end
|
|
181
|
+
post '/containers' do
|
|
182
|
+
begin
|
|
183
|
+
res = @man.create_container(params[:name],
|
|
184
|
+
params[:ip_address],
|
|
185
|
+
params[:disk_size_gb],
|
|
186
|
+
params[:memory_limit_mb],
|
|
187
|
+
params[:cpu_core_count]
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
return { success: 'container was created', output: res }
|
|
191
|
+
rescue ArgumentError => e
|
|
192
|
+
error!(e.message, 400)
|
|
193
|
+
rescue ::NotFoundError => e
|
|
194
|
+
error!('Not Found', 404)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
=begin
|
|
199
|
+
@api {get} /containers/:name Request container by its name
|
|
200
|
+
@apiVersion 1.0.0
|
|
201
|
+
@apiName GetContainer
|
|
202
|
+
@apiGroup Container
|
|
203
|
+
|
|
204
|
+
@apiDescription Returns information on a specific container
|
|
205
|
+
|
|
206
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
207
|
+
|
|
208
|
+
@apiParam {String} name Unique name of the container
|
|
209
|
+
|
|
210
|
+
@apiSuccess {String} name Name of the container
|
|
211
|
+
@apiSuccess {String} state State of the container (either 'RUNNING' or 'STOPPED')
|
|
212
|
+
@apiSuccess {String} ip_address IP address assigned to the container
|
|
213
|
+
@apiSuccess {Integer} cpu_cores Number of Vcores
|
|
214
|
+
@apiSuccess {Integer} memory_limit_bytes Memory limit in bytes
|
|
215
|
+
@apiSuccess {Integer} memory_usage_bytes Current amount of memory usage in bytes
|
|
216
|
+
@apiSuccess {Integer} disk_space_gb Available disk space in GB
|
|
217
|
+
@apiSuccess {Integer} disk_usage_gb Current amount of disk usage in GB
|
|
218
|
+
@apiSuccess {String} container_type Container type, could be either 'lxc' or 'vserver'
|
|
219
|
+
|
|
220
|
+
@apiUse UnauthorizedError
|
|
221
|
+
@apiUse InternalError
|
|
222
|
+
@apiUse NotFoundError
|
|
223
|
+
=end
|
|
224
|
+
params do
|
|
225
|
+
requires :name, type: String
|
|
226
|
+
end
|
|
227
|
+
get '/containers/:name' do
|
|
228
|
+
begin
|
|
229
|
+
return @man.container(params[:name])
|
|
230
|
+
rescue ::NotFoundError => e
|
|
231
|
+
error!('Not Found', 404)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
=begin
|
|
236
|
+
@api {put} /containers/:name/start Start a container
|
|
237
|
+
@apiVersion 1.0.0
|
|
238
|
+
@apiName StartContainer
|
|
239
|
+
@apiGroup Container
|
|
240
|
+
|
|
241
|
+
@apiDescription Starts a container if it exists
|
|
242
|
+
|
|
243
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
244
|
+
|
|
245
|
+
@apiParam {String} name Unique name of the container
|
|
246
|
+
|
|
247
|
+
@apiSuccess {String} success Success message
|
|
248
|
+
@apiSuccess {String} output STDOUT from container start
|
|
249
|
+
|
|
250
|
+
@apiUse UnauthorizedError
|
|
251
|
+
@apiUse NotFoundError
|
|
252
|
+
@apiUse InternalError
|
|
253
|
+
=end
|
|
254
|
+
params do
|
|
255
|
+
requires :name, type: String
|
|
256
|
+
end
|
|
257
|
+
put '/containers/:name/start' do
|
|
258
|
+
begin
|
|
259
|
+
res = @man.start(params[:name])
|
|
260
|
+
return { success: 'container has been started', output: res }
|
|
261
|
+
rescue ::NotFoundError => e
|
|
262
|
+
error!('Not Found', 404)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
=begin
|
|
267
|
+
@api {put} /containers/:name/stop Stop a container
|
|
268
|
+
@apiVersion 1.0.0
|
|
269
|
+
@apiName StopContainer
|
|
270
|
+
@apiGroup Container
|
|
271
|
+
|
|
272
|
+
@apiDescription Stops a container if it exists
|
|
273
|
+
|
|
274
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
275
|
+
|
|
276
|
+
@apiParam {String} name Unique name of the container
|
|
277
|
+
|
|
278
|
+
@apiSuccess {String} success Success message
|
|
279
|
+
@apiSuccess {String} output STDOUT from container stop
|
|
280
|
+
|
|
281
|
+
@apiUse UnauthorizedError
|
|
282
|
+
@apiUse NotFoundError
|
|
283
|
+
@apiUse InternalError
|
|
284
|
+
=end
|
|
285
|
+
params do
|
|
286
|
+
requires :name, type: String
|
|
287
|
+
end
|
|
288
|
+
put '/containers/:name/stop' do
|
|
289
|
+
begin
|
|
290
|
+
res = @man.stop(params[:name])
|
|
291
|
+
return { success: 'container has been stopped', output: res }
|
|
292
|
+
rescue ::NotFoundError => e
|
|
293
|
+
error!('Not Found', 404)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
=begin
|
|
298
|
+
@api {put} /containers/:name/kill Kill a container
|
|
299
|
+
@apiVersion 1.0.0
|
|
300
|
+
@apiName KillContainer
|
|
301
|
+
@apiGroup Container
|
|
302
|
+
|
|
303
|
+
@apiDescription Kills a container if it exists. Does essentially the same as StopContainer
|
|
304
|
+
but forces the container to shut down and does not care about processes running on it.
|
|
305
|
+
|
|
306
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
307
|
+
|
|
308
|
+
@apiParam {String} name Unique name of the container
|
|
309
|
+
|
|
310
|
+
@apiSuccess {String} success Success message
|
|
311
|
+
@apiSuccess {String} output STDOUT from container kill
|
|
312
|
+
|
|
313
|
+
@apiUse UnauthorizedError
|
|
314
|
+
@apiUse NotFoundError
|
|
315
|
+
@apiUse InternalError
|
|
316
|
+
=end
|
|
317
|
+
params do
|
|
318
|
+
requires :name, type: String
|
|
319
|
+
end
|
|
320
|
+
put '/containers/:name/kill' do
|
|
321
|
+
begin
|
|
322
|
+
res = @man.kill(params[:name])
|
|
323
|
+
return { success: 'container has been killed', output: res }
|
|
324
|
+
rescue ::NotFoundError => e
|
|
325
|
+
error('Not Found', 404)
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
=begin
|
|
330
|
+
@api {delete} /containers/:name Delete a container
|
|
331
|
+
@apiVersion 1.0.0
|
|
332
|
+
@apiName DeleteContainer
|
|
333
|
+
@apiGroup Container
|
|
334
|
+
|
|
335
|
+
@apiDescription Deletes a container if it exists.
|
|
336
|
+
|
|
337
|
+
@apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf)
|
|
338
|
+
|
|
339
|
+
@apiParam {String} name Unique name of the container
|
|
340
|
+
|
|
341
|
+
@apiSuccess {String} success Success message
|
|
342
|
+
@apiSuccess {String} output STDOUT from container deletion
|
|
343
|
+
|
|
344
|
+
@apiUse UnauthorizedError
|
|
345
|
+
@apiUse NotFoundError
|
|
346
|
+
@apiUse InternalError
|
|
347
|
+
=end
|
|
348
|
+
params do
|
|
349
|
+
requires :name, type: String
|
|
350
|
+
end
|
|
351
|
+
delete '/containers/:name' do
|
|
352
|
+
begin
|
|
353
|
+
res = @man.delete(params[:name])
|
|
354
|
+
return { success: 'container has been deleted', output: res }
|
|
355
|
+
rescue ::NotFoundError => e
|
|
356
|
+
error!('Not Found', 404)
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# bind address for the rest api
|
|
2
|
+
$http_bind_addr = '0.0.0.0'
|
|
3
|
+
|
|
4
|
+
# ssl cert path - not working right now
|
|
5
|
+
$ssl_crt_path = ''
|
|
6
|
+
$ssl_key_path = ''
|
|
7
|
+
|
|
8
|
+
$api_token = '<%= @api_token %>'
|
|
9
|
+
|
|
10
|
+
$log_file = '/var/log/wf_node_api.log'
|
|
11
|
+
$log_level = Logger::INFO
|
|
12
|
+
|
|
13
|
+
# container name
|
|
14
|
+
# possible values: lxc, vserver, ezjail
|
|
15
|
+
$container_type = 'lxc'
|
|
16
|
+
|
|
17
|
+
# command for getting the hostname
|
|
18
|
+
$cmd_hostname = 'hostname'
|
|
19
|
+
|
|
20
|
+
$lxc_container_config_path = '/var/lib/lxc/[name]/config'
|
|
21
|
+
$lxc_ip_netmask = 24
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
$lxc_cgroup_mount_path = '/sys/fs/cgroup'
|
|
25
|
+
|
|
26
|
+
# lxc specific commands
|
|
27
|
+
$lxc_cmd_ls = 'lxc-ls'
|
|
28
|
+
$lxc_cmd_start = 'lxc-start -n [name] -d'
|
|
29
|
+
# dont set the timeout too high (broken pipes)
|
|
30
|
+
$lxc_cmd_stop = 'lxc-stop -n [name] --timeout=15'
|
|
31
|
+
$lxc_cmd_kill = 'lxc-stop -n [name] -k'
|
|
32
|
+
$lxc_cmd_info = 'lxc-info -n [name] -H'
|
|
33
|
+
$lxc_cmd_destroy = 'lxc-destroy -n [name] -f'
|
|
34
|
+
$lxc_cmd_create = 'lxc-create -t centos -n [name]'
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# linux-vserver specific commands
|
|
38
|
+
$vserver_cmd_ls = 'ls -1 /etc/vservers'
|
|
39
|
+
$vserver_cmd_start = 'vserver [name] start'
|
|
40
|
+
$vserver_cmd_stop = 'vserver [name] stop'
|
|
41
|
+
$vserver_cmd_stat = 'vserver-stat | grep [name]$'
|
|
42
|
+
$vserver_cmd_destroy = "echo 'y' | vserver [name] delete"
|
|
43
|
+
#$vserver_cmd_create = "vserver [name] build -m clone --context [context] --hostname [name] --interface eth0:[ip_address]/24 -- --source /vservers/test"
|
|
44
|
+
$vserver_cmd_create = "vserver [name] build -m debootstrap --context [context] --hostname [name] --interface eth0:[ip_address]/24 -- -d wheezy -m http://ftp.de.debian.org/debian"
|
|
45
|
+
|
|
46
|
+
$vserver_cmd_get_memory_limit = 'vlimit -c [context] -a -d | grep RSS'
|
|
47
|
+
|
|
48
|
+
$vserver_config_dir = '/etc/vservers/[name]'
|
|
49
|
+
|
|
50
|
+
$page_size_cmd = 'getconf PAGESIZE'
|