[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