[PATCH v3]
by Christy Perez
This patchset is a better functioning, but not final, version of the
topology logic. Aline asked that I send another version with details
for the UI will interact with the cpu_info API.
The flow will be:
- GET /host/cpu_info:
curl -k -u user -H 'Content-Type: application/json' \
-H 'Accept: application/json' https://localhost:8001/host/cpuinfo
{
"cores":2,
"threading_enabled":true,
"sockets":1,
"threads_per_core":2
}
Note: I removed the cores_online and cores_present, and changed it
to just cores. I think the other was too much info.
- Based on that information, plus the host arch, the UI can display
- If host arch is Power:
- Display a menu labled SMT, with up to four check-boxes.
The check-boxes will be labeled SMT1, SMT2, SMT4, and SMT8.
The max SMT value displayed will be dependant upon
threads_per_core from above. The default checkbox should be the
greatest SMT value (e.g. SMT8).
- Display the same box for CPUs as before. I had initially thought
about having a drop-down for CPUs instead of the empty field,
(with only legal vCPU amounts, like 1,2,4,8, etc.), but that will
get complicated with different types of processors, and also
be too tedious to use. So, unless someone objects,
I think the next best thing to do, is just slightly adjust the number
of vCPUs the user asked for in order to make sure that the number
is a legal number to use with a topology (since vCPUS must equal
sockets * cores * threads).
Note: See below return from get_rec_topology. If different than
what the user entered, this new vcpus should replace the number
entered by the user. If some kind of effect could be shown
when it's changed, that might be helpful.
- Else:
- Display a menu labeled Hyper-Threading, with only a checkbox labeled
HT.
Note: The same comments for vCPUS as above apply here. The number
maybe need to change based on the CPU capabilities.
- The user's selections from those fields is sent to the get_rec_topology
method, which will then return two values:
{'topology': {'sockets': sockets, 'cores': cores, 'threads': threads},
'vcpus': best_vcpus}
These values can then be used to create the template:
curl -k -u user -X POST -H 'Content-Typ: application/json' -H 'Accept: application/json' \
https://localhost:8001/templates -d'{"name": "test_topo", "cdrom": "/isos/DVD_name.iso", \
"cpus":4, "cpu_info": {"topology": {"sockets": 1, "cores": 2, "threads":2}}}'
What doesn't work right now:
- Some error messages still need to be created.
- API doc needs to be added.
Christy Perez (1):
Parts to allow Kimchi to configure the cpu topology.
docs/API.md | 2 +
src/kimchi/API.json | 6 ++
src/kimchi/control/cpuinfo.py | 37 +++++++++
src/kimchi/control/host.py | 2 +
src/kimchi/i18n.py | 2 +
src/kimchi/model/cpuinfo.py | 175 ++++++++++++++++++++++++++++++++++++++++++
src/kimchi/model/host.py | 1 +
src/kimchi/model/templates.py | 16 +++-
8 files changed, 240 insertions(+), 1 deletion(-)
create mode 100644 src/kimchi/control/cpuinfo.py
create mode 100644 src/kimchi/model/cpuinfo.py
--
1.9.3
10 years
[PATCH v3] Auto Topology for Guest Templates
by Christy Perez
This patchset is a better functioning, but not final, version of the
topology logic. Aline asked that I send another version with details
for the UI will interact with the cpu_info API.
The flow will be:
- GET /host/cpu_info:
curl -k -u user -H 'Content-Type: application/json' \
-H 'Accept: application/json' https://localhost:8001/host/cpuinfo
{
"cores":2,
"threading_enabled":true,
"sockets":1,
"threads_per_core":2
}
Note: I removed the cores_online and cores_present, and changed it
to just cores. I think the other was too much info.
- Based on that information, plus the host arch, the UI can display
- If host arch is Power:
- Display a menu labled SMT, with up to four check-boxes.
The check-boxes will be labeled SMT1, SMT2, SMT4, and SMT8.
The max SMT value displayed will be dependant upon
threads_per_core from above. The default checkbox should be the
greatest SMT value (e.g. SMT8).
- Display the same box for CPUs as before. I had initially thought
about having a drop-down for CPUs instead of the empty field,
(with only legal vCPU amounts, like 1,2,4,8, etc.), but that will
get complicated with different types of processors, and also
be too tedious to use. So, unless someone objects,
I think the next best thing to do, is just slightly adjust the number
of vCPUs the user asked for in order to make sure that the number
is a legal number to use with a topology (since vCPUS must equal
sockets * cores * threads).
Note: See below return from get_rec_topology. If different than
what the user entered, this new vcpus should replace the number
entered by the user. If some kind of effect could be shown
when it's changed, that might be helpful.
- Else:
- Display a menu labeled Hyper-Threading, with only a checkbox labeled
HT.
Note: The same comments for vCPUS as above apply here. The number
maybe need to change based on the CPU capabilities.
- The user's selections from those fields is sent to the get_rec_topology
method, which will then return two values:
{'topology': {'sockets': sockets, 'cores': cores, 'threads': threads},
'vcpus': best_vcpus}
These values can then be used to create the template:
curl -k -u user -X POST -H 'Content-Typ: application/json' -H 'Accept: application/json' \
https://localhost:8001/templates -d'{"name": "test_topo", "cdrom": "/isos/DVD_name.iso", \
"cpus":4, "cpu_info": {"topology": {"sockets": 1, "cores": 2, "threads":2}}}'
What doesn't work right now:
- Some error messages still need to be created.
- API doc needs to be added.
Christy Perez (1):
Parts to allow Kimchi to configure the cpu topology.
docs/API.md | 2 +
src/kimchi/API.json | 6 ++
src/kimchi/control/cpuinfo.py | 37 +++++++++
src/kimchi/control/host.py | 2 +
src/kimchi/i18n.py | 2 +
src/kimchi/model/cpuinfo.py | 175 ++++++++++++++++++++++++++++++++++++++++++
src/kimchi/model/host.py | 1 +
src/kimchi/model/templates.py | 16 +++-
8 files changed, 240 insertions(+), 1 deletion(-)
create mode 100644 src/kimchi/control/cpuinfo.py
create mode 100644 src/kimchi/model/cpuinfo.py
--
1.9.3
10 years
[PATCH 00/10] Add snapshot support
by Crístian Viana
Crístian Viana (10):
Update clone test
snapshot: Create domain snapshots
snapshot: Lookup a domain snapshot
snapshot: List domain snapshots
snapshot: Delete a domain snapshot
snapshot: Lookup current snapshot on a domain
snapshot: Revert a domain to a snapshot
snapshot: Add model tests
snapshot: Delete snapshots when deleting a VM
snapshot: Clone snapshots when cloning a VM
docs/API.md | 30 ++++++
src/kimchi/control/vm/snapshots.py | 58 +++++++++++
src/kimchi/i18n.py | 10 ++
src/kimchi/mockmodel.py | 94 ++++++++++++++++++
src/kimchi/model/vms.py | 47 ++++++++-
src/kimchi/model/vmsnapshots.py | 192 +++++++++++++++++++++++++++++++++++++
tests/test_model.py | 74 +++++++++++++-
tests/test_rest.py | 100 +++++++++++++++++++
8 files changed, 603 insertions(+), 2 deletions(-)
create mode 100644 src/kimchi/control/vm/snapshots.py
create mode 100644 src/kimchi/model/vmsnapshots.py
--
1.9.3
10 years
[PATCH] Issue #473: Update selectMenu method to set a default value.
by Paulo Vital
On all pages with selectMenu (combobox) the user had to choose an
option to effectively store its value in the form.
This patch updates the function to use the first option as default
value. With this patch, user can skip the combo selection if want
use the first option.
Signed-off-by: Paulo Vital <pvital(a)linux.vnet.ibm.com>
---
ui/js/widgets/select-menu.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/js/widgets/select-menu.js b/ui/js/widgets/select-menu.js
index c4b0209..4a79605 100644
--- a/ui/js/widgets/select-menu.js
+++ b/ui/js/widgets/select-menu.js
@@ -46,6 +46,7 @@
if(option.value === value) {
item.addClass(selectedClass);
that.label.text(option.label);
+ that.target.val(option.value);
}
that.listControl.append(item);
});
--
1.9.3
10 years
[PATCH v4] Keep disk ref_counts accurate
by Christy Perez
v1 : Change the way storage is represented (as volumes).
v1->v2:
- Royce pointed out that the concept of a volume was a new feature to
libvirt, and after some investigation I found that this would break
kimchi on RHEL 6.
- I changed from using the pool:vol label to identify storage to using
the path alone. This will make it easier to track disks not in pools.
v2->v3:
- Rebase and fixed conflicts
- Add ref_cnt checking on update. This problem was found by the model test
that ejects a CD ROM, leaving a blank 'path' element in the XML.
- Resolve issue with circular include of [s,g]et_ref_cnt functions in both
vmstorages.py and storagevolumes.py by creating a new diskutils module.
v3->v4:
- Remove unused lookup_by_path() method
Christy Perez (1):
Prevent disks from being added twice
src/kimchi/model/diskutils.py | 75 ++++++++++++++++++++++++++++++++++++++
src/kimchi/model/storagevolumes.py | 38 +++----------------
src/kimchi/model/vmstorages.py | 70 +++++++++++++++++++++++++++++++----
3 files changed, 143 insertions(+), 40 deletions(-)
create mode 100644 src/kimchi/model/diskutils.py
--
1.9.3
10 years
[PATCH] Delete ui/js/modernizr.custom.2.6.2.min.js
by Aline Manera
This file is not in use by Kimchi. So we don't need to keep it in the
source code.
Signed-off-by: Aline Manera <alinefm(a)linux.vnet.ibm.com>
---
ui/js/modernizr.custom.2.6.2.min.js | 4 ----
1 file changed, 4 deletions(-)
delete mode 100644 ui/js/modernizr.custom.2.6.2.min.js
diff --git a/ui/js/modernizr.custom.2.6.2.min.js b/ui/js/modernizr.custom.2.6.2.min.js
deleted file mode 100644
index 39a08de..0000000
--- a/ui/js/modernizr.custom.2.6.2.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
- * Build: http://modernizr.com/download/#-boxshadow-multiplebgs-cssgradients-shiv-m...
- */
-;window.Modernizr=function(a,b,c){function A(a){j.cssText=a}function B(a,b){return A(m.join(a+";")+(b||""))}function C(a,b){return typeof a===b}function D(a,b){return!!~(""+a).indexOf(b)}function E(a,b){for(var d in a){var e=a[d];if(!D(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function F(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:C(f,"function")?f.bind(d||b):f}return!1}function G(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return C(b,"string")||C(b,"undefined")?E(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),F(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?!
e[d]:h+(d+1),l.appendChild(j);return f=["­",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return w("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},y={}.hasOwnProperty,z;!C(y,"undefined")&&!C(y.call,"undefined")?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var!
f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.multiplebgs=function(){return A("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},q.boxshadow=function(){return G("boxShadow")},q.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return A((a+"-webkit- ".split(" ").join(b+a)+m.join(c+a)).slice(0,-a.length)),D(j.backgroundImage,"gradient")};for(var H in q)z(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)z(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},A(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getE!
lementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<st!
yle>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag!
.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section su!
mmary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shiv!
Methods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.mq=x,e.testProp=function(a){return E([a])},e.testAllProps=G,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document);
\ No newline at end of file
--
1.9.3
10 years
[PATCH] Delete ui/libs/modernizr.custom.76777.js
by Aline Manera
modernizr provides support for HTML5 and CSS3. As all the browsers
supported by Kimchi alreay has support for those technologies we don't
need it.
Signed-off-by: Aline Manera <alinefm(a)linux.vnet.ibm.com>
---
ui/libs/modernizr.custom.76777.js | 4 ----
ui/pages/kimchi-ui.html.tmpl | 1 -
ui/pages/login.html.tmpl | 1 -
3 files changed, 6 deletions(-)
delete mode 100644 ui/libs/modernizr.custom.76777.js
diff --git a/ui/libs/modernizr.custom.76777.js b/ui/libs/modernizr.custom.76777.js
deleted file mode 100644
index 187b113..0000000
--- a/ui/libs/modernizr.custom.76777.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
- * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borde...
- */
-;window.Modernizr=function(a,b,c){function C(a){j.cssText=a}function D(a,b){return C(n.join(a+";")+(b||""))}function E(a,b){return typeof a===b}function F(a,b){return!!~(""+a).indexOf(b)}function G(a,b){for(var d in a){var e=a[d];if(!F(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function H(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:E(f,"function")?f.bind(d||b):f}return!1}function I(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return E(b,"string")||E(b,"undefined")?G(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),H(e,b,c))}function J(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="!
position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["­",'<styl!
e id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=E(e[d],"function"),E(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),A={}.hasOwnProperty,B;!E(A,"undefined")&&!E(A.call,"undefined")?B=function(a,b){return A.call(a,b)}:B=function(a,b){return b in a&&E(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(a!
rguments,1),e=function(){if(this instanceof e){var a=function(){};a.pro!
totype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return I("flexWrap")},s.flexboxlegacy=function(){return I("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!E(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!I("indexedDB",a)},s.hashchange=function(){return z("has!
hchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return C("background-color:rgba(150,255,150,.5)"),F(j.backgroundColor,"rgba")},s.hsla=function(){return C("background-color:hsla(120,40%,100%,.5)"),F(j.backgroundColor,"rgba")||F(j.backgroundColor,"hsla")},s.multiplebgs=function(){return C("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return I("backgroundSize")},s.borderimage=function(){return I("borderImage")},s.borderradius=function(){return I("borderRadius")},s.boxshadow=function(){return I("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return D("opacity:.55"),/^0.55$/.test(!
j.opacity)},s.cssanimations=function(){return I("animationName")},s.css!
columns=function(){return I("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return C((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),F(j.backgroundImage,"gradient")},s.cssreflections=function(){return I("boxReflect")},s.csstransforms=function(){return!!I("transform")},s.csstransforms3d=function(){var a=!!I("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return I("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d!
.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h)!
,localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=fun!
ction(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var K in s)B(s,K)&&(x=K.toLowerCase(),e[x]=s[K](),v.push((e[x]?"":"no-")+x));return e.input||J(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)B(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},C("!
"),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function(!
"h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMe!
thods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details fig!
caption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.hasEvent=z,e.testProp=function(a){return G([a])},e.testAllProps=I,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.r!
emoveChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].on!
load()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b!
=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].sl!
ice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}el!
se!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createE!
lement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
\ No newline at end of file
diff --git a/ui/pages/kimchi-ui.html.tmpl b/ui/pages/kimchi-ui.html.tmpl
index aee3c4a..2f592a6 100644
--- a/ui/pages/kimchi-ui.html.tmpl
+++ b/ui/pages/kimchi-ui.html.tmpl
@@ -33,7 +33,6 @@
<link rel="stylesheet" href="$href('libs/themes/base/jquery-ui.min.css')">
<link rel="stylesheet" href="$href('css/theme-default.min.css')">
-<script src="$href('libs/modernizr.custom.76777.js')"></script>
<script src="$href('libs/jquery-1.10.0.min.js')"></script>
<script src="$href('libs/jquery-ui.min.js')"></script>
<script src="$href('libs/jquery-ui-i18n.min.js')"></script>
diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl
index d4d5b7e..f289af5 100644
--- a/ui/pages/login.html.tmpl
+++ b/ui/pages/login.html.tmpl
@@ -32,7 +32,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<link rel="shortcut icon" href="images/logo.ico">
<link rel="stylesheet" href="$href('css/theme-default.min.css')">
-<script src="$href('libs/modernizr.custom.76777.js')"></script>
<script src="$href('libs/jquery-1.10.0.min.js')"></script>
<script src="$href('libs/jquery-ui.min.js')"></script>
<script src="$href('libs/jquery-ui-i18n.min.js')"></script>
--
1.9.3
10 years
[PATCH v2] Auto Topology for Guest Templates
by Christy Perez
This patchset is a better functioning, but not final, version of the
topology logic. Aline asked that I send another version with details
for the UI will interact with the cpu_info API.
The flow will be:
- GET /host/cpu_info:
Returns {'threading_enabled': boolean
'sockets': integer
'cores_present': integer
'cores_online': integer
'threads_per_core': integer
}
- Based on that information, plus the host arch, the UI can display
- If host arch is Power:
- Display a menu labled SMT, with up to four check-boxes.
The check-boxes will be labeled SMT1, SMT2, SMT4, and SMT8.
The max SMT value displayed will be dependant upon
threads_per_core from above. The default checkbox should be the
greatest SMT value (e.g. SMT8).
- Display the same box for CPUs as before. I had initially thought
about having a drop-down for CPUs instead of the empty field,
(with only legal vCPU amounts, like 1,2,4,8, etc.), but that will
get complicated with different types of processors, and also
be too tedious to use. So, unless someone objects,
I think the next best thing to do, is just slightly adjust the number
of vCPUs the user asked for in order to make sure that the number
is a legal number to use with a topology (since vCPUS must equal
sockets * cores * threads).
- Else:
- Display a menu labeled Hyper-Threading, with only a checkbox labeled
HT.
- The user's selections from those fields is sent to the get_rec_topology
method, which will then return two values:
{'topology': {'sockets': sockets, 'cores': cores, 'threads': threads},
'vcpus': best_vcpus}
These values can then be used to create the template:
curl -k -u user -X POST -H 'Content-Typ: application/json' -H 'Accept: application/json' \
https://localhost:8001/templates -d'{"name": "test_topo", "cdrom": "/isos/DVD_name.iso", \
"cpus":4, "cpu_info": {"topology": {"sockets": 1, "cores": 2, "threads":2}}}'
What doesn't work right now:
- The GET for cpu_info.
- Some error messages still need to be created.
- Some values of vCPUs will return an error that topology isn't supported.
Hopefully this description will help the UI developers while I finish.
Christy Perez (1):
Parts to allow Kimchi to configure the cpu topology.
docs/API.md | 2 +
src/kimchi/API.json | 6 ++
src/kimchi/control/cpuinfo.py | 35 ++++++++
src/kimchi/i18n.py | 2 +
src/kimchi/model/cpuinfo.py | 183 ++++++++++++++++++++++++++++++++++++++++++
src/kimchi/model/host.py | 1 +
src/kimchi/model/templates.py | 15 +++-
7 files changed, 243 insertions(+), 1 deletion(-)
create mode 100644 src/kimchi/control/cpuinfo.py
create mode 100644 src/kimchi/model/cpuinfo.py
--
1.9.3
10 years
[v5] UI: Clone Guest(static message)
by huoyuxin@linux.vnet.ibm.com
From: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
Signed-off-by: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
---
ui/css/theme-default/button.css | 4 ++
ui/css/theme-default/list.css | 18 ++++++
ui/js/src/kimchi.api.js | 17 +++++-
ui/js/src/kimchi.guest_main.js | 111 +++++++++++++++++++++++++++++++--------
ui/pages/guest.html.tmpl | 6 ++-
ui/pages/i18n.json.tmpl | 1 +
6 files changed, 132 insertions(+), 25 deletions(-)
diff --git a/ui/css/theme-default/button.css b/ui/css/theme-default/button.css
index 499bf4a..0df53a6 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -50,6 +50,10 @@
cursor: pointer;
}
+.btn[disabled] {
+ opacity: 0.3;
+}
+
.btn:not([disabled]):hover {
box-shadow: -2px -2px 2px #dadada, 2px 2px 2px #fff, 3px 3px 3px white
inset, -3px -3px 3px rgba(0, 0, 0, .25) inset;
diff --git a/ui/css/theme-default/list.css b/ui/css/theme-default/list.css
index 8ffee69..ded18eb 100644
--- a/ui/css/theme-default/list.css
+++ b/ui/css/theme-default/list.css
@@ -275,3 +275,21 @@
text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff;
padding-left: 10px;
}
+
+.guest-clone {
+ margin: 10px;
+}
+
+.guest-clone .icon {
+ background: url('../../images/theme-default/kimchi-loading15x15.gif') no-repeat;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.guest-clone .text {
+ color: #666666;
+ margin-left: 5px;
+ text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF;
+}
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 5895a07..2f90219 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -695,10 +695,10 @@ var kimchi = {
}, 2000);
break;
case 'finished':
- suc(result);
+ suc && suc(result);
break;
case 'failed':
- err(result);
+ err && err(result);
break;
default:
break;
@@ -1233,5 +1233,18 @@ var kimchi = {
success : suc,
error : err
});
+ },
+
+ cloneGuest: function(vm, suc, err) {
+ kimchi.requestJSON({
+ url : kimchi.url + 'vms/'+encodeURIComponent(vm)+"/clone",
+ type : 'POST',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err ? err : function(data) {
+ kimchi.message.error(data.responseJSON.reason);
+ }
+ });
}
};
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index dbe8753..2fd5c55 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -15,6 +15,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+kimchi.sampleGuestObject = {
+ "name": "",
+ "uuid": "",
+ "state": "shutoff",
+ "persistent": true,
+ "icon": null,
+ "cpus": 0,
+ "memory": 0,
+ "stats": {
+ "net_throughput": 0,
+ "io_throughput_peak": 100,
+ "cpu_utilization": 0,
+ "io_throughput": 0,
+ "net_throughput_peak": 100
+ },
+ "screenshot": null,
+ "graphics": {
+ "passwd": null,
+ "passwdValidTo": null,
+ "type": "vnc",
+ "port": null,
+ "listen": "127.0.0.1"
+ },
+ "users": [],
+ "groups": [],
+ "access": "full"
+};
+
kimchi.vmstart = function(event) {
var button=$(this);
@@ -173,8 +201,24 @@ kimchi.listVmsAuto = function() {
if (kimchi.vmTimeout) {
clearTimeout(kimchi.vmTimeout);
}
+ var getCloningGuests = function(){
+ var guests = [];
+ kimchi.getTasksByFilter('status=running&target_uri='+encodeURIComponent('^/vms/*'), function(tasks) {
+ for(var i=0;i<tasks.length;i++){
+ var guestUri = tasks[i].target_uri;
+ var guestName = guestUri.substring(guestUri.lastIndexOf('/')+1, guestUri.length);
+ guests.push($.extend({}, kimchi.sampleGuestObject, {name: guestName, isCloning: true}));
+ if(kimchi.trackingTasks.indexOf(tasks[i].id)==-1)
+ kimchi.trackTask(tasks[i].id, null, function(err){
+ kimchi.message.error(err.message);
+ }, null);
+ }
+ }, null, true);
+ return guests;
+ };
kimchi.listVMs(function(result, textStatus, jqXHR) {
if (result && textStatus=="success") {
+ result = getCloningGuests().concat(result);
if(result.length) {
var listHtml = '';
var guestTemplate = kimchi.guestTemplate;
@@ -233,14 +277,16 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
imgLoad.attr('src',load_src);
//Link the stopped tile to the start action, the running tile to open the console
- if (vmRunningBool) {
- liveTile.off("click", kimchi.vmstart);
- liveTile.on("click", kimchi.openVmConsole);
- }
- else {
- liveTile.off("click", kimchi.openVmConsole);
- liveTile.on("click", kimchi.vmstart);
- liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ if(!vmObject.isCloning){
+ if (vmRunningBool) {
+ liveTile.off("click", kimchi.vmstart);
+ liveTile.on("click", kimchi.openVmConsole);
+ }
+ else {
+ liveTile.off("click", kimchi.openVmConsole);
+ liveTile.on("click", kimchi.vmstart);
+ liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ }
}
@@ -257,6 +303,7 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
//Setup the VM Actions
var guestActions=result.find("div[name=guest-actions]");
guestActions.find(".shutoff-disabled").prop('disabled', !vmRunningBool );
+ guestActions.find(".running-disabled").prop('disabled', vmRunningBool );
if (vmRunningBool) {
guestActions.find(".running-hidden").hide();
@@ -276,21 +323,41 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
}
//Setup action event handlers
- guestActions.find("[name=vm-start]").on({click : kimchi.vmstart});
- guestActions.find("[name=vm-poweroff]").on({click : kimchi.vmpoweroff});
- if (vmRunningBool) { //If the guest is not running, do not enable reset
- guestActions.find("[name=vm-reset]").on({click : kimchi.vmreset});
- }
- if (vmRunningBool) { //If the guest is not running, do not enable shutdown
- guestActions.find("[name=vm-shutdown]").on({click : kimchi.vmshutdown});
- }
- guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
- guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
+ if(!vmObject.isCloning){
+ guestActions.find("[name=vm-start]").on({click : kimchi.vmstart});
+ guestActions.find("[name=vm-poweroff]").on({click : kimchi.vmpoweroff});
+ if (vmRunningBool) { //If the guest is not running, do not enable reset
+ guestActions.find("[name=vm-reset]").on({click : kimchi.vmreset});
+ }
+ if (vmRunningBool) { //If the guest is not running, do not enable shutdown
+ guestActions.find("[name=vm-shutdown]").on({click : kimchi.vmshutdown});
+ }
+ guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
+ guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
+ guestActions.find("[name=vm-clone]").click(function(){
+ var guest = $(this).closest('li[name=guest]').attr("id");
+ kimchi.confirm({
+ title : i18n['KCHAPI6006M'],
+ content : i18n['KCHVM6010M'],
+ confirm : i18n['KCHAPI6002M'],
+ cancel : i18n['KCHAPI6003M']
+ }, function() {
+ kimchi.cloneGuest(guest, function(data){
+ kimchi.listVmsAuto();
+ });
+ }, null);
+ });
+
+ //Maintain menu open state
+ var actionMenu=guestActions.find("div[name=actionmenu]");
+ if (openMenu) {
+ $('.popover', actionMenu).toggle();
+ }
- //Maintain menu open state
- var actionMenu=guestActions.find("div[name=actionmenu]");
- if (openMenu) {
- $('.popover', actionMenu).toggle();
+ }else{
+ guestActions.find('.btn').attr('disabled', true);
+ result.find('.guest-clone').removeClass('hide-content');
+ $('.popover', guestActions.find("div[name=actionmenu]")).remove();
}
return result;
diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
index 43fb350..74206fd 100644
--- a/ui/pages/guest.html.tmpl
+++ b/ui/pages/guest.html.tmpl
@@ -26,6 +26,9 @@
<div class="guest-general">
<h2 class="title" title="{name}">{name}</h2>
</div>
+ <div class="guest-clone hide-content">
+ <span class="icon"></span><span class="text">$_("Cloning")...</span>
+ </div>
</div>
<div name="cpu_utilization" class="sortable">
<div class="circleGauge"></div>
@@ -56,7 +59,8 @@
<span class="text">$_("Actions")</span><span class="arrow"></span>
<div class="popover actionsheet right-side" style="width: 250px">
<button class="button-big shutoff-disabled" name="vm-console" ><span class="text">$_("Connect")</span></button>
- <button class="button-big running-disabled" name="vm-edit"><span class="text">$_("Edit")</span></button>
+ <button class="button-big running-disabled" name="vm-clone"><span class="text">$_("Clone")</span></button>
+ <button class="button-big" name="vm-edit"><span class="text">$_("Edit")</span></button>
<button class="button-big shutoff-hidden" name="vm-reset"><span class="text">$_("Reset")</span></button>
<button class="button-big shutoff-hidden" name="vm-shutdown"><span class="text">$_("Shut Down")</span></button>
<button class="button-big running-hidden" name="vm-start"><span class="text">$_("Start")</span></button>
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl
index 75f1e43..56abd36 100644
--- a/ui/pages/i18n.json.tmpl
+++ b/ui/pages/i18n.json.tmpl
@@ -128,6 +128,7 @@
"KCHVM6007M": "$_("Note the guest OS may ignore this request. Would you like to continue?")",
"KCHVM6008M": "$_("Virtual Machine delete Confirmation")",
"KCHVM6009M": "$_("This virtual machine is not persistent. Power Off will delete it. Continue?")",
+ "KCHVM6010M": "$_("When the target guest has SCSI or iSCSI volumes, they will be cloned on default storage pool. The same will happen when the target pool does not have enough space to clone the volumes. Do you want to continue?")",
"KCHVMCD6001M": "$_("This CDROM will be detached permanently and you can re-attach it. Continue to detach it?")",
"KCHVMCD6002M": "$_("Attach")",
--
1.7.1
10 years
[PATCH v2 0/5] Clone virtual machine
by Crístian Viana
This is the difference between this and the previous patchset (v1):
- The function "StorageVolumes.create(volume_path)" was rewritten as
"StorageVolume.clone(pool, name)".
- Patch 2 has been updated to fix the test error (introduced by a commit
pushed later).
- The function "get_next_clone_name" was moved to the module "kimchi.utils" and
was generified (i.e. it can handle different resources other than VMs, such as
storage volumes)
Crístian Viana (5):
Add model function to wait for task
Clean up test pool directories
Clone storage volume
Clone virtual machine
Add tests and mockmodel for the cloning feature
docs/API.md | 10 ++
src/kimchi/control/storagevolumes.py | 1 +
src/kimchi/control/vms.py | 1 +
src/kimchi/i18n.py | 5 +
src/kimchi/mockmodel.py | 86 ++++++++++-
src/kimchi/model/storagevolumes.py | 97 +++++++++++-
src/kimchi/model/tasks.py | 28 ++++
src/kimchi/model/vms.py | 280 ++++++++++++++++++++++++++++++++++-
src/kimchi/utils.py | 41 +++++
tests/test_model.py | 81 ++++++++--
tests/test_rest.py | 54 +++++++
11 files changed, 669 insertions(+), 15 deletions(-)
--
1.9.3
10 years