[Kimchi-devel] [PATCH v12 6/6] Host device passthrough (Front-end): Add PCI Devices to VM

Aline Manera alinefm at linux.vnet.ibm.com
Mon Oct 13 15:45:40 UTC 2014


Just one comment:

When I select "Added" in the filter box, the all the dialog content 
moves to right.

On 10/08/2014 06:08 AM, Zhou Zheng Sheng wrote:
> From: Yu Xin Huo <huoyuxin at linux.vnet.ibm.com>
>
> Signed-off-by: Yu Xin Huo <huoyuxin at linux.vnet.ibm.com>
> Signed-off-by: Wen Wang <wenwang 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 | 81 ++++++++++++++++++++++++++++++++++
>   ui/pages/guest-edit.html.tmpl       | 28 ++++++++++++
>   4 files changed, 248 insertions(+), 2 deletions(-)
>
> diff --git a/ui/css/theme-default/guest-edit.css b/ui/css/theme-default/guest-edit.css
> index 76fbaf2..ef2266f 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 {
> @@ -261,3 +261,85 @@
>       width: 46%;
>       float: right;
>   }
> +
> +.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 3398bd4..86bfd22 100644
> --- a/ui/js/src/kimchi.api.js
> +++ b/ui/js/src/kimchi.api.js
> @@ -1114,6 +1114,20 @@ var kimchi = {
>           });
>       },
>
> +    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);
> +            }
> +        });
> +    },
> +
>       getISCSITargets : function(server, port, suc, err) {
>           server = encodeURIComponent(server);
>           port = port ? '&_server_port='+encodeURIComponent(port) : '';
> @@ -1144,6 +1158,47 @@ var kimchi = {
>           });
>       },
>
> +    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);
> +            }
> +        });
> +    },
> +
>       /**
>        * Add a volume to a given storage pool.
>        */
> diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
> index c281289..030e112 100644
> --- a/ui/js/src/kimchi.guest_edit_main.js
> +++ b/ui/js/src/kimchi.guest_edit_main.js
> @@ -359,6 +359,86 @@ kimchi.guest_edit_main = function() {
>           });
>       };
>
> +    var setupPCIDevice = function(){
> +        kimchi.getHostPCIDevices(function(hostPCIs){
> +            kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs){
> +                kimchi.getCapabilities(function(result) {
> +                    var pciEnabled = result.kernel_vfio;
> +                    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;
> +                            }
> +                        }
> +                        pciEnabled || $("button", itemNode).remove();
> +                        $("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(){
> +                                    kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs1){
> +                                        for(var k=0; k<hostPCIs.length; k++) {
> +                                            $("button", "#" + hostPCIs[k].name).button("option", "icons", {primary: "ui-icon-plus"});
> +                                        }
> +                                        for(var k=0; k<vmPCIs1.length; k++) {
> +                                            $("button", "#" + vmPCIs1[k].name).button("option", "icons", {primary: "ui-icon-minus"});
> +                                        }
> +                                    });
> +                                    filterNodes($("select", "#form-guest-edit-pci").val(), $("input", "#form-guest-edit-pci").val());
> +                                });
> +                            }else{
> +                                kimchi.addVMPCIDevice(kimchi.selectedGuest, { name: obj.parent().prop("id") }, function(){
> +                                    kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs1){
> +                                        for(var k=0; k<vmPCIs1.length; k++) {
> +                                            $("button", "#" + vmPCIs1[k].name).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);
> @@ -395,6 +475,7 @@ kimchi.guest_edit_main = function() {
>           initStorageListeners();
>           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 917b2e8..69b11a7 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">$_("Host PCI Device")</a>
> +                </li>
>               </ul>
>               <form id="form-guest-edit-general">
>                   <fieldset class="guest-edit-fieldset">
> @@ -138,6 +141,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>
> @@ -221,6 +241,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>




More information about the Kimchi-devel mailing list