Signed-off-by: Agata Murawska <[email protected]>
---
lib/ovf.py | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 161 insertions(+), 0 deletions(-)
diff --git a/lib/ovf.py b/lib/ovf.py
index d413ede..254298c 100644
--- a/lib/ovf.py
+++ b/lib/ovf.py
@@ -1168,8 +1168,18 @@ class OVFExporter(Converter):
@ivar output_path: complete path to .ovf file
@type config_parser: L{ConfigParserWithDefaults}
@ivar config_parser: parser for the config.ini file
+ @type results_disk: list
+ @ivar results_disk: list of dictionaries of disk options from config.ini
+ @type results_network: list
+ @ivar results_network: list of dictionaries of network options form
config.ini
@type results_name: string
@ivar results_name: name of the instance
+ @type results_vcpus: string
+ @ivar results_vcpus: number of VCPUs
+ @type results_memory: string
+ @ivar results_memory: RAM memory in MB
+ @type results_ganeti: dict
+ @ivar results_ganeti: dictionary of Ganeti-specific options from config.ini
"""
def _ReadInputData(self, input_path):
@@ -1219,6 +1229,150 @@ class OVFExporter(Converter):
raise errors.OpPrereqError("No instance name found")
return name
+ def _ParseVCPUs(self):
+ """Parses vcpus number from config file.
+
+ @rtype: int
+ @return: number of virtual CPUs
+
+ @raises errors.OpPrereqError: if number of VCPUs equals 0
+
+ """
+ vcpus = self.config_parser.getint(constants.INISECT_BEP, "vcpus")
+ if vcpus == 0:
+ raise errors.OpPrereqError("No CPU information found")
+ return vcpus
+
+ def _ParseMemory(self):
+ """Parses vcpus number from config file.
+
+ @rtype: int
+ @return: amount of memory in MB
+
+ @raises errors.OpPrereqError: if amount of memory equals 0
+
+ """
+ memory = self.config_parser.getint(constants.INISECT_BEP, "memory")
+ if memory == 0:
+ raise errors.OpPrereqError("No memory information found")
+ return memory
+
+ def _ParseGaneti(self):
+ """Parses Ganeti data from config file.
+
+ @rtype: dictionary
+ @return: dictionary of Ganeti-specific options
+
+ """
+ results = {}
+ # hypervisor
+ results["hypervisor"] = {}
+ results["hypervisor"]["name"] = \
+ self.config_parser.get(constants.INISECT_INS, "hypervisor")
+ pairs = self.config_parser.items(constants.INISECT_HYP)
+ for (name, value) in pairs:
+ results["hypervisor"][name] = value
+ if results["hypervisor"].get("name") is None:
+ raise errors.OpPrereqError("No hypervisor information found")
+ # os
+ results["os"] = {}
+ results["os"]["name"] = \
+ self.config_parser.get(constants.INISECT_EXP, "os")
+ pairs = self.config_parser.items(constants.INISECT_OSP)
+ for (name, value) in pairs:
+ results["os"][name] = value
+ if results["os"].get("name") is None:
+ raise errors.OpPrereqError("No operating system information found")
+ # other
+ results["disk_template"] = \
+ self.config_parser.get(constants.INISECT_INS, "disk_template")
+ results["auto_balance"] = \
+ self.config_parser.get(constants.INISECT_BEP, "auto_balance")
+ results["tags"] = \
+ self.config_parser.get(constants.INISECT_INS, "tags")
+ results["version"] = \
+ self.config_parser.get(constants.INISECT_EXP, "version")
+ return results
+
+ def _ParseNetworks(self):
+ """Parses network data from config file.
+
+ @rtype: list
+ @return: list of dictionaries of network options
+
+ @raises errors.OpPrereqError: then network mode is not recognized
+
+ """
+ nics_count = self.config_parser.getint(constants.INISECT_INS, "nic_count")
+ results = []
+ for counter in range(nics_count):
+ results.append({})
+ results[counter]["mode"] = \
+ self.config_parser.get(constants.INISECT_INS, "nic%s_mode" % counter)
+ results[counter]["mac"] = \
+ self.config_parser.get(constants.INISECT_INS, "nic%s_mac" % counter)
+ results[counter]["ip"] = \
+ self.config_parser.get(constants.INISECT_INS, "nic%s_ip" % counter)
+ results[counter]["link"] = \
+ self.config_parser.get(constants.INISECT_INS, "nic%s_link" % counter)
+ if results[counter]["mode"] not in ["bridged", "routed"]:
+ raise errors.OpPrereqError("Network mode %s not recognized" %
+ results[counter]["mode"])
+ return results
+
+ def _GetDiskOptions(self, disk_file, compression):
+ """Convert the disk and gather disk info for .ovf file.
+
+ @type disk_file: string
+ @param disk_file: name of the disk (without the full path)
+ @type compression: bool
+ @param compression: whether the disk should be compressed or not
+
+ @raise errors.OpPrereqError: when disk image does not exist
+
+ """
+ disk_path = utils.PathJoin(self.input_dir, disk_file)
+ results = {}
+ if not os.path.isfile(disk_path):
+ raise errors.OpPrereqError("Disk image does not exist: %s" % disk_path)
+ if os.path.dirname(disk_file):
+ raise errors.OpPrereqError("Unsafe path for the disk: %s" % disk_path)
+ (disk_name, _) = os.path.splitext(disk_file)
+ new_disk_name = "%s.%s" % (disk_name, self.options.disk_format)
+ new_disk_path = utils.PathJoin(self.output_dir, new_disk_name)
+ self._ConvertDisk(self.options.disk_format, disk_path, new_disk_path)
+ results["format"] = self.options.disk_format
+ results["virt-size"] = self._GetDiskQemuInfo(new_disk_path,
+ "virtual size: \S+ \((\S+) bytes\)")
+ if compression:
+ skip_removing = disk_path == new_disk_path
+ # we do not want to delete the original disk
+ new_disk_path = self._CompressDisk(new_disk_path, "gzip", "compress",
+ skip_removing=skip_removing)
+ new_disk_name = "%s%s" % (new_disk_name, COMPRESSION_EXT)
+ results["compression"] = "gzip"
+ results["real-size"] = os.path.getsize(new_disk_path)
+ results["path"] = new_disk_name # TODO: path or name (after checking)?
+ self.references_files.append(new_disk_path)
+ return results
+
+ def _ParseDisks(self):
+ """Parses disk data from config file.
+
+ @rtype: list
+ @return: list of dictionaries of disk options
+
+ """
+ disk_count = self.config_parser.getint(constants.INISECT_INS, "disk_count")
+ results = []
+ for counter in range(disk_count):
+ results.append({})
+ disk_file = \
+ self.config_parser.get(constants.INISECT_INS, "disk%s_dump" % counter)
+ results[counter] = self._GetDiskOptions(disk_file,
+ self.options.compression)
+ return results
+
def Parse(self):
"""Parses the data and creates a structure containing all required info.
@@ -1229,7 +1383,14 @@ class OVFExporter(Converter):
raise errors.OpPrereqError("Failed to create directory %s:\n\t%s" %
(self.output_dir, err))
+ self.references_files = []
self.results_name = self._ParseName()
+ self.results_vcpus = self._ParseVCPUs()
+ self.results_memory = self._ParseMemory()
+ if not self.options.ext_usage:
+ self.results_ganeti = self._ParseGaneti()
+ self.results_network = self._ParseNetworks()
+ self.results_disk = self._ParseDisks()
def _PrepareManifest(self, path):
"""Creates manifest for all the files in OVF package.
--
1.7.3.1