[PATCH v8 0/3] Backend support for templates with sockets, cores, and threads
by Christy Perez
v7->v8
- Add mockmodel tests for POST, PUT and GET
- Move model test into existing function to work around bug
(being worked by Zhou)
v6->v7
- Add unit tests
- Rebase
v5->v6:
- Change cpu_info to empty dict instead of empty string if not specified
- Split translations into different commit
v4->v5:
- Fix format issues
- Remove if check for cpu_info in control, and set cpu_info
to the empty string in model if None
- Add format requirements error for topology requirements.
- Add new error to toplogy in API.json
- Update po files
v3->v4:
- Remove the unused cpu_ elements from common_spec
- Pass new_t into validate function to reduce complexity
- Rearrange code to decrese indents in _get_cpu_xml
v2->v3:
- Set vcpus based on topology, if specified.
- Move the update cpu+topology validation out to a function
for redability
- Add a minimum value of 1 for topology values
- Leave new English error msg as empty string
- Update the API documentation on cpu defaults
v1->v2:
- Added a check to make sure that vcpus = sockets*cores*threads
- Set individual topoology params to required in API.json
- Change the topology object types from string to integer
- Always return cpu_info from templates lookup()
- Removed check for cpu_info in to_vm_xml
- Build cpu_info xml using lxml.builder instead of string
- CPU and topology verification on template update
Christy Perez (3):
Backend support for templates with sockets, cores, and threads
cpu_info tests for model and mockmodel
Translations for new cpu_info messages
docs/API.md | 13 ++++++-
po/de_DE.po | 76 +++++++++++++++++++++++++++++++++++----
po/en_US.po | 76 +++++++++++++++++++++++++++++++++++----
po/es_ES.po | 76 +++++++++++++++++++++++++++++++++++----
po/fr_FR.po | 76 +++++++++++++++++++++++++++++++++++----
po/it_IT.po | 76 +++++++++++++++++++++++++++++++++++----
po/ja_JP.po | 76 +++++++++++++++++++++++++++++++++++----
po/kimchi.pot | 76 +++++++++++++++++++++++++++++++++++----
po/ko_KR.po | 76 +++++++++++++++++++++++++++++++++++----
po/pt_BR.po | 75 ++++++++++++++++++++++++++++++++++----
po/ru_RU.po | 76 +++++++++++++++++++++++++++++++++++----
po/zh_CN.po | 79 +++++++++++++++++++++++++++++++++++------
po/zh_TW.po | 76 +++++++++++++++++++++++++++++++++++----
src/kimchi/API.json | 36 +++++++++++++++++--
src/kimchi/control/templates.py | 31 ++++++++--------
src/kimchi/i18n.py | 2 ++
src/kimchi/mockmodel.py | 3 ++
src/kimchi/model/templates.py | 32 +++++++++++++++++
src/kimchi/osinfo.py | 5 ++-
src/kimchi/vmtemplate.py | 15 ++++++++
tests/test_mockmodel.py | 24 +++++++++++++
tests/test_model.py | 13 +++++++
22 files changed, 980 insertions(+), 108 deletions(-)
--
1.9.3
9 years, 10 months
[PATCH] Update libvirtstoragepool.py to use lxml.builder
by Aline Manera
Instead of using plan XML text, we should use lxml.builder to avoid any
issue while generating the XML.
Signed-off-by: Aline Manera <alinefm(a)linux.vnet.ibm.com>
---
src/kimchi/model/libvirtstoragepool.py | 177 +++++++++++++--------------------
tests/test_storagepool.py | 16 ++-
2 files changed, 77 insertions(+), 116 deletions(-)
diff --git a/src/kimchi/model/libvirtstoragepool.py b/src/kimchi/model/libvirtstoragepool.py
index d7b49e2..c6deafc 100644
--- a/src/kimchi/model/libvirtstoragepool.py
+++ b/src/kimchi/model/libvirtstoragepool.py
@@ -17,9 +17,10 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import copy
import os
import tempfile
+import lxml.etree as ET
+from lxml.builder import E
import libvirt
@@ -65,15 +66,10 @@ class DirPoolDef(StoragePoolDef):
# name:
# type:
# path:
- xml = u"""
- <pool type='dir'>
- <name>{name}</name>
- <target>
- <path>{path}</path>
- </target>
- </pool>
- """.format(**self.poolArgs)
- return xml
+ pool = E.pool(type='dir')
+ pool.append(E.name(self.poolArgs['name']))
+ pool.append(E.target(E.path(self.poolArgs['path'])))
+ return ET.tostring(pool, encoding='unicode', pretty_print=True)
class NetfsPoolDef(StoragePoolDef):
@@ -120,21 +116,16 @@ class NetfsPoolDef(StoragePoolDef):
# type:
# source[host]:
# source[path]:
- poolArgs = copy.deepcopy(self.poolArgs)
- poolArgs['path'] = self.path
- xml = u"""
- <pool type='netfs'>
- <name>{name}</name>
- <source>
- <host name='{source[host]}'/>
- <dir path='{source[path]}'/>
- </source>
- <target>
- <path>{path}</path>
- </target>
- </pool>
- """.format(**poolArgs)
- return xml
+ pool = E.pool(type='netfs')
+ pool.append(E.name(self.poolArgs['name']))
+
+ source = E.source()
+ source.append(E.host(name=self.poolArgs['source']['host']))
+ source.append(E.dir(path=self.poolArgs['source']['path']))
+
+ pool.append(source)
+ pool.append(E.target(E.path(self.path)))
+ return ET.tostring(pool, encoding='unicode', pretty_print=True)
class LogicalPoolDef(StoragePoolDef):
@@ -150,26 +141,16 @@ class LogicalPoolDef(StoragePoolDef):
# name:
# type:
# source[devices]:
- poolArgs = copy.deepcopy(self.poolArgs)
- devices = []
- for device_path in poolArgs['source']['devices']:
- devices.append('<device path="%s" />' % device_path)
-
- poolArgs['source']['devices'] = ''.join(devices)
- poolArgs['path'] = self.path
-
- xml = u"""
- <pool type='logical'>
- <name>{name}</name>
- <source>
- {source[devices]}
- </source>
- <target>
- <path>{path}</path>
- </target>
- </pool>
- """.format(**poolArgs)
- return xml
+ pool = E.pool(type='logical')
+ pool.append(E.name(self.poolArgs['name']))
+
+ source = E.source()
+ for device_path in self.poolArgs['source']['devices']:
+ source.append(E.device(path=device_path))
+
+ pool.append(source)
+ pool.append(E.target(E.path(self.path)))
+ return ET.tostring(pool, encoding='unicode', pretty_print=True)
class ScsiPoolDef(StoragePoolDef):
@@ -199,22 +180,17 @@ class ScsiPoolDef(StoragePoolDef):
# source[adapter][wwnn]:
# source[adapter][wwpn]:
# path:
+ pool = E.pool(type='scsi')
+ pool.append(E.name(self.poolArgs['name']))
+
+ adapter = E.adapter(type=self.poolArgs['source']['adapter']['type'])
+ adapter.set('name', self.poolArgs['source']['name'])
+ adapter.set('wwnn', self.poolArgs['source']['adapter']['wwnn'])
+ adapter.set('wwpn', self.poolArgs['source']['adapter']['wwpn'])
- xml = """
- <pool type='scsi'>
- <name>{name}</name>
- <source>
- <adapter type='{source[adapter][type]}'\
- name='{source[name]}'\
- wwnn='{source[adapter][wwnn]}'\
- wwpn='{source[adapter][wwpn]}'/>
- </source>
- <target>
- <path>{path}</path>
- </target>
- </pool>
- """.format(**self.poolArgs)
- return xml
+ pool.append(E.source(adapter))
+ pool.append(E.target(E.path(self.poolArgs['path'])))
+ return ET.tostring(pool, encoding='unicode', pretty_print=True)
class IscsiPoolDef(StoragePoolDef):
@@ -237,36 +213,19 @@ class IscsiPoolDef(StoragePoolDef):
virSecret = conn.secretLookupByUsage(
libvirt.VIR_SECRET_USAGE_TYPE_ISCSI, self.poolArgs['name'])
except libvirt.libvirtError:
- xml = '''
- <secret ephemeral='no' private='yes'>
- <description>Secret for iSCSI storage pool {name}</description>
- <auth type='chap' username='{username}'/>
- <usage type='iscsi'>
- <target>{name}</target>
- </usage>
- </secret>'''.format(name=self.poolArgs['name'],
- username=auth['username'])
- virSecret = conn.secretDefineXML(xml)
+ secret = E.secret(ephemeral='no', private='yes')
- virSecret.setValue(auth['password'])
-
- def _format_port(self, poolArgs):
- try:
- port = poolArgs['source']['port']
- except KeyError:
- return ""
- return "port='%s'" % port
+ description = E.description('Secret for iSCSI storage pool %s' %
+ self.poolArgs['name'])
+ secret.append(description)
+ secret.append(E.auth(type='chap', username=auth['username']))
- def _format_auth(self, poolArgs):
- try:
- auth = poolArgs['source']['auth']
- except KeyError:
- return ""
+ usage = E.usage(type='iscsi')
+ usage.append(E.target(self.poolArgs['name']))
+ secret.append(usage)
+ virSecret = conn.secretDefineXML(ET.tostring(secret))
- return '''
- <auth type='chap' username='{username}'>
- <secret type='iscsi' usage='{name}'/>
- </auth>'''.format(name=poolArgs['name'], username=auth['username'])
+ virSecret.setValue(auth['password'])
@property
def xml(self):
@@ -278,22 +237,28 @@ class IscsiPoolDef(StoragePoolDef):
#
# Optional parameters
# source[port]:
- poolArgs = copy.deepcopy(self.poolArgs)
- poolArgs['source'].update({'port': self._format_port(poolArgs),
- 'auth': self._format_auth(poolArgs)})
- poolArgs['path'] = '/dev/disk/by-id'
-
- xml = u"""
- <pool type='iscsi'>
- <name>{name}</name>
- <source>
- <host name='{source[host]}' {source[port]}/>
- <device path='{source[target]}'/>
- {source[auth]}
- </source>
- <target>
- <path>{path}</path>
- </target>
- </pool>
- """.format(**poolArgs)
- return xml
+ pool = E.pool(type='iscsi')
+ pool.append(E.name(self.poolArgs['name']))
+
+ host = E.host(name=self.poolArgs['source']['host'])
+ port = self.poolArgs['source'].get('port')
+ if port is not None:
+ host.set('port', str(port))
+
+ source = E.source(host)
+ source.append(E.device(path=self.poolArgs['source']['target']))
+
+ source_auth = self.poolArgs['source'].get('auth')
+ if source_auth is not None:
+ auth = E.auth(type='chap')
+ auth.set('username', source_auth['username'])
+
+ secret = E.secret(type='iscsi')
+ secret.set('usage', self.poolArgs['name'])
+ auth.append(secret)
+
+ source.append(auth)
+
+ pool.append(source)
+ pool.append(E.target(E.path('/dev/disk/by-id')))
+ return ET.tostring(pool, encoding='unicode', pretty_print=True)
diff --git a/tests/test_storagepool.py b/tests/test_storagepool.py
index 3fbeed0..ee30e9a 100644
--- a/tests/test_storagepool.py
+++ b/tests/test_storagepool.py
@@ -17,12 +17,11 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import libxml2
+import lxml.etree as ET
import unittest
from kimchi.model.libvirtstoragepool import StoragePoolDef
-from kimchi.rollbackcontext import RollbackContext
class storagepoolTests(unittest.TestCase):
@@ -166,11 +165,8 @@ class storagepoolTests(unittest.TestCase):
for poolDef in poolDefs:
defObj = StoragePoolDef.create(poolDef['def'])
xmlStr = defObj.xml
- with RollbackContext() as rollback:
- t1 = libxml2.readDoc(xmlStr, URL='', encoding='UTF-8',
- options=libxml2.XML_PARSE_NOBLANKS)
- rollback.prependDefer(t1.freeDoc)
- t2 = libxml2.readDoc(poolDef['xml'], URL='', encoding='UTF-8',
- options=libxml2.XML_PARSE_NOBLANKS)
- rollback.prependDefer(t2.freeDoc)
- self.assertEquals(t1.serialize(), t2.serialize())
+
+ parser = ET.XMLParser(remove_blank_text=True)
+ t1 = ET.fromstring(xmlStr, parser)
+ t2 = ET.fromstring(poolDef['xml'], parser)
+ self.assertEquals(ET.tostring(t1), ET.tostring(t2))
--
1.9.3
9 years, 10 months
[PATCH 0/3] Backend support for templates with sockets, cores, and threads
by Christy Perez
v7->v8
- Add mockmodel tests for POST, PUT and GET
- Move model test into existing function to work around bug
(being worked by Zhou)
v6->v7
- Add unit tests
- Rebase
v5->v6:
- Change cpu_info to empty dict instead of empty string if not specified
- Split translations into different commit
v4->v5:
- Fix format issues
- Remove if check for cpu_info in control, and set cpu_info
to the empty string in model if None
- Add format requirements error for topology requirements.
- Add new error to toplogy in API.json
- Update po files
v3->v4:
- Remove the unused cpu_ elements from common_spec
- Pass new_t into validate function to reduce complexity
- Rearrange code to decrese indents in _get_cpu_xml
v2->v3:
- Set vcpus based on topology, if specified.
- Move the update cpu+topology validation out to a function
for redability
- Add a minimum value of 1 for topology values
- Leave new English error msg as empty string
- Update the API documentation on cpu defaults
v1->v2:
- Added a check to make sure that vcpus = sockets*cores*threads
- Set individual topoology params to required in API.json
- Change the topology object types from string to integer
- Always return cpu_info from templates lookup()
- Removed check for cpu_info in to_vm_xml
- Build cpu_info xml using lxml.builder instead of string
- CPU and topology verification on template update
Christy Perez (3):
Backend support for templates with sockets, cores, and threads
cpu_info tests for model and mockmodel
Translations for new cpu_info messages
docs/API.md | 13 ++++++-
po/de_DE.po | 76 +++++++++++++++++++++++++++++++++++----
po/en_US.po | 76 +++++++++++++++++++++++++++++++++++----
po/es_ES.po | 76 +++++++++++++++++++++++++++++++++++----
po/fr_FR.po | 76 +++++++++++++++++++++++++++++++++++----
po/it_IT.po | 76 +++++++++++++++++++++++++++++++++++----
po/ja_JP.po | 76 +++++++++++++++++++++++++++++++++++----
po/kimchi.pot | 76 +++++++++++++++++++++++++++++++++++----
po/ko_KR.po | 76 +++++++++++++++++++++++++++++++++++----
po/pt_BR.po | 75 ++++++++++++++++++++++++++++++++++----
po/ru_RU.po | 76 +++++++++++++++++++++++++++++++++++----
po/zh_CN.po | 79 +++++++++++++++++++++++++++++++++++------
po/zh_TW.po | 76 +++++++++++++++++++++++++++++++++++----
src/kimchi/API.json | 36 +++++++++++++++++--
src/kimchi/control/templates.py | 31 ++++++++--------
src/kimchi/i18n.py | 2 ++
src/kimchi/mockmodel.py | 3 ++
src/kimchi/model/templates.py | 32 +++++++++++++++++
src/kimchi/osinfo.py | 5 ++-
src/kimchi/vmtemplate.py | 15 ++++++++
tests/test_mockmodel.py | 24 +++++++++++++
tests/test_model.py | 13 +++++++
22 files changed, 980 insertions(+), 108 deletions(-)
--
1.9.3
9 years, 10 months
Re: [Kimchi-devel] [PATCH 3/5] AsyncTask: Improve continuous status feedback
by Crístian Viana
On 28-10-2014 04:48, Zhou Zheng Sheng wrote:
> - inst.storagevolumes_create(pool, params)
> + task_id = inst.storagevolumes_create(pool, params)['id']
> rollback.prependDefer(inst.storagevolume_delete, pool, vol)
> + self._wait_task(inst, task_id)
I think you should add the delete call to the rollback session only
after the task has finished (i.e. after waiting for it). What if the
task raises an exception and the storage volume isn't created? The
rollback session will try to delete it but it won't exist.
9 years, 10 months
Re: [Kimchi-devel] [PATCH 4/5] ModelTests: Improve leftover cleaning
by Crístian Viana
As I wrote on the patch 3/5, I think you should only add the deletion
rollback calls after you're sure the resource has been created (i.e.
after waiting for its task to finish).
On 28-10-2014 04:48, Zhou Zheng Sheng wrote:
> In ModelTests we use RollbackContext to register undo actions for
> cleaning leftovers. The general principle for using RollbackContext is
> that we should register an undo action right after the successful
> allocation of a resource, otherwise we leave a window between the
> resource allocation and cleanup action registration. If it happened to
> raise an exception in this window, the allocated resource is not
> cleaned.
>
> In ModelTests, you can find that some test methods is not properly using
> RollbackContext, they place assertions between resource allocation and
> cleanup registration. This patch tries to adjust the order peroperly.
9 years, 10 months
[PATCH V2] Enhancement: PCI Device information enhancement
by Wen Wang
From: Wen Wang <wenwang(a)linux.vnet.ibm.com>
V1 -> V2:
1) Changed the API name to "getPCIDeviceCompanion".
2) Changed for a more specific way of detecting the related devices.
3) Added the "Affected devices" to the tip with aligned format.
4) tip will when the pointer hang over any section of the affected line.
This patch provide the way that shows more specific PCI device
information by hanging the mouse on top of device name.
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.api.js | 14 ++++++++++++++
ui/js/src/kimchi.guest_edit_main.js | 25 +++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 8a6e416..ebf826b 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -1129,6 +1129,20 @@ var kimchi = {
});
},
+ getPCIDeviceCompanions : function(pcidev, suc, err) {
+ kimchi.requestJSON({
+ url : kimchi.url + 'host/devices?_passthrough_affected_by=' + pcidev,
+ 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) : '';
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 030e112..2a9c1ab 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -407,6 +407,31 @@ kimchi.guest_edit_main = function() {
});
}
});
+ kimchi.getPCIDeviceCompanions(hostPCIs[i].name, function(infoData) {
+ var pciTitle = "";
+ if(infoData.length>0) {
+ for(var p=0; p<infoData.length; p++) {
+ if(infoData[p].device_type === "net") {
+ pciTitle += "Affected devices:\n";
+ pciTitle += infoData[p].name + "\n";
+ pciTitle += " " + "interface: " + infoData[p].interface;
+ pciTitle += ", address: " + infoData[p].address;
+ pciTitle += ", link_type: " + infoData[p].link_type + "\n";
+ } else if(infoData[p].device_type === "storage") {
+ pciTitle += "Affected devices:\n";
+ pciTitle += infoData[p].name + "\n";
+ pciTitle += " " + "block: " + infoData[p].block;
+ pciTitle += ", drive_type: " + infoData[p].drive_type;
+ pciTitle += ", model: " + infoData[p].model + "\n";
+ }
+ }
+ for(var q=0; q<infoData.length; q++) {
+ pciTitle === "" || $(".name", "#" + infoData[q].parent).attr("title", pciTitle);
+ pciTitle === "" || $(".product", "#" + infoData[q].parent).attr("title", pciTitle);
+ pciTitle === "" || $(".vendor", "#" + infoData[q].parent).attr("title", pciTitle);
+ }
+ }
+ });
}
});
});
--
1.7.1
9 years, 10 months
[PATCH V2] Guest disk hot plug UI
by Wen Wang
From: Wen Wang <wenwang(a)linux.vnet.ibm.com>
V1 -> V2:
Enable CDROM hot plug including detaching.
Enable users add and detach disk when vm is running.
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.guest_edit_main.js | 29 +++++++++++------------------
1 files changed, 11 insertions(+), 18 deletions(-)
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 030e112..82aeeb6 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -57,17 +57,12 @@ kimchi.guest_edit_main = function() {
text: false
});
- if(kimchi.thisVMState != "running") {
- $('.detach', container).button({
- icons: {
- primary: 'ui-icon-trash'
- },
- text: false
- });
-
- } else {
- $('.detach', container).remove();
- }
+ $('.detach', container).button({
+ icons: {
+ primary: 'ui-icon-trash'
+ },
+ text: false
+ });
$('.save', container).button({
icons: {
@@ -443,14 +438,8 @@ kimchi.guest_edit_main = function() {
guest['icon'] = guest['icon'] || 'images/icon-vm.png';
$('#form-guest-edit-general').fillWithObject(guest);
kimchi.thisVMState = guest['state'];
-
refreshCDROMs();
- if(kimchi.thisVMState === "running") {
- $("#form-guest-edit-general input").prop("disabled", "disabled");
- $("#guest-edit-attach-cdrom-button").remove();
- $("#form-guest-edit-interface .header button").remove();
- } else {
- $('#guest-edit-attach-cdrom-button').button({
+ $('#guest-edit-attach-cdrom-button').button({
icons: {
primary: "ui-icon-plusthick"
},
@@ -459,6 +448,10 @@ kimchi.guest_edit_main = function() {
event.preventDefault();
kimchi.window.open("guest-storage-add.html");
});
+ if(kimchi.thisVMState === "running") {
+ $("#form-guest-edit-general input").prop("disabled", "disabled");
+ $("#form-guest-edit-interface .header button").remove();
+ } else {
$("#action-button-container").removeClass("hidden");
}
--
1.7.1
9 years, 10 months
[PATCH 0/8] Create a common function to generate guest disk XML
by Aline Manera
This patch set moves common functions related to guest disk XML to
xmlutils/disk.py. That way model/vmstorages.py and vmtemplate.py can make use
of it and we make sure the logic is the same in both cases.
It is the first step and only changes the way vmtemplate.py generated the guest
CDROM XML. But in the next patches all the guest disk generation on vmtemplate.py
will do the same (I prefered to do in parts to avoid huge patch sets)
Aline Manera (8):
Move _get_storage_xml() to xmlutils/disk.py
Move vmdisks.py functions to xmlutils/disk.py
Remove 'bus' paramater from /vms/<name>/storages documentation
Update get_disk_xml() to get the device same according to bus and
index values
Remove ignore_src parameter from get_disk_xml()
Get disk type according to file path on get_disk_xml()
Check QEMU stream DNS capability while generating guest disk XML
Update vmtemplate.py to use get_disk_xml() while generating CDROM XML
docs/API.md | 1 -
src/kimchi/model/storagevolumes.py | 8 +-
src/kimchi/model/vms.py | 1 -
src/kimchi/model/vmstorages.py | 140 ++++++++-----------------------
src/kimchi/vmdisks.py | 75 -----------------
src/kimchi/vmtemplate.py | 78 +++++-------------
src/kimchi/xmlutils/disk.py | 163 +++++++++++++++++++++++++++++++++++++
tests/test_model.py | 11 ++-
8 files changed, 233 insertions(+), 244 deletions(-)
delete mode 100644 src/kimchi/vmdisks.py
create mode 100644 src/kimchi/xmlutils/disk.py
--
1.9.3
9 years, 10 months
[PATCH] Enhancement: PCI Device information enhancement
by Wen Wang
From: Wen Wang <wenwang(a)linux.vnet.ibm.com>
This patch provide the way that shows more specific PCI device
information by hanging the mouse on top of device name.
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.api.js | 14 ++++++++++++++
ui/js/src/kimchi.guest_edit_main.js | 25 +++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 8a6e416..aebac56 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -1129,6 +1129,20 @@ var kimchi = {
});
},
+ getPCIDeviceDescriptions : function(pcidev, suc, err) {
+ kimchi.requestJSON({
+ url : kimchi.url + 'host/devices?_passthrough_affected_by=' + pcidev,
+ 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) : '';
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 030e112..580f648 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -365,6 +365,9 @@ kimchi.guest_edit_main = function() {
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,
@@ -407,6 +410,28 @@ kimchi.guest_edit_main = function() {
});
}
});
+ kimchi.getPCIDeviceDescriptions(hostPCIs[i].name, function(infoData) {
+ var pciTitle = "";
+ if(infoData.length>0) {
+ for(var p=0; p<infoData.length; p++) {
+ if(infoData[p].interface) {
+ pciTitle += "interface: " + infoData[p].interface;
+ pciTitle += ", address: " + infoData[p].address;
+ pciTitle += ", link_type: " + infoData[p].link_type;
+ pciTitle += " ";
+ } else if(infoData[p].block) {
+ pciTitle += "block: " + infoData[p].block;
+ pciTitle += ", drive_type: " + infoData[p].drive_type;
+ pciTitle += ", model: " + infoData[p].model;
+ pciTitle += " ";
+ }
+
+ }
+ for(var q=0; q<infoData.length; q++) {
+ pciTitle === "" || $(".name", "#" + infoData[q].parent).attr("title", pciTitle);
+ }
+ }
+ });
}
});
});
--
1.7.1
9 years, 10 months