Change in vdsm[master]: v2v: get VM information from OVA file

shavivi at redhat.com shavivi at redhat.com
Tue Jul 7 11:15:03 UTC 2015


Shahar Havivi has uploaded a new change for review.

Change subject: v2v: get VM information from OVA file
......................................................................

v2v: get VM information from OVA file

In order to import a VM that exists in an OVA file the oVirt engine
needs to get information regarding the VM, such as disks sizes,
interfaces memory etc.
Adding a new verb: getOvfInfo

Change-Id: I3c55c846f837bb5bf363717e05daabf5ee6631ca
Signed-off-by: Shahar Havivi <shaharh at redhat.com>
---
M vdsm/API.py
M vdsm/rpc/Bridge.py
M vdsm/rpc/bindingxmlrpc.py
M vdsm/rpc/vdsmapi-schema.json
M vdsm/v2v.py
5 files changed, 97 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/71/43271/1

diff --git a/vdsm/API.py b/vdsm/API.py
index eafceb7..645b962 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1418,6 +1418,13 @@
         """
         return v2v.get_external_vms(uri, username, password)
 
+    def getOvaInfo(self, ova_path):
+        """
+        return a dictionary, information regading a VM that is a part
+        of the ova
+        """
+        return v2v.get_ova_info(ova_path)
+
     def convertExternalVm(self, uri, username, password, vminfo, jobid):
         return v2v.convert_external_vm(uri, username, password, vminfo, jobid,
                                        self._cif.irs)
diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py
index 4302baa..99396c1 100644
--- a/vdsm/rpc/Bridge.py
+++ b/vdsm/rpc/Bridge.py
@@ -410,6 +410,7 @@
     'Host_getDeviceList': {'ret': 'devList'},
     'Host_getDevicesVisibility': {'ret': 'visible'},
     'Host_getExternalVMs': {'ret': 'vmList'},
+    'Host_getOvaInfo': {'ret': 'vm'},
     'Host_getConvertedVm': {'ret': 'ovf'},
     'Host_getHardwareInfo': {'ret': 'info'},
     'Host_getLVMVolumeGroups': {'ret': 'vglist'},
diff --git a/vdsm/rpc/bindingxmlrpc.py b/vdsm/rpc/bindingxmlrpc.py
index 05110c4..c3d4022 100644
--- a/vdsm/rpc/bindingxmlrpc.py
+++ b/vdsm/rpc/bindingxmlrpc.py
@@ -372,6 +372,10 @@
         api = API.Global()
         return api.getExternalVMs(uri, username, password)
 
+    def getOvaInfo(self, ova_path):
+        api = API.Global()
+        return api.getOvaInfo(ova_path)
+
     def convertExternalVm(self, uri, username, password, vminfo, jobid):
         password = ProtectedPassword(password)
         api = API.Global()
@@ -1093,6 +1097,7 @@
                 (self.vmSetCpuTuneQuota, 'vmSetCpuTuneQuota'),
                 (self.vmSetCpuTunePeriod, 'vmSetCpuTunePeriod'),
                 (self.getExternalVMs, 'getExternalVMs'),
+                (self.getOvaInfo, 'getOvaInfo'),
                 (self.convertExternalVm, 'convertExternalVm'),
                 (self.getConvertedVm, 'getConvertedVm'),
                 (self.abortV2VJob, 'abortV2VJob'),
diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json
index 7c4fe1c..08b85d7 100644
--- a/vdsm/rpc/vdsmapi-schema.json
+++ b/vdsm/rpc/vdsmapi-schema.json
@@ -3930,6 +3930,24 @@
   'data': {'uri': 'str', 'username': 'str', 'password': 'str'},
   'returns': ['ExternalVmInfo']}
 
+
+##
+# @Host.getOvaInfo:
+#
+# Get VM information (disks, interfaces, memory etc) from OVA file
+#
+# @ova_path: path to the ova file
+#
+# Returns:
+# A dictionary with information regarding the VM
+#
+# Since: 4.17.0
+##
+{'command': {'class': 'Host', 'name': 'getOvaInfo'},
+  'data': {'ova_path': 'str'},
+  'returns': 'ExternalVmInfo'}
+
+
 ##
 # @Host.convertExternalVm:
 #
diff --git a/vdsm/v2v.py b/vdsm/v2v.py
index 18cc9bc..e891894 100644
--- a/vdsm/v2v.py
+++ b/vdsm/v2v.py
@@ -50,6 +50,10 @@
 _V2V_DIR = os.path.join(P_VDSM_RUN, 'v2v')
 _VIRT_V2V = CommandPath('virt-v2v', '/usr/bin/virt-v2v')
 
+_OVF_NS = 'http://schemas.dmtf.org/ovf/envelope/1'
+_RASD_NS = 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' \
+           'CIM_ResourceAllocationSettingData'
+
 ImportProgress = namedtuple('ImportProgress',
                             ['current_disk', 'disk_count', 'description'])
 DiskProgress = namedtuple('DiskProgress', ['progress'])
@@ -161,6 +165,22 @@
     job.start()
     _add_job(job_id, job)
     return {'status': doneCode}
+
+
+def get_ova_info(ova_path):
+    ns = {'ovf': _OVF_NS, 'rasd': _RASD_NS}
+
+    try:
+        root = ET.fromstring(_read_ovf_from_ova(ova_path))
+    except ET.ParseError as e:
+        raise V2VError('Error reading ovf from ova, position: %r' % e.position)
+
+    vm = {}
+    _add_general_ovf_info(vm, root, ns)
+    _add_disks_ovf_info(vm, root, ns)
+    _add_networks_ovf_info(vm, root, ns)
+
+    return {'status': doneCode, 'vm': vm}
 
 
 def get_converted_vm(job_id):
@@ -651,3 +671,49 @@
         if model is not None:
             i['model'] = model.get('type')
         params['networks'].append(i)
+
+
+def _read_ovf_from_ova(ova_path):
+    cmd = ['/usr/bin/tar', 'xf', ova_path, '*.ovf', '--to-stdout']
+    rc, output, error = execCmd(cmd)
+    if rc:
+        raise V2VError(error)
+
+    return output
+
+
+def _add_general_ovf_info(vm, node, ns):
+    try:
+        vm['status'] = 'Down'
+        vm['vmName'] = node.find('./ovf:VirtualSystem/ovf:Name', ns).text
+        vm['memSize'] = node.find('.//ovf:Item[rasd:ResourceType="4"]/'
+                                  'rasd:VirtualQuantity', ns).text
+        vm['smp'] = node.find('.//ovf:Item[rasd:ResourceType="3"]/'
+                              'rasd:VirtualQuantity', ns).text
+    except Exception as e:
+        raise V2VError('Error parsing ovf information: %s' % e.message)
+
+
+def _add_disks_ovf_info(vm, node, ns):
+    try:
+        vm['disks'] = []
+        for d in node.findall(".//ovf:DiskSection/ovf:Disk", ns):
+            disk = {}
+            disk['capacity'] = str(d.attrib.get('{%s}capacity' % _OVF_NS))
+            disk['allocation'] = str(d.attrib.get('{%s}populatedSize'
+                                     % _OVF_NS))
+            vm['disks'].append(disk)
+    except Exception as e:
+        raise V2VError('Error parsing ovf disk information: %s' % e.message)
+
+
+def _add_networks_ovf_info(vm, node, ns):
+    try:
+        vm['networks'] = []
+        for n in node.findall('.//ovf:Item[rasd:ResourceType="10"]', ns):
+            net = {}
+            net['dev'] = net.find('./rasd:ElementName', ns).text
+            net['model'] = net.find('./rasd:ResourceSubType', ns).text
+            vm['networks'].append(net)
+    except Exception as e:
+        raise V2VError('Error parsing ovf network information: %s' % e.message)


-- 
To view, visit https://gerrit.ovirt.org/43271
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3c55c846f837bb5bf363717e05daabf5ee6631ca
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Shahar Havivi <shavivi at redhat.com>


More information about the vdsm-patches mailing list