[Kimchi-devel] [V2 1/2] Add users/groups to VM

huoyuxin at linux.vnet.ibm.com huoyuxin at linux.vnet.ibm.com
Tue Jul 22 09:33:10 UTC 2014


From: Yu Xin Huo <huoyuxin at linux.vnet.ibm.com>

Signed-off-by: Yu Xin Huo <huoyuxin at linux.vnet.ibm.com>
---
 ui/css/theme-default/guest-edit.css |  116 +++++++++++++++++++++++++++++++++++
 ui/images/theme-default/group.png   |  Bin 0 -> 1703 bytes
 ui/images/theme-default/user.png    |  Bin 0 -> 1322 bytes
 ui/js/src/kimchi.api.js             |   28 ++++++++
 ui/js/src/kimchi.guest_edit_main.js |  112 ++++++++++++++++++++++++++++++++-
 ui/pages/guest-edit.html.tmpl       |   37 +++++++++++
 6 files changed, 290 insertions(+), 3 deletions(-)
 create mode 100644 ui/images/theme-default/group.png
 create mode 100644 ui/images/theme-default/user.png

diff --git a/ui/css/theme-default/guest-edit.css b/ui/css/theme-default/guest-edit.css
index 3ce48be..8c2b26f 100644
--- a/ui/css/theme-default/guest-edit.css
+++ b/ui/css/theme-default/guest-edit.css
@@ -162,3 +162,119 @@
 .guest-edit-interface .hide {
     display: none;
 }
+
+.guest-edit-permission {
+    height: 240px;
+    padding: 5px 10px!important;
+}
+
+.guest-edit-permission .column {
+    display: inline-block;
+    vertical-align: top;
+    height: 100%;
+}
+
+.guest-edit-permission .title {
+    margin-bottom: 3px;
+}
+
+.guest-edit-permission input[type="text"] {
+    margin-bottom: 3px;
+    font-size: 12px;
+    width: 97%;
+}
+
+.guest-edit-permission .body {
+    border: 1px solid #999999;
+    font-size: 12px;
+    padding: 1px;
+    overflow: auto;
+}
+
+.guest-edit-permission .body .head {
+    margin-bottom: 3px;
+    font-weight: bold;
+    background: linear-gradient(to bottom, #E5E5E5 0%, #C4C4C4 100%) repeat scroll 0 0 transparent;
+}
+
+.guest-edit-permission .body .item {
+    padding: 2px 3px;
+    margin-bottom: 1px;
+    cursor: pointer;
+}
+
+.guest-edit-permission .body .item:hover {
+    background-color: #AAAAAA;
+}
+
+.guest-edit-permission .body .item-picked {
+    background-color: #BBBBBB;
+}
+
+.guest-edit-permission .body .item .icon {
+    display: inline-block;
+    height: 15px;
+    width: 15px;
+    vertical-align: bottom;
+}
+
+.guest-edit-permission .body .item .user-icon {
+    background: url('/images/theme-default/user.png') no-repeat scroll;
+    background-size: 15px 15px;
+}
+
+.guest-edit-permission .body .item .group-icon {
+    background: url('/images/theme-default/group.png') no-repeat scroll;
+    background-size: 15px 15px;
+}
+
+.guest-edit-permission .avail {
+    width: 58%;
+}
+
+.guest-edit-permission .avail .body {
+    height: 192px;
+}
+
+.guest-edit-permission .avail .body .column-user {
+    width: 48%;
+}
+.guest-edit-permission .avail .body .column-group {
+    width: 50%;
+}
+
+.guest-edit-permission .control {
+    width: 9%;
+}
+
+.guest-edit-permission .control button {
+    width: 26px;
+    margin-left: 18px;
+}
+
+.guest-edit-permission .control button:first-child {
+    margin-top: 110px;
+    margin-bottom: 2px;
+}
+
+.guest-edit-permission .control .ui-button-text-only .ui-button-text {
+    padding: 2px 8px;
+}
+
+.guest-edit-permission .selected {
+    width: 30%;
+    float: right;
+}
+
+.guest-edit-permission .selected .title {
+    height: 43px;
+}
+
+.guest-edit-permission .selected .body {
+    height: 192px;
+}
+
+#form-guest-edit-permission-save {
+    float: right;
+    margin-right: 10px;
+}
diff --git a/ui/images/theme-default/group.png b/ui/images/theme-default/group.png
new file mode 100644
index 0000000000000000000000000000000000000000..1160bd97178375f202c3c20fef689ddf4a6dcfae
GIT binary patch
literal 1703
zcmV;Y23YxtP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU&Nl8RORCwCNS9?s8R}{bBqot*VmO`u2
z73hYPhb at ot@PRUQFz|tzm>K_=)0sIn{<XyibGT({Vw{pJTQnrgqMI>U7Ux{1;*3V8
zWNO4Ij{2AksU%LE7{a^H{mv%^EG?Kp;%!du*ZbY?o^yWpch0$&^ZWhmWi~M(Az^%0
z;+Vj5yq)KHJN_wse%}?p&tC at zdxEE4tFIe0z|Z_+)C<jmkS~+VzLm at 67Eu(Xaj(bA
z+#dIXzP`RSc&-VjM;xniQ6}2eYV~iCk&zK-3<xle<Cxd$WiFS?)ZNv6ytA{j)a`bk
z4rPQm765pGXR*52!}17ugi@&_BnIBeWHL!G#si&0PyT&k at _0P1VQY-ReTIdt9M7dF
z6bi|6BJ at z9F+xQYM1w}FDWh+O89=c7pC7?*x7!zD-zCU{l at B!nhBBMYwg4n$!P~$~
z|HBDQ;Q1mzxeuOP2GZwbqHHe~vXIi^H;V=GkXkqcNN8 at HKGr~e at Ro-~0FwoHSFKj5
z&uKK8burqQd~J-jC|VQ!fl95q4z_Ptw7C4l+V$_dh;SnrKr+Q at bq3ZR6#;@*p;T0Y
z-D{wbMMXuiNL3_LsZ`Q4M4^mSemO0Fx^DKI*{dd}OqN*h^ZAAejnn($k~e<vd3`U2
z0KBt+)gO~Wf|%G%dr3lZu2d)`V<3m87tHv6>a>De;ZUIO*R5ZB73<ZKL8Br-L`kuv
ztiXo?g;A*eB{mcJU{D<TyzHFpswvitVe`zdn%T}>J37!W&$i`cNy>u|5QA$05oJ>R
zr2O{w_CbYV8X=RHpZB`SWZJ)d=k~W+TU(1A4GxBQXXzQ~EIvN|3Z|{f&Ccrqc^z1L
zi^uJ$8Z{Fd40_ at At=nw0LPcCjO|{6gtvT&LqonS})dYjVP>5G@$VGcr?mfURXtml?
z at LcBcdiHjAckA)4Vvqwtu%U>s!kLBFLJ=xhKvY&Xzw8pe$w#VPVoT5b$Ci<K7;*s5
z_uy?lw(%_V%%x1Jic~SA>@D`p+}&YGNDI#>obgTByfW!ITv!q5R=>Bp2QXhSy<*x5
z1wTe8BKiPzJ&1Z0+-QNa%TPK?%9Kdks2gMeLj-LEYNa7bNJ_J;*^YNsuJ}4FEj6Ta
znlldu&R;NZeNLubS@~(D&oIHjqNAgUc&W%6c8D=5I!Z!mXpNAf2x#bHb=A@~>J9qm
z!-C^=*v~EXjvJrh?=L?cJyukEv6eO7Ym}HzF<riBA(8JZFuMXCZLhs_ at nFNB4Hqi6
zZd1csPg`4?NMx2WUx-EyfD5dnqhltg*XxH?w`45vD?T-YFq<&+`5*PyHlSY$p at Rk;
zE{NHrybf?5118gO at c6Fg^vUXn4<FX-*}XU7(W6JQaLNM>=L81S4smgDaZ+3hypV;x
zIfwYy5M(r=x3~8=tlf{r&cZ0^WCMjpbZ>)P6_^`Mkb-~=ggbNO*pVGi+u9Cn{BTp^
zXvLI5Rj1QAB?I8O5n1gf7L1|HMb^^<SD%Zy+%D-k5Ry`LLxQ4t)YE?=B#fnbKVPZ4
zyt8Ug)uodsYPgY5pluLD!OhboU5xGvxlA4tD6N4cLj(%se<B!(R2RVH{!BP9S4!Eu
zP>v8wUbcMMK|*Gv;zX^hvrERqdmV-rQ_UV)*8^FR79wQ<=|ANROVNS4uhnUH8I8tG
zvx;VUM+#$Ft6*vY6DJrZyxZH?D+FK}OCuxTl?eo$xb2h5GpA0TDxvtNW;UByVp0N2
zNK9lI85t}qJF^GQoEO2wr7bNj10Id(kjhCXWS0C|^2#}L=j=;MPb--?X(B@^rq?$i
zj(+(aavtImVX-9u{kU8Yu$C-BHWz2W3P>)7oYpkk<3O6H{?=W`U}6IN>hbV?r~zGF
zU5V+I3>WSLb)ib|bJY;>D~$K`45+FkPWeaY6u))bM?IxwrA$glV{9nJY+?BVwz*<+
z*NfgaxW`Xhm!L0)6gM|JjrW_HSYzYg?19tCoX!UWX|wr$v&8b`$;ktRrMf_O%OrCW
zSe`@&5GP*MkXVvak4k625bdv~yMqQG9X`8G at f>s9X|P}{9b$!8`h}XZf7}bXK4dL=
xz7t?K_Pq&p;n{h??+d&4&l&Ktujl^>FaVgriY_I-t at r={002ovPDHLkV1m5fG0*@2

literal 0
HcmV?d00001

diff --git a/ui/images/theme-default/user.png b/ui/images/theme-default/user.png
new file mode 100644
index 0000000000000000000000000000000000000000..c57a81a92757ef31c424a4e6c741f71db62a1092
GIT binary patch
literal 1322
zcmV+_1=aeAP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$%t=H+RCwCFS6xgTRTRGSvwt(QEW2!%
zZEC<RY*%PmU|~TT(9l}brY~)zO*HkzHZ`VcV>GER{yyo84?Y{zXpHs6S4l9Y#$eJ`
zmI9TeNz<hS;wC6n(*0#;*YAuwlVv;L6r^`@m^(Xj at A=NT=X~eDmCI%J$6w2=dc>kV
zY@@+(9ODK4xF85;1zu=k91CHOq^hbvsYP|PR4&aWrYD(|;jiDtI5Pm<(b&U^nWnhO
zZnuB!bUFte4hIuOQ3F&emDt+a8q4K!YCf0$1oO+2)4!@#0EkwQl5$ualok1!EXhHq
z%gJmu8{>K206<bG6ogDB^F}6}*^Ol{S=pO6{k6PaIG$r3kLNqL+Z|Ng3M1<QNK>wD
z0wClKm&?WQ4U=X0#ew+2^IHe7-h8rlfP at r~VhtmXu2yJ}XCzr-e!u_2cz2($B>?5B
zi|2UO+S2;E!|Bj0HB)Q`0>S806y at n{9{~c7$%@p!ndP-YM`IIhEY=e{_Fn+RjXY4D
zb{x;w(OtLDQsClyUxV+7?FS)7Fxa?e#qxE6tFbYV-gXdDdWFN`J9K{(0F)I&&kRj$
zI|#vW?8M0vpCb(|D<`nShlY!hry^t9K7x{3LJ-PdzWUnvKdl1r at A9)#r$@fP4l7&p
zK#etB9o>b2g9B$ST)a at CRMeTzOi1}V at 4bC5&=`2jO0Zg at ViXxFP-BUi$(LJN_Ksfp
z=3D3WYuB~o(FYyT;UkCH$jA$KK}644v0lp-vto3ht%C^2h1~xbJa874jpHaz!TRjf
zY@!{XyqnEtPcAMl+BGYX^P$j_DNIKpA3+{;9_VVv`tOm%b^yJ6^VZZ?maAd3z0;0@
z^8+}4h*+&yEHYHNtJz%k6}(OoDNW5J6wD))C57Iu_-s)vYB2+#M<hwQVt3em#0U9&
zo&oSVtQoZgARg=c6uf^<=YBd{Y`}8a9F^U1Jl{ry%u<!a_#1N%?h2Ge at cpwW*%8Sl
zF#ymAiApspWGS6aAB88zHwA!z8&qWFXDTRUy%7gEZ}J3fMsuAPv~1!2Wj+Ec3L+D2
zqQ(OhuzFCF7qC8cf8~C7W^Vd{X+O}>78M%&4WH3QB-PYQo53<|<J#h5P&Rc-l^#J?
ztdGi32J7nTKEUIfrfCS5pT-%6Ny$cqM^~a*D~g8DbG5~0>&O6nb1AyN(`O36>+`;^
zE8i^Fw<;AciT(!v#fQ?cbAMMCx}7NsJl&F=7!*g?e<hVl1yaAKR6|o}Z|D*QkY09o
zN@#y%ln=dSY#kHg^-=2m9;N1QW$4+`+|+aik2gd;`n?U_M)dhR4nPNiKf{Ix&_Fij
z3wd5}JSG6RifhF^Mi%tOdm`1jyVF9%1!9s64=8STpq4mxa*!S{s%Us%UnHDGZax<4
zb!iSYtJOTviuu)rdkcFeCVpX4i3FROnWX~qzgZm!1kk2;v%da**4x{|>b>>js0Gj0
z79%RJ$03IxgUidyp5)ymo1dR&^T~O(w6w(16;L1%wz|4%C<yKjGVr{ij5;GUFVxVY
zR|qke<XXV1A0cCv`|^h6xNTp%_8-x2w{KCTwpR&x%A<1^#8<T}S=9xRvL(nY<R)Z}
gniR8!<R1YB09_*wa#VgYhyVZp07*qoM6N<$f^kM~^#A|>

literal 0
HcmV?d00001

diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 021be63..936e964 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -1056,5 +1056,33 @@ var kimchi = {
                 kimchi.message.error(data.responseJSON.reason);
             }
         });
+    },
+
+    getHostUsers : function(suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'host/users',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend : true,
+            success : suc,
+            error : err ? err : function(data) {
+                kimchi.message.error(data.responseJSON.reason);
+            }
+        });
+    },
+
+    getHostGroups : function(suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'host/groups',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend : true,
+            success : suc,
+            error : err ? err : function(data) {
+                kimchi.message.error(data.responseJSON.reason);
+            }
+        });
     }
 };
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 99dbe96..2e21e70 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -19,12 +19,13 @@ kimchi.guest_edit_main = function() {
     var buttonContainer = $('#action-button-container');
     $('#guest-edit-tabs').tabs({
         beforeActivate: function(event, ui) {
+            $(buttonContainer).addClass('hidden');
+            $("#form-guest-edit-permission-save").addClass('hidden');
             var deactivated = ui['newPanel'];
             if($(deactivated).attr('id') === 'form-guest-edit-general') {
                 $(buttonContainer).removeClass('hidden');
-            }
-            else {
-                $(buttonContainer).addClass('hidden');
+            }else if($(deactivated).attr('id') === 'form-guest-edit-permission'){
+                $("#form-guest-edit-permission-save").removeClass('hidden');
             }
         }
     });
@@ -236,6 +237,110 @@ kimchi.guest_edit_main = function() {
         });
     };
 
+    var setupPermission = function() {
+        var userNodes = {}, groupNodes = {};
+        kimchi.retrieveVM(kimchi.selectedGuest, function(vm){
+            kimchi.getHostUsers(function(users){
+                kimchi.getHostGroups(function(groups){
+                    var subArray = function(a1, a2){ //a1-a2
+                        for(var i=0; i<a2.length; i++){
+                            for(var j=0; j<a1.length; j++){
+                                if(a2[i] == a1[j]){
+                                    a1.splice(j, 1);
+                                    break;
+                                }
+                            }
+                        }
+                    };
+                    subArray(users, vm.users); subArray(groups, vm.groups);
+                    init(users, groups, vm.users, vm.groups);
+                });
+            });
+        });
+        var sortNodes = function(container, isUser){
+            nodes = container.children();
+            var keys = [];
+            nodes.each(function(){
+                keys.push($("label", this).text());
+            });
+            keys.sort();
+            container.empty();
+            for(var i=0; i<keys.length; i++){
+                var itemNode = isUser ? userNodes[keys[i]] : groupNodes[keys[i]];
+                $(itemNode).click(function(){
+                    $(this).toggleClass("item-picked");
+                });
+                container.append(itemNode);
+            }
+        };
+        var init = function(availUsers, availGroups, selUsers, selGroups){
+            var initNode = function(key, isUserNode){
+                var nodeGroups = isUserNode ? userNodes : groupNodes;
+                nodeGroups[key] = $.parseHTML(kimchi.substitute($('#permission-item').html(), {
+                    val: key,
+                    class: isUserNode? "user-icon" : "group-icon"
+                }));
+            };
+            for(var i=0; i<availUsers.length; i++){
+                initNode(availUsers[i], true);
+                $("#permission-avail-users").append(userNodes[availUsers[i]]);
+                sortNodes($("#permission-avail-users"), true);
+            }
+            for(var i=0; i<selUsers.length; i++){
+                initNode(selUsers[i], true);
+                $("#permission-sel-users").append(userNodes[selUsers[i]]);
+                sortNodes($("#permission-sel-users"), true);
+            }
+            for(var i=0; i<availGroups.length; i++){
+                initNode(availGroups[i], false);
+                $("#permission-avail-groups").append(groupNodes[availGroups[i]]);
+                sortNodes($("#permission-avail-groups"), false);
+            }
+            for(var i=0; i<selGroups.length; i++){
+                initNode(selGroups[i], false);
+                $("#permission-sel-groups").append(groupNodes[selGroups[i]]);
+                sortNodes($("#permission-sel-groups"), false);
+            }
+        };
+        var filterNodes = function(key, container){
+            container.children().each(function(){
+                $(this).css("display", $("label", this).text().indexOf(key)==-1 ? "none" : "");
+            });
+        }
+        $("#permission-searchBox").on("keyup", function() {
+            var key = $(this).val();
+            filterNodes(key, $("#permission-avail-users"));
+            filterNodes(key, $("#permission-avail-groups"));
+        });
+        $('#permissionGo').button().click(function() {
+            $("#permission-avail-users").children(".item-picked").appendTo("#permission-sel-users").removeClass("item-picked");
+            sortNodes($("#permission-sel-users"), true);
+            $("#permission-avail-groups").children(".item-picked").appendTo("#permission-sel-groups").removeClass("item-picked");
+            sortNodes($("#permission-sel-groups"), false);
+        });
+        $('#permissionBack').button().click(function() {
+            $("#permission-sel-users").children(".item-picked").appendTo("#permission-avail-users").removeClass("item-picked");
+            sortNodes($("#permission-avail-users"), true);
+            $("#permission-sel-groups").children(".item-picked").appendTo("#permission-avail-groups").removeClass("item-picked");
+            sortNodes($("#permission-avail-groups"), false);
+            $("#permission-searchBox").val("");
+            filterNodes("", $("#permission-avail-users"));
+            filterNodes("", $("#permission-avail-groups"));
+        });
+        $("#form-guest-edit-permission-save").on("click", function(){
+            var content = { users: [], groups: [] };
+            $("#permission-sel-users").children().each(function(){
+                content.users.push($("label", this).text());
+            });
+            $("#permission-sel-groups").children().each(function(){
+                content.groups.push($("label", this).text());
+            });
+            kimchi.updateVM(kimchi.selectedGuest, content, function(){
+                kimchi.window.close();
+            });
+        });
+    };
+
     var initContent = function(guest) {
         guest['icon'] = guest['icon'] || 'images/icon-vm.png';
         $('#form-guest-edit-general').fillWithObject(guest);
@@ -265,6 +370,7 @@ kimchi.guest_edit_main = function() {
         initStorageListeners();
 
         setupInterface();
+        setupPermission();
 
         kimchi.topic('kimchi/vmCDROMAttached').subscribe(onAttached);
         kimchi.topic('kimchi/vmCDROMReplaced').subscribe(onReplaced);
diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl
index ded892c..bb5f28d 100644
--- a/ui/pages/guest-edit.html.tmpl
+++ b/ui/pages/guest-edit.html.tmpl
@@ -38,6 +38,9 @@
                 <li>
                     <a href="#form-guest-edit-interface">$_("Interface")</a>
                 </li>
+                <li>
+                    <a href="#form-guest-edit-permission">$_("Permission")</a>
+                </li>
             </ul>
             <form id="form-guest-edit-general">
                 <fieldset class="guest-edit-fieldset">
@@ -109,6 +112,31 @@
                 </div>
                 <div class="body"></div>
             </form>
+            <form id="form-guest-edit-permission" class="guest-edit-permission">
+                    <div class="column avail">
+                        <div class="title">$_("Available system users and groups")</div>
+                        <input type="text" id="permission-searchBox">
+                        <div class="body">
+                            <div class="head">
+                                <div class="column column-user"><div class="item">Users</div></div>
+                                <div class="column column-group"><div class="item">Groups</div></div>
+                            </div>
+                            <div id="permission-avail-users" class="column column-user"></div>
+                            <div id="permission-avail-groups"  class="column column-group"></div>
+                        </div>
+                    </div>
+                    <div class="column control">
+                        <button id="permissionGo"> > </button>
+                        <button id="permissionBack"> < </button>
+                    </div>
+                    <div class="column selected">
+                        <div class="title">$_("Selected system users and groups")</div>
+                        <div class="body">
+                            <div id="permission-sel-users"></div>
+                            <div id="permission-sel-groups"></div>
+                        </div>
+                    </div>
+            </form>
         </div>
     </div>
     <footer>
@@ -117,6 +145,9 @@
                 <span class="text">$_("Save")</span>
             </button>
         </div>
+        <button id="form-guest-edit-permission-save" class="btn-normal hidden">
+            <span class="text">$_("Save")</span>
+        </button>
     </footer>
 </div>
 <script id="cdrom-row-tmpl" type="text/html">
@@ -186,6 +217,12 @@
         </span>
     </div>
 </script>
+<script id="permission-item" type="text/html">
+<div class="item">
+    <span class="icon {class}"></span>
+    <label>{val}</label>
+</div>
+</script>
 <script type="text/javascript">
     kimchi.guest_edit_main();
 </script>
-- 
1.7.1




More information about the Kimchi-devel mailing list