[Kimchi-devel] [PATCH] Passthrough: Add PCI Devices to VM

huoyuxin at linux.vnet.ibm.com huoyuxin at linux.vnet.ibm.com
Wed Aug 6 10:44:38 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 |   86 ++++++++++++++++++++++++++++++++++-
 ui/js/src/kimchi.api.js             |   55 ++++++++++++++++++++++
 ui/js/src/kimchi.guest_edit_main.js |   66 +++++++++++++++++++++++++++
 ui/pages/guest-edit.html.tmpl       |   28 +++++++++++
 4 files changed, 233 insertions(+), 2 deletions(-)

diff --git a/ui/css/theme-default/guest-edit.css b/ui/css/theme-default/guest-edit.css
index 1092cc9..c9b43bd 100644
--- a/ui/css/theme-default/guest-edit.css
+++ b/ui/css/theme-default/guest-edit.css
@@ -17,8 +17,8 @@
  */
 #guest-edit-window {
     font-size: 13px;
-    height: 400px;
-    width: 610px;
+    height: 420px;
+    width: 820px;
 }
 
 #guest-edit-tabs {
@@ -266,3 +266,85 @@
     float: right;
     margin-right: 10px;
 }
+
+.guest-edit-pci {
+    height: 79%;
+    overflow: auto;
+    font-size: 12px;
+}
+
+.guest-edit-pci .filter {
+    height: 35px;
+    margin-right: 5px;
+    overflow: hidden;
+}
+
+.guest-edit-pci .group {
+    float: right;
+}
+
+.guest-edit-pci .filter .control {
+    border: 1px solid #AAAAAA;
+    font-size: 12px;
+    background-color: white;
+}
+
+.guest-edit-pci .filter select {
+    border-right: 0px!important;
+    border-radius: 7px 0px 0px 7px;
+    padding: 2px 2px 2px 7px;
+    width: 100px;
+}
+
+.guest-edit-pci .filter select option {
+    padding-left: 7px;
+}
+
+.guest-edit-pci .filter input {
+    border-radius: 0px 7px 7px 0px;
+    padding: 3px 3px 3px 10px;
+    width: 200px;
+    font-style: italic;
+}
+
+.guest-edit-pci .header {
+    margin-bottom: 8px;
+    padding-bottom: 2px;
+    font-weight: bold;
+    border-bottom: 1px solid #999999;
+}
+
+.guest-edit-pci .item {
+    margin-bottom: 4px;
+    overflow: hidden;
+}
+
+.guest-edit-pci .cell {
+    display: inline-block;
+    vertical-align: middle;
+    margin-right: 10px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.guest-edit-pci .item button {
+    width: 20px;
+    height: 20px;
+    float: right;
+}
+
+.guest-edit-pci .name {
+    width: 18%;
+    max-width: 18%;
+}
+
+.guest-edit-pci .product {
+    width: 45%;
+    max-width: 45%;
+}
+
+.guest-edit-pci .vendor {
+    width: 25%;
+    max-width: 25%;
+}
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 4562992..ad91ad3 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -1098,5 +1098,60 @@ var kimchi = {
                 kimchi.message.error(data.responseJSON.reason);
             }
         });
+    },
+
+    getHostPCIDevices : function(suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'host/devices?_passthrough=true&_cap=pci',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend : true,
+            success : suc,
+            error : err ? err : function(data) {
+                kimchi.message.error(data.responseJSON.reason);
+            }
+        });
+    },
+
+    getVMPCIDevices : function(id, suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'vms/'+encodeURIComponent(id)+'/hostdevs',
+            type : 'GET',
+            contentType : 'application/json',
+            dataType : 'json',
+            resend : true,
+            success : suc,
+            error : err ? err : function(data) {
+                kimchi.message.error(data.responseJSON.reason);
+            }
+        });
+    },
+
+    addVMPCIDevice : function(vm, device, suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'vms/'+ encodeURIComponent(vm) +'/hostdevs',
+            type : 'POST',
+            contentType : 'application/json',
+            dataType : 'json',
+            data : JSON.stringify(device),
+            success : suc,
+            error : err ? err : function(data) {
+                kimchi.message.error(data.responseJSON.reason);
+            }
+        });
+    },
+
+    removeVMPCIDevice : function(vm, device, suc, err) {
+        kimchi.requestJSON({
+            url : kimchi.url + 'vms/'+ encodeURIComponent(vm) +'/hostdevs/' + encodeURIComponent(device),
+            type : 'DELETE',
+            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_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 38a2bc0..d002add 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -349,6 +349,71 @@ kimchi.guest_edit_main = function() {
         });
     };
 
+    var setupPCIDevice = function(){
+        kimchi.getHostPCIDevices(function(hostPCIs){
+            kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs){
+                for(var i=0; i<hostPCIs.length; i++){
+                    var itemNode = $.parseHTML(kimchi.substitute($('#pci-tmpl').html(),{
+                        name: hostPCIs[i].name,
+                        product: hostPCIs[i].product.description,
+                        vendor: hostPCIs[i].vendor.description
+                    }));
+                    $(".body", "#form-guest-edit-pci").append(itemNode);
+                    var iconClass = "ui-icon-plus";
+                    for(var j=0; j<vmPCIs.length; j++){
+                        if(hostPCIs[i].name==vmPCIs[j].name){
+                            iconClass = "ui-icon-minus";
+                            break;
+                        }
+                    }
+                    $("button", itemNode).button({
+                        icons: { primary: iconClass },
+                        text: false
+                    }).click(function(){
+                        var obj = $(this);
+                        if(obj.button("option", "icons").primary == "ui-icon-minus"){
+                            kimchi.removeVMPCIDevice(kimchi.selectedGuest, obj.parent().prop("id"), function(){
+                                obj.button("option", "icons", { primary: "ui-icon-plus" });
+                                filterNodes($("select", "#form-guest-edit-pci").val(), $("input", "#form-guest-edit-pci").val());
+                            });
+                        }else{
+                            kimchi.addVMPCIDevice(kimchi.selectedGuest, { name: obj.parent().prop("id") }, function(){
+                                obj.button("option", "icons", { primary: "ui-icon-minus" });
+                                filterNodes($("select", "#form-guest-edit-pci").val(), $("input", "#form-guest-edit-pci").val());
+                            });
+                        }
+                    });
+                }
+            });
+        });
+        var filterNodes = function(group, text){
+            text = text.toLowerCase();
+            $(".body", "#form-guest-edit-pci").children().each(function(){
+                var textFilter = $(".name", this).text().toLowerCase().indexOf(text)!=-1;
+                textFilter = textFilter || $(".product", this).text().toLowerCase().indexOf(text)!=-1;
+                textFilter = textFilter || $(".vendor", this).text().toLowerCase().indexOf(text)!=-1;
+                var display = "none";
+                var itemGroup = $("button", this).button("option", "icons").primary;
+                if(textFilter){
+                    if(group == "all"){
+                        display = "";
+                    }else if(group=="toAdd" && itemGroup=="ui-icon-plus"){
+                        display = ""
+                    }else if(group == "added" && itemGroup=="ui-icon-minus"){
+                        display = ""
+                    }
+                }
+                $(this).css("display", display);
+            });
+        };
+        $("select", "#form-guest-edit-pci").change(function(){
+            filterNodes($(this).val(), $("input", "#form-guest-edit-pci").val());
+        });
+        $("input", "#form-guest-edit-pci").on("keyup", function() {
+            filterNodes($("select", "#form-guest-edit-pci").val(), $(this).val());
+        });
+    };
+
     var initContent = function(guest) {
         guest['icon'] = guest['icon'] || 'images/icon-vm.png';
         $('#form-guest-edit-general').fillWithObject(guest);
@@ -379,6 +444,7 @@ kimchi.guest_edit_main = function() {
 
         setupInterface();
         setupPermission();
+        setupPCIDevice();
 
         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 1c1d7d4..7ae3bfd 100644
--- a/ui/pages/guest-edit.html.tmpl
+++ b/ui/pages/guest-edit.html.tmpl
@@ -41,6 +41,9 @@
                 <li>
                     <a href="#form-guest-edit-permission">$_("Permission")</a>
                 </li>
+                <li>
+                    <a href="#form-guest-edit-pci">$_("PCI Device")</a>
+                </li>
             </ul>
             <form id="form-guest-edit-general">
                 <fieldset class="guest-edit-fieldset">
@@ -142,6 +145,23 @@
                         </div>
                     </div>
             </form>
+            <form id="form-guest-edit-pci" class="guest-edit-pci">
+                <div class="filter">
+                    <span class="group">
+                        <select class="control">
+                            <option value="all">$_("All")</option>
+                            <option value="toAdd">$_("To Add")</option>
+                            <option value="added">$_("Added")</option>
+                        </select><input type="text" class="control" placeholder="$_("filter")">
+                    </span>
+                </div>
+                <div class="header">
+                    <span class="cell name">$_("Name")</span>
+                    <span class="cell product">$_("Product")</span>
+                    <span class="cell vendor">$_("Vendor")</span>
+                </div>
+                <div class="body"></div>
+            </form>
         </div>
     </div>
     <footer>
@@ -228,6 +248,14 @@
     <label>{val}</label>
 </div>
 </script>
+<script id="pci-tmpl" type="text/html">
+<div class="item" id="{name}">
+    <span class="cell name" title="{name}">{name}</span>
+    <span class="cell product" title="{product}">{product}</span>
+    <span class="cell vendor" title="{vendor}">{vendor}</span>
+    <button></button>
+</div>
+</script>
 <script type="text/javascript">
     kimchi.guest_edit_main();
 </script>
-- 
1.7.1




More information about the Kimchi-devel mailing list