[Kimchi-devel] [PATCH v2] [Kimchi] Issue #956: Unable to assign pci passthrough devices through kimchi
joserz at linux.vnet.ibm.com
joserz at linux.vnet.ibm.com
Fri Jul 22 19:40:01 UTC 2016
Hello Samuel,
I found something that can help, please read my comments below
Thank you
On Thu, Jul 21, 2016 at 05:49:35PM -0300, sguimaraes943 at gmail.com wrote:
> From: Samuel Guimarães <sguimaraes943 at gmail.com>
>
> This commit fixes an issue with PCI passthrough devices through Kimchi.
> It also addresses an enhancement to display success messages when some actions doesn't require the Save button and there's no UI feedback to the user (Issue #975).
>
> Signed-off-by: Samuel Guimarães <sguimaraes943 at gmail.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 | 236 +++++++++++++++++++++++------------
> ui/js/src/kimchi.guest_main.js | 10 +-
> ui/pages/guest-edit.html.tmpl | 20 ++-
> ui/pages/i18n.json.tmpl | 2 +
> 7 files changed, 180 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..d1d6335 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,9 +491,142 @@ kimchi.guest_edit_main = function() {
> haveCompanions && $('.vendor', '#' + infoData[q].parent).attr('title', pciTitle);
> }
> });
> - }
> + device = deviceHtml[0].outerHTML;
> + $('.body', '#form-guest-edit-pci').append(device);
> + });
> + };
You can receive the task as parameter here
like 'var getOngoingAttachingDevices = function(task) {
> + var getOngoingAttachingDevices = function() {
> + var result = {};
> + var devices = 'status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/vms/' + kimchi.selectedGuest + '/hostdevs');
> + kimchi.getTasksByFilter(devices, function(tasks) {
> + for (var i = 0; i < tasks.length; i++) {
> + if (tasks[i].message === 'Attaching PCI device') {
> + var selectedVm = tasks[i].target_uri.split('/');
> + selectedVm = selectedVm[4];
> + result[selectedVm] = tasks[i];
> +
> + if (kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
> + continue;
> + }
> +
I think this code above can be removed since we can get the task id from
the function argument. Suppose we call the argument 'task', we can
simply pass task.id
> + kimchi.trackTask(tasks[i].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();
> + });
> + }
> + }
> + }, null, true);
> + };
> + var getOngoingDetachingDevices = function() {
the same
> + var result = {};
> + var devices = 'status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/vms/' + kimchi.selectedGuest + '/hostdevs');
> + kimchi.getTasksByFilter(devices, function(tasks) {
> + for (var i = 0; i < tasks.length; i++) {
> + if (tasks[i].message === 'Detaching device') {
> + var selectedVm = tasks[i].target_uri.split('/');
> + selectedVm = selectedVm[4];
> + result[selectedVm] = tasks[i];
> +
> + if (kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
> + continue;
> + }
> +
> + kimchi.trackTask(tasks[i].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();
> + });
> + }
> + }
> + }, null, true);
> + };
> + 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() {
Here you can pass the task returned by remove device, like
kimchi.removeVMPCIDevice(kimchi.selectedGuest, id, function(task) {
getOngoingDetachingDevices(task);
> + getOngoingDetachingDevices();
> + }, function(err) {
> + wok.message.error(err.responseJSON.reason, '#alert-modal-container');
> + });
> + } else {
> + kimchi.addVMPCIDevice(kimchi.selectedGuest, {
> + name: id
> + }, function() {
like I said above:
}, function(task) {
getOngoingAttachingDevices(task);
}
> + getOngoingAttachingDevices();
> + }, 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;
> var setCurrentSnapshot = function(aSnapshot) {
> 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.")",
> --
> 1.9.3
>
> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
More information about the Kimchi-devel
mailing list