wf_node_api 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|