From b179ce7256d4e6533aa9ef97985818f7052449f3 Mon Sep 17 00:00:00 2001 From: Agata Murawska <agatamurawska@google.com> Date: Mon, 12 Sep 2011 13:17:28 +0200 Subject: [PATCH] Export: parsing data from config file Signed-off-by: Agata Murawska <agatamurawska@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- lib/ovf.py | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/lib/ovf.py b/lib/ovf.py index 9c1651238..6b99782c6 100644 --- a/lib/ovf.py +++ b/lib/ovf.py @@ -98,6 +98,14 @@ CONVERT_UNITS_TO_MB = { # Names of the config fields NAME = "name" +OS = "os" +HYPERV = "hypervisor" +VCPUS = "vcpus" +MEMORY = "memory" +AUTO_BALANCE = "auto_balance" +DISK_TEMPLATE = "disk_template" +TAGS = "tags" +VERSION = "version" def LinkFile(old_path, prefix=None, suffix=None, directory=None): @@ -1233,8 +1241,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): @@ -1284,6 +1302,157 @@ 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 + + @raise 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 + + @raise 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"] = {} + hyp_name = self.config_parser.get(constants.INISECT_INS, HYPERV) + if hyp_name is None: + raise errors.OpPrereqError("No hypervisor information found") + results["hypervisor"]["name"] = hyp_name + pairs = self.config_parser.items(constants.INISECT_HYP) + for (name, value) in pairs: + results["hypervisor"][name] = value + # os + results["os"] = {} + os_name = self.config_parser.get(constants.INISECT_EXP, OS) + if os_name is None: + raise errors.OpPrereqError("No operating system information found") + results["os"]["name"] = os_name + pairs = self.config_parser.items(constants.INISECT_OSP) + for (name, value) in pairs: + results["os"][name] = value + # other + others = [ + (constants.INISECT_INS, DISK_TEMPLATE, "disk_template"), + (constants.INISECT_BEP, AUTO_BALANCE, "auto_balance"), + (constants.INISECT_INS, TAGS, "tags"), + (constants.INISECT_EXP, VERSION, "version"), + ] + for (section, element, name) in others: + results[name] = self.config_parser.get(section, element) + return results + + def _ParseNetworks(self): + """Parses network data from config file. + + @rtype: list + @return: list of dictionaries of network options + + @raise errors.OpPrereqError: then network mode is not recognized + + """ + results = [] + counter = 0 + while True: + data_link = \ + self.config_parser.get(constants.INISECT_INS, "nic%s_link" % counter) + if data_link is None: + break + results.append({ + "mode": self.config_parser.get(constants.INISECT_INS, + "nic%s_mode" % counter), + "mac": self.config_parser.get(constants.INISECT_INS, + "nic%s_mac" % counter), + "ip": self.config_parser.get(constants.INISECT_INS, + "nic%s_ip" % counter), + "link": data_link, + }) + if results[counter]["mode"] not in constants.NIC_VALID_MODES: + raise errors.OpPrereqError("Network mode %s not recognized" + % results[counter]["mode"]) + counter += 1 + 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("Path for the disk: %s contains a directory" + " name" % disk_path) + disk_name, _ = os.path.splitext(disk_file) + ext, new_disk_path = self._ConvertDisk(self.options.disk_format, disk_path) + results["format"] = self.options.disk_format + results["virt-size"] = self._GetDiskQemuInfo(new_disk_path, + "virtual size: \S+ \((\d+) bytes\)") + if compression: + ext2, new_disk_path = self._CompressDisk(new_disk_path, "gzip", + COMPRESS) + disk_name, _ = os.path.splitext(disk_name) + results["compression"] = "gzip" + ext += ext2 + final_disk_path = LinkFile(new_disk_path, prefix=disk_name, suffix=ext, + directory=self.output_dir) + final_disk_name = os.path.basename(final_disk_path) + results["real-size"] = os.path.getsize(final_disk_path) + results["path"] = final_disk_name + self.references_files.append(final_disk_path) + return results + + def _ParseDisks(self): + """Parses disk data from config file. + + @rtype: list + @return: list of dictionaries of disk options + + """ + results = [] + counter = 0 + while True: + disk_file = \ + self.config_parser.get(constants.INISECT_INS, "disk%s_dump" % counter) + if disk_file is None: + break + results.append(self._GetDiskOptions(disk_file, self.options.compression)) + counter += 1 + return results + def Parse(self): """Parses the data and creates a structure containing all required info. @@ -1294,7 +1463,14 @@ class OVFExporter(Converter): raise errors.OpPrereqError("Failed to create directory %s: %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. -- GitLab