
From: Samuel GuimarĂ£es <sguimaraes943@gmail.com> Signed-off-by: Samuel GuimarĂ£es <sguimaraes943@gmail.com> Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com> --- model/vmhostdevs.py | 2 +- ui/css/kimchi.css | 5 + ui/css/src/modules/_edit-guests.scss | 4 + ui/js/src/kimchi.guest_edit_main.js | 204 +++++++++++++++++++++-------------- ui/js/src/kimchi.guest_main.js | 10 +- ui/pages/guest-edit.html.tmpl | 20 ++-- ui/pages/i18n.json.tmpl | 2 + 7 files changed, 148 insertions(+), 99 deletions(-) diff --git a/model/vmhostdevs.py b/model/vmhostdevs.py index 2130ac4..b57cbf0 100644 --- a/model/vmhostdevs.py +++ b/model/vmhostdevs.py @@ -510,7 +510,7 @@ class VMHostDevModel(object): return self.task.lookup(taskid) def _detach_device(self, cb, params): - cb('Detaching device.') + cb('Detaching device') vmid = params['vmid'] dev_name = params['dev_name'] dom = params['dom'] diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css index 34347c2..59d96e1 100644 --- a/ui/css/kimchi.css +++ b/ui/css/kimchi.css @@ -1039,6 +1039,11 @@ body.wok-gallery { width: 22%; } +#guest-edit-window #form-guest-edit-pci .wok-mask { + top: 0 !important; + z-index: 2 !important; +} + #guest-edit-window #form-guest-edit-pci .column-actions { width: 4.47%; } diff --git a/ui/css/src/modules/_edit-guests.scss b/ui/css/src/modules/_edit-guests.scss index 6196ed9..b7e6941 100644 --- a/ui/css/src/modules/_edit-guests.scss +++ b/ui/css/src/modules/_edit-guests.scss @@ -62,6 +62,10 @@ } } #form-guest-edit-pci { + .wok-mask { + top: 0 !important; + z-index: 2 !important; + } .column-actions { width: 4.47%; } diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js index fc67d82..cabd497 100644 --- a/ui/js/src/kimchi.guest_edit_main.js +++ b/ui/js/src/kimchi.guest_edit_main.js @@ -425,16 +425,16 @@ kimchi.guest_edit_main = function() { var filterPCINodes = function(group, text) { text = text.trim().split(" "); var rows = $('.body', '#form-guest-edit-pci').find('div'); - if(text === ""){ + if (text === "") { rows.show(); return; } rows.hide(); - rows.filter(function(index, value){ + rows.filter(function(index, value) { var $span = $(this); var $itemGroup = $('button i', this); - for (var i = 0; i < text.length; ++i){ + for (var i = 0; i < text.length; ++i) { if ($span.is(":containsNC('" + text[i] + "')")) { if (group === 'all') { return true; @@ -448,87 +448,26 @@ kimchi.guest_edit_main = function() { return false; }).show(); }; - var setupPCIDevice = function() { - kimchi.getAvailableHostPCIDevices(function(hostPCIs) { - kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { - setupNode(hostPCIs, 'fa-power-off'); - setupNode(vmPCIs, 'fa-ban'); - }); - }); - $('select', '#form-guest-edit-pci').change(function() { - filterPCINodes($(this).val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); - }); - $('select', '#form-guest-edit-pci').selectpicker(); - $('input#guest-edit-pci-filter', '#form-guest-edit-pci').on('keyup', function() { - filterPCINodes($('select', '#form-guest-edit-pci').val(), $(this).val()); - }); - }; - var setupNode = function(arrPCIDevices, iconClass) { + + var _generatePciDeviceHtml = function(devices, pciType) { var pciEnabled = kimchi.capabilities.kernel_vfio; - var pciDeviceName, pciDeviceProduct, pciDeviceProductDesc, pciDeviceVendor, pciDeviceVendorDesc, pciDeviceStatus; - for (var i = 0; i < arrPCIDevices.length; i++) { - pciDeviceName = arrPCIDevices[i].name; - pciDeviceProduct = arrPCIDevices[i].product; - pciDeviceVendor = arrPCIDevices[i].vendor; - pciDeviceStatus = (iconClass === 'fa-ban') ? 'enabled' : 'disabled'; - if (pciDeviceProduct !== null) { - pciDeviceProductDesc = pciDeviceProduct.description; - } - if (pciDeviceVendor !== null) { - pciDeviceVendorDesc = pciDeviceVendor.description; - } - var itemNode = $.parseHTML(wok.substitute($('#pci-tmpl').html(), { - status: pciDeviceStatus, - name: pciDeviceName, - product: pciDeviceProductDesc, - vendor: pciDeviceVendorDesc + var deviceHTml = devices.map(function(device, index) { + device.iconClass = (pciType === 'hostPCIs' ? 'fa-power-off' : (pciType === 'vmPCIs' ? 'fa-ban' : 'fa-power-off')); + device.status = (pciType === 'vmPCIs' ? 'enabled' : 'disabled'); + device.product = (device.product !== null ? device.product.description : ''); + device.vendor = (device.vendor !== null ? device.vendor.description : ''); + deviceHtml = $.parseHTML(wok.substitute($('#pci-tmpl').html(), { + status: device.status, + name: device.name, + product: device.product, + vendor: device.vendor })); - $('.body', '#form-guest-edit-pci').append(itemNode); - pciEnabled || $('button', itemNode).remove(); - $('button i', itemNode).addClass(iconClass); - if (kimchi.thisVMState === "running" && arrPCIDevices[i].vga3d) { - $('button', itemNode).prop("disabled", true); + pciEnabled || $('button', deviceHtml).remove(); + $('button > i', deviceHtml).addClass(device.iconClass); + if (kimchi.thisVMState === "running" && device.vga3d) { + $('button', deviceHtml).prop("disabled", true); } - $('button', itemNode).on('click', function(event) { - event.preventDefault(); - var obj = $(this); - var objIcon = obj.find('i'); - var id = obj.parent().parent().attr('id'); - if (objIcon.hasClass('fa-ban')) { - kimchi.removeVMPCIDevice(kimchi.selectedGuest, id, function() { - kimchi.getAvailableHostPCIDevices(function(arrPCIDevices) { - kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { - for (var k = 0; k < arrPCIDevices.length; k++) { - $('#' + arrPCIDevices[k].name + '.item').removeClass('enabled').addClass('disabled'); - $('#' + arrPCIDevices[k].name + ' .action-area button i').removeClass('fa-ban').addClass('fa-power-off'); - } - for (var k = 0; k < vmPCIs.length; k++) { - $('#' + arrPCIDevices[k].name + '.item').removeClass('disabled').addClass('enabled'); - $('#' + arrPCIDevices[k].name + ' .action-area button i').removeClass('fa-power-off').addClass('fa-ban'); - } - }); - }); - //id is for the object that is being added back to the available PCI devices - filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); - }, null); - } else { - kimchi.addVMPCIDevice(kimchi.selectedGuest, { - name: id - }, function() { - kimchi.getAvailableHostPCIDevices(function(arrPCIDevices) { - kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { - for (var k = 0; k < vmPCIs.length; k++) { - $('#' + vmPCIs[k].name + '.item').removeClass('disabled').addClass('enabled'); - $('#' + vmPCIs[k].name + ' .action-area button i').removeClass('fa-power-off').addClass('fa-ban'); - } - }); - }); - //id is for the object that is being removed from the available PCI devices - filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); - }, null); - } - }); - kimchi.getPCIDeviceCompanions(pciDeviceName, function(infoData) { + kimchi.getPCIDeviceCompanions(device.name, function(infoData) { var pciTitle = i18n['KCHVMED6007M'] + '\n'; var haveCompanions = false; for (var p = 0; p < infoData.length; p++) { @@ -552,8 +491,109 @@ kimchi.guest_edit_main = function() { haveCompanions && $('.vendor', '#' + infoData[q].parent).attr('title', pciTitle); } }); - } + device = deviceHtml[0].outerHTML; + $('.body', '#form-guest-edit-pci').append(device); + }); + }; + var getOngoingAttachingDevices = function(task) { + kimchi.trackTask(task.id, function(result) { + kimchi.getAvailableHostPCIDevices(function(arrPCIDevices) { + kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { + for (var k = 0; k < vmPCIs.length; k++) { + $('#' + vmPCIs[k].name + '.item').removeClass('disabled').addClass('enabled'); + $('#' + vmPCIs[k].name + ' .action-area button i').removeClass('fa-power-off').addClass('fa-ban'); + } + }); + }); + $('#form-guest-edit-pci > .wok-mask').fadeOut(300, function() {}); + wok.message.success(i18n['KCHVMED6010M'], '#alert-modal-container'); + filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); + }, function(result) { + if (result['message']) { + var errText = result['message']; + } else { + var errText = result['responseJSON']['reason']; + } + $('#form-guest-edit-pci > .wok-mask').fadeOut(300, function() {}); + filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); + result && wok.message.error(errText, '#alert-modal-container'); + }, function(result) { + $('#form-guest-edit-pci > .wok-mask').show(); + }); }; + var getOngoingDetachingDevices = function(task) { + kimchi.trackTask(task.id, function(result) { + kimchi.getAvailableHostPCIDevices(function(arrPCIDevices) { + kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { + for (var k = 0; k < arrPCIDevices.length; k++) { + $('#' + arrPCIDevices[k].name + '.item').removeClass('enabled').addClass('disabled'); + $('#' + arrPCIDevices[k].name + ' .action-area button i').removeClass('fa-ban').addClass('fa-power-off'); + } + for (var k = 0; k < vmPCIs.length; k++) { + $('#' + arrPCIDevices[k].name + '.item').removeClass('disabled').addClass('enabled'); + $('#' + arrPCIDevices[k].name + ' .action-area button i').removeClass('fa-power-off').addClass('fa-ban'); + } + }); + }); + $('#form-guest-edit-pci > .wok-mask').fadeOut(300, function() {}); + wok.message.success(i18n['KCHVMED6011M'], '#alert-modal-container'); + //id is for the object that is being added back to the available PCI devices + filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); + }, function(result) { + if (result['message']) { + var errText = result['message']; + } else { + var errText = result['responseJSON']['reason']; + } + $('#form-guest-edit-pci > .wok-mask').fadeOut(300, function() {}); + filterPCINodes($('select', '#form-guest-edit-pci').val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); + result && wok.message.error(errText, '#alert-modal-container'); + }, function(result) { + $('#form-guest-edit-pci > .wok-mask').show(); + }); + }; + var pciDeviceButtonHandler = function() { + $('button', '#form-guest-edit-pci').on('click', function(event) { + event.preventDefault(); + var obj = $(this); + var objIcon = obj.find('i'); + var id = obj.parent().parent().attr('id'); + if (objIcon.hasClass('fa-ban')) { + kimchi.removeVMPCIDevice(kimchi.selectedGuest, id, function(task) { + getOngoingDetachingDevices(task); + }, function(err) { + wok.message.error(err.responseJSON.reason, '#alert-modal-container'); + }); + } else { + kimchi.addVMPCIDevice(kimchi.selectedGuest, { + name: id + }, function(task) { + getOngoingAttachingDevices(task); + }, function(err) { + wok.message.error(err.responseJSON.reason, '#alert-modal-container'); + }); + } + }); + }; + + var setupPCIDevice = function() { + kimchi.getAvailableHostPCIDevices(function(hostPCIs) { + kimchi.getVMPCIDevices(kimchi.selectedGuest, function(vmPCIs) { + _generatePciDeviceHtml(hostPCIs, 'hostPCIs'); + _generatePciDeviceHtml(vmPCIs, 'vmPCIs'); + pciDeviceButtonHandler(); + $('#form-guest-edit-pci > .wok-mask').fadeOut(300, function() {}); + }); + }); + $('select', '#form-guest-edit-pci').change(function() { + filterPCINodes($(this).val(), $('input#guest-edit-pci-filter', '#form-guest-edit-pci').val()); + }); + $('select', '#form-guest-edit-pci').selectpicker(); + $('input#guest-edit-pci-filter', '#form-guest-edit-pci').on('keyup', function() { + filterPCINodes($('select', '#form-guest-edit-pci').val(), $(this).val()); + }); + }; + var setupSnapshot = function() { var currentSnapshot; diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js index 0e11aa1..605cd2d 100644 --- a/ui/js/src/kimchi.guest_main.js +++ b/ui/js/src/kimchi.guest_main.js @@ -315,7 +315,7 @@ kimchi.initClone = function() { kimchi.listVmsAuto = function() { - $('.wok-mask').removeClass('hidden'); + $('#guests-root-container > .wok-mask').removeClass('hidden'); //Check if the actions button is opened or not, //if opended stop the reload of the itens until closed var $isDropdownOpened = $('[name="guest-actions"] ul.dropdown-menu').is(":visible"); @@ -431,13 +431,13 @@ kimchi.listVmsAuto = function() { }); }); } - $('.wok-mask').fadeOut(300, function() { + $('#guests-root-container > .wok-mask').fadeOut(300, function() { }); } else { $('.grid-control').addClass('hidden'); $('#guestListField').hide(); $('#noGuests').show(); - $('.wok-mask').fadeOut(300, function() {}); + $('#guests-root-container > .wok-mask').fadeOut(300, function() {}); } } @@ -446,8 +446,8 @@ kimchi.listVmsAuto = function() { function(errorResponse, textStatus, errorThrown) { if (errorResponse.responseJSON && errorResponse.responseJSON.reason) { wok.message.error(errorResponse.responseJSON.reason); - $('.wok-mask').fadeOut(300, function() { - $('.wok-mask').addClass('hidden'); + $('#guests-root-container > .wok-mask').fadeOut(300, function() { + $('#guests-root-container > .wok-mask').addClass('hidden'); }); } kimchi.vmTimeout = window.setTimeout("kimchi.listVmsAuto();", 5000); diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl index f18d42c..a9a468e 100644 --- a/ui/pages/guest-edit.html.tmpl +++ b/ui/pages/guest-edit.html.tmpl @@ -160,6 +160,14 @@ </div> <div class="body"></div> </div> + <div class="wok-mask" role="presentation" class="hidden"> + <div class="wok-mask-loader-container"> + <div class="wok-mask-loading"> + <div class="wok-mask-loading-icon"></div> + <div class="wok-mask-loading-text">$_("Loading")...</div> + </div> + </div> + </div> </form> <form role="tabpanel" id="form-guest-edit-snapshot" class="guest-edit-snapshot tab-pane"> <div class="btn-group"> @@ -273,17 +281,7 @@ <label>{val}</label> </div> </script> -<script id="pci-tmpl" type="text/html"> -<div class="item {status}" id="{name}"> - <span class="cell status column-pci-status"> - <i class="fa fa-power-off"></i> - </span> - <span class="cell name column-pci-name" title="{name}">{name}</span> - <span class="cell product column-product" title="{product}">{product}</span> - <span class="cell vendor column-vendor" title="{vendor}">{vendor}</span> - <span class="cell column-actions action-area"><button class="btn btn-link"><i class="fa"></i></button></span> -</div> -</script> +<script id="pci-tmpl" type="text/html"><div class="item {status}" id="{name}"><span class="cell status column-pci-status"><i class="fa fa-power-off"></i></span><span class="cell name column-pci-name" title="{name}">{name}</span><span class="cell product column-product" title="{product}">{product}</span><span class="cell vendor column-vendor" title="{vendor}">{vendor}</span><span class="cell column-actions action-area"><button class="btn btn-link"><i class="fa"></i></button></span></div></script> <script id="snapshot-tmpl" type="text/html"> <div class="item" id="{name}"> <span class="cell column-sel"> diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index 4efc1ec..610debc 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -84,6 +84,8 @@ "KCHVMED6007M": "$_("Affected devices:")", "KCHVMED6008M": "$_("More")", "KCHVMED6009M": "$_("Less")", + "KCHVMED6010M": "$_("Successfully attached device to VM")", + "KCHVMED6011M": "$_("Successfully detached device from VM")", "KCHNET6001M": "$_("unavailable")", "KCHNET6002M": "$_("This action will interrupt network connectivity for any virtual machine that depend on this network.")", -- 2.7.4