Hello community, here is the log from the commit of package open-ovf for openSUSE:Factory checked in at Fri Feb 5 15:11:01 CET 2010. -------- --- open-ovf/open-ovf.changes 2009-10-22 17:31:14.000000000 +0200 +++ /mounts/work_src_done/STABLE/open-ovf/open-ovf.changes 2009-11-20 00:34:45.000000000 +0100 @@ -1,0 +2,29 @@ +Tue Nov 10 18:02:43 MST 2009 - jfehlig@novell.com + +- Changed lsovf, chovf, and rmovf to use common cli class + instead of OptionsParser +- Fixed help of lsovf, chovf, rmovf, and ova commands + +------------------------------------------------------------------- +Fri Nov 6 20:44:11 MDT 2009 - jfehlig@novell.com + +- Improved help by adding '<cmd> --help <subcmd>' +- Fixed disk device creation for xenpv appliances +- Improved README.SuSE + +------------------------------------------------------------------- +Thu Nov 5 12:19:47 MDT 2009 - jfehlig@novell.com + +- spec file: conditionally specify noarch + +------------------------------------------------------------------- +Tue Nov 3 21:51:09 MDT 2009 - jfehlig@novell.com + +- Fix mkovf help + mkovf-help.patch +- Refactor OvfSet init code + OvfSet-init.patch +- Fix ova command + ova.patch + +------------------------------------------------------------------- @@ -9 +38 @@ -- Initial packaging of open-ovf +- Initial packaging of open-ovf, FATE #303038 calling whatdependson for head-i586 Old: ---- fix-libvirtxml.patch New: ---- chovf.patch help.patch libvirt-clock.patch lsovf.patch ova.patch OvfSet-init.patch rmovf.patch xenpv-libvirtxml.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ open-ovf.spec ++++++ --- /var/tmp/diff_new_pack.7ePcC9/_old 2010-02-05 15:10:10.000000000 +0100 +++ /var/tmp/diff_new_pack.7ePcC9/_new 2010-02-05 15:10:10.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package open-ovf (Version 0.1) # -# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ Name: open-ovf Version: 0.1 -Release: 1 +Release: 2 Summary: Tool for importing and exporting OVF Url: http://open-ovf.wiki.sourceforge.net/ License: EPL @@ -29,11 +29,21 @@ Patch0: output-libvirtxml-file.patch Patch1: xenfv-libvirtxml.patch Patch2: use-before-define.patch -Patch3: fix-libvirtxml.patch +Patch3: libvirt-clock.patch Patch4: python2.6.patch +Patch5: help.patch +Patch6: OvfSet-init.patch +Patch7: ova.patch +Patch8: xenpv-libvirtxml.patch +Patch9: lsovf.patch +Patch10: rmovf.patch +Patch11: chovf.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: python python-devel +%if 0%{?suse_version} > 1110 BuildArch: noarch +%endif +%py_requires %description Open-OVF project is an open source library and tools designed to promote @@ -47,13 +57,19 @@ %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 %build -python setup.py build +%{__python} setup.py build %install -python setup.py install --prefix=%{_prefix} --root=$RPM_BUILD_ROOT --record-rpm=INSTALLED_FILES -#rm -f $RPM_BUILD_ROOT/%{py_sitedir}/*.egg-info +%{__python} setup.py install --prefix=%{_prefix} --root=$RPM_BUILD_ROOT --record-rpm=INSTALLED_FILES mkdir -p $RPM_BUILD_ROOT%{_docdir}/%{name}/ install -m 644 %SOURCE1 $RPM_BUILD_ROOT%{_docdir}/%{name}/ @@ -61,5 +77,4 @@ %defattr(-,root,root) %doc %dir %{_docdir}/%{name} %doc %{_docdir}/%{name}/README.SuSE - %changelog ++++++ chovf.patch ++++++ ++++ 897 lines (skipped) ++++++ help.patch ++++++ Index: open-ovf-0.1/py/scripts/mkovf =================================================================== --- open-ovf-0.1.orig/py/scripts/mkovf +++ open-ovf-0.1/py/scripts/mkovf @@ -22,6 +22,8 @@ from ovf import validation from ovf.commands import cli from ovf.commands import VERSION_STR +USAGE = "usage: mkovf command -f <Ovf file path> [options]" + def initOVF(ovfFile, options=None): """ This function creates an empy OVF. @@ -580,7 +582,7 @@ def validateOVF(ovfFile, options): def main(): #The version=VERSION_STR is the version of the OVF. - cliParser = cli.CLI(commands, common, version=VERSION_STR) + cliParser = cli.CLI(commands, common, usage=USAGE, version=VERSION_STR) command, options, args = cliParser.parseArgs() ovfFile = None @@ -630,20 +632,21 @@ commands = { "required": True }, { "flags" : [ "-s", "--size" ], - "parms" : { "dest" : "size","help":"The size of the file. If none"+ - " is given the size will be acquired for that file." }}, + "parms" : { "dest" : "size","help":"The size of the file in bytes."+ + " If none is given the size will be acquired for that"+ + " file." }}, { "flags" : [ "-c", "--compression" ], "parms" : { "dest" : "compression","help": "Defines the"+ - " compression of the file if any. If none is given the"+ - " compression shall be determined. Specifying 'identity',"+ + " compression of the file, if any. If none is given the"+ + " compression shall be determined. Specifying 'identity'"+ " states that no compression is used. If the href is an"+ - " HTTP or HTTPS ,URI, then the compression may be"+ + " HTTP or HTTPS URI, then the compression may be"+ " specified by the HTTP server." }}, { "flags" : [ "-C", "--chunksize" ], "parms" : { "dest" : "chunksize","help":"Defines the chunksize for"+ - " the file if any." }} + " the file, if any." }} ) }, "disk" : { @@ -664,23 +667,32 @@ commands = { "required": True }, { "flags" : [ "-r", "--fileRef" ], - "parms" : { "dest" : "fileRef","help" : "File reference." }}, + "parms" : { "dest" : "fileRef","help" : "File reference. The"+ + " ovfID of corresponding File element in references"+ + " section."} + }, { "flags" : [ "-s", "--size" ], - "parms" : { "dest" : "populatedSize","help": "Populated Size." }}, + "parms" : { "dest" : "populatedSize","help": "Populated size"+ + " in bytes."} + }, { "flags" : [ "-u", "--capacityAlloc" ], "parms" : { "dest" : "capacityAllocUnits","help" : "Capacity"+ - " allocation Units." }}, + " allocation Units." } + }, { "flags" : [ "-p", "--parentRef" ], - "parms" : { "dest" : "parentRef","help" :"Parent ref. In order to"+ - " specify this the parent must have already been "+ - "specified." }}, - { "flags" : [ "-m", "--info" ], + "parms" : { "dest" : "parentRef","help" :"Reference to parent"+ + " diskID. In order to specify this the parent must"+ + " have already been specified." } + }, + { "flags" : [ "-m", "--info" ], "parms" : { "dest" : "info","help" : "The information to describe"+ - " the section." }}, - { "flags" : [ "-y"], + " the section." } + }, + { "flags" : [ "-y"], "parms" : { "dest" : "infoID","help" : "The id of the section's"+ - " information." }}, - { "flags" : [ "-q", "--notrequired"], + " information." } + }, + { "flags" : [ "-q", "--notrequired"], "parms" : { "dest" : "required", "action": "store_false", "default": True, "help" : "Defines if the section is not required."}, Index: open-ovf-0.1/py/ovf/commands/cli.py =================================================================== --- open-ovf-0.1.orig/py/ovf/commands/cli.py +++ open-ovf-0.1/py/ovf/commands/cli.py @@ -98,15 +98,19 @@ class CLI: @rtype: str """ - parser = OptionParser(self.usage, version = self.version) + parser = OptionParser(self.usage, version=self.version, + add_help_option=False) for opt in self.commands: parser.add_option("--" + opt, help = self.commands[opt]['help'], action="store_const", const=opt, dest="cmd") + parser.add_option("-h", "--help", action="store_const", + const="help", dest="cmd") + try: cmdStr = args[0] except IndexError: - parser.print_help() + self.printHelp(args) sys.exit(2) options, args = parser.parse_args([ cmdStr ]) @@ -158,13 +162,46 @@ class CLI: """ # if args is not specified use sys.argv - args = args or sys.argv[1:] + args = args or sys.argv + + cmd = self._parseCommand(args[1:]) + if cmd == 'help': + self.printHelp(args) + sys.exit(0) - cmd = self._parseCommand(args) - options, pArgs = self._parseSubcommand(cmd, args[1:]) + options, pArgs = self._parseSubcommand(cmd, args[2:]) return cmd, options, pArgs + def printHelp(self, args): + + if len(args) <= 2 or \ + (len(args) > 2 and not self.commands.has_key(args[2])): + print self.usage + print "\nCommands:" + print " --help, -h\n Show this help message and exit" + for cmd in self.commands: + print " --%s" % cmd + print " %s" % self.commands[cmd]['help'] + else: + print "usage: %s --%s [options]" % (args[0], args[2]) + print self.commands[args[2]]['help'] + print "\nOptions:" + for carg in self.common: + flags = " " + for f in carg['flags']: + flags += f + "," + print flags.rsplit(',', 1)[0] + print " %s" % carg['parms']['help'] + cargs = self.commands[args[2]]['args'] + for carg in cargs: + flags = " " + for f in carg['flags']: + flags += f + ", " + print flags.rsplit(',', 1)[0] + print " %s" % carg['parms']['help'] + + class MultipleNodeError(Exception): """ This error class will be used to print information about multiple ++++++ libvirt-clock.patch ++++++ Index: open-ovf-0.1/py/ovf/OvfLibvirt.py =================================================================== --- open-ovf-0.1.orig/py/ovf/OvfLibvirt.py +++ open-ovf-0.1/py/ovf/OvfLibvirt.py @@ -448,7 +448,7 @@ def clockElement(sync): """ document = Document() elem = document.createElement('clock') - elem.setAttribute('sync', sync) + elem.setAttribute('offset', sync) return elem def devicesElement(*devices): ++++++ lsovf.patch ++++++ Index: open-ovf-0.1/py/scripts/lsovf =================================================================== --- open-ovf-0.1.orig/py/scripts/lsovf +++ open-ovf-0.1/py/scripts/lsovf @@ -12,8 +12,10 @@ ############################################################################## import sys -from optparse import OptionParser +from ovf.commands import cli +from ovf.commands import VERSION_STR +from ovf.OvfFile import OvfFile from ovf.OvfFile import OvfFile def getEfile(ovfFile, options): @@ -397,29 +399,10 @@ def getOS(ovfFile, options): print child.firstChild.data def main(): - usage = "usage: %prog command [options]" - command = None - parser = OptionParser(usage) - for long in commands.keys(): - parser.add_option("--" + long, help=commands[long]['help'], - action="store_true") - - #do the help stuff up here.... - if len(sys.argv) > 1: - for long in commands: - if sys.argv[1] == "--" + long or sys.argv[1] == long: - command = long - break - - if command == None or sys.argv[1] == "--help" or sys.argv[1] == "-h": - parser.parse_args(['--help']) - exit(command != None) - - parser = OptionParser(usage) - for opt in commands[long]['args']+common: - parser.add_option(*opt['flags'], **opt['parms']) + usage = "usage: lsovf command --file <Ovf file path> [options]" + cliParser = cli.CLI(commands, common, usage=usage, version=VERSION_STR) + command, options, args = cliParser.parseArgs() - (options, args) = parser.parse_args(sys.argv[2:]) ovfFile = None if options.ovfFile: try: @@ -443,92 +426,92 @@ commands = { 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "disk" : { 'func': getDisk, - 'help' : 'List the disks from the Disk Section.', + 'help' : "List the disks from the Disk Section.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "net" : { 'func': getNetwork, - 'help' : 'List the networks from the network Section.', + 'help' : "List the networks from the network Section.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "deploy" : { 'func': getDeploy, - 'help' : 'List the Deploymen Options Section.', + 'help' : "List the Deploymen Options Section.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "vsc" : { 'func': getVSC, - 'help' : 'List a Virtual System Collection', + 'help' : "List a Virtual System Collection", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "vs" : { 'func': getVS, - 'help' : 'Lists a Virtual System.', + 'help' : "Lists a Virtual System.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "virthw" : { 'func': getHW, - 'help' : 'List a Virtual Hardware Section.', + 'help' : "List a Virtual Hardware Section.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "resource" : { 'func': _getRes, - 'help' : 'Define resources.', + 'help' : "List resources.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "resAlloc" : { 'func' : _findResAlloc, - 'help' : "List the Resource Allocation Sections. ", + 'help' : "List the Resource Allocation Sections.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "annotate" : { @@ -537,8 +520,8 @@ commands = { 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "product" : { @@ -547,60 +530,60 @@ commands = { 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "license" : { 'func': getLicense, - 'help' : "List the legal temrs for using a particular entity. ", + 'help' : "List the legal temrs for using a particular entity.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "startup" : { 'func': getStartup, - 'help' : "List the startup section for either a Virtual System or a\ - Virtual System Collection. ", + 'help' : "List the startup section for either a Virtual System or a " + "Virtual System Collection.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "compat" : { 'func': getCompat, - 'help' : 'List CPU Compatibility Section which specifies requirements on\ - the virtualized CPU. It is only valid in a Virtual System Section.', + 'help' : "List CPU Compatibility Section which specifies requirements on " + "the virtualized CPU. It is only valid in a Virtual System Section.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, "os" : { 'func': getOS, - 'help' : 'List the operating systems section for a Virtual System.', + 'help' : "List the operating systems section for a Virtual System.", 'args' : ( { 'flags' : [ '--vv' ], - 'parms' : { 'dest' : 'vv','help' : 'Very verbose. Only show some\ - parts of the section.','action': 'store_true','default':False } }, + 'parms' : { 'dest' : 'vv','help' : "Very verbose. Only show some " + "parts of the section.",'action': 'store_true','default':False } }, ) }, "install" : { 'func': getInstall, - 'help' : 'List the install section used to describe a virtual system in\ - a virtual system collection.', + 'help' : "List the install section used to describe a virtual system in " + "a virtual system collection.", 'args' : ( { 'flags' : [ '--vv' ], 'parms' : { 'dest' : 'vv', - 'help' : 'Very verbose. Only show some parts of the\ - section.','action': 'store_true','default':False } }, + 'help' : "Very verbose. Only show some parts of the " + "section.",'action': 'store_true','default':False } }, ) }, @@ -618,15 +601,15 @@ common = ( { 'flags' : [ '-f', '--file' ], - 'parms' : { 'dest' : 'ovfFile', 'help': 'Target OVF.' } + 'parms' : { 'dest' : 'ovfFile', 'help' : "Target OVF." } }, { 'flags' : [ '--id' ], 'parms' : { 'dest' : 'id', - 'help':'ID of the section to attach to, if any.'} + 'help' : "ID of the section to attach to, if any."} }, { 'flags' : [ '--verbose' ], 'parms' : {'action':'store_true', 'dest' : 'verbose', - 'help':'Display with verbose.' } + 'help' : "Display with verbose." } }, ) ++++++ output-libvirtxml-file.patch ++++++ --- /var/tmp/diff_new_pack.7ePcC9/_old 2010-02-05 15:10:10.000000000 +0100 +++ /var/tmp/diff_new_pack.7ePcC9/_new 2010-02-05 15:10:10.000000000 +0100 @@ -18,7 +18,7 @@ - # queue domains with action: domains[id].create() - schedule = OvfLibvirt.getSchedule(startup, domains) + if ofile: -+ fd = os.open(ofile, os.O_RDWR | os.O_CREAT | os.O_TRUNC) ++ fd = os.open(ofile, os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0644) + for domain in domains.values(): + os.write(fd, domain) + os.write(fd, "\n\n") ++++++ ova.patch ++++++ Index: open-ovf-0.1/py/scripts/ova =================================================================== --- open-ovf-0.1.orig/py/scripts/ova +++ open-ovf-0.1/py/scripts/ova @@ -36,7 +36,7 @@ from ovf.OvfFile import OvfFile from ovf import OvfPlatform from ovf import OvfProperty from ovf.OvfReferencedFile import OvfReferencedFile -from ovf.OvfSet import OvfSet +from ovf.OvfSet import * from ovf.OvfManifest import writeManifestFromReferencedFilesList from ovf import OvfTransport from ovf.env import PlatformSection @@ -105,7 +105,7 @@ def packOva(options, args): # Base the output file name on the ovf file name outFile = os.path.splitext(options.ovfFile)[0] + '.ova' - ovfSet = OvfSet(options.ovfFile) + ovfSet = OvfSet(outFile, "w", FORMAT_TAR) if options.noManifest == False: manifestFile = options.manifestFile @@ -141,7 +141,7 @@ def unpackOva(options, args): @param args : target directory path to extract the appliance archive file """ if options.ovfFile != None and os.path.isfile(options.ovfFile): - ovaSet = OvfSet(options.ovfFile, "r") + ovaSet = OvfSet(options.ovfFile, "r", FORMAT_TAR) if not os.path.isdir(options.targetDir): os.mkdir(options.targetDir) ovaSet.writeAsDir(options.targetDir) @@ -610,7 +610,7 @@ COMMANDS = { "manifest" : { 'function' : makeManifest, - 'help' : "Create a manifest file with SHA-1 sum for each " + + 'help' : "Create a manifest file with SHA-1 sum for each " "referenced file", 'args' : ( { @@ -640,7 +640,7 @@ COMMANDS = { "pack" : { 'function' : packOva, - 'help' : "Packs a set of files comprising a virtual appliance into " + + 'help' : "Packs a set of files comprising a virtual appliance into " "a single file in the tar format", 'args' : ( { @@ -690,7 +690,7 @@ COMMANDS = { "runtime" : { "function" : run, - "help" : "Deploy the virtual systems of an OVF file as " + + "help" : "Deploy the virtual systems of an OVF file as " "libvirt domains", "args" : ( { @@ -732,8 +732,8 @@ COMMANDS = { 'flags' : ['-z', '--no-value'], 'parms' : {'dest' : 'noValue', 'action' : "store_true", 'default' : False, - 'help' : "With no-prompt, values without defaults " +\ - "are listed but left unset"} + 'help' : "With no-prompt, values without defaults " + "are listed but left unset"} }, { 'flags' : ['-i', '--id'], @@ -770,14 +770,14 @@ COMMANDS = { { 'flags' : ['-t', '--format'], 'parms' : {'dest' : 'format', 'default' : 'iso', - 'help' : "Transport format. Valid values: 'iso'." +\ + 'help' : "Transport format. Valid values: 'iso'. " "Default is 'iso'."} }, { 'flags' : ['-o', '--outfile'], 'parms': {'dest' : 'outFile', 'default' : None, - 'help' : "Output file. All environment files will be" +\ - " put on a single iso with this name."} + 'help' : "Output file. All environment files will be " + "put on a single iso with this name."} } ), ++++++ OvfSet-init.patch ++++++ Index: open-ovf-0.1/py/ovf/OvfSet.py =================================================================== --- open-ovf-0.1.orig/py/ovf/OvfSet.py +++ open-ovf-0.1/py/ovf/OvfSet.py @@ -29,7 +29,7 @@ class OvfSet(object): archive or as a directory layout """ - def __init__(self, path=None, mode="r"): + def __init__(self, path=None, mode="r", format=FORMAT_DIR): """ Initialize object from path in read/write mode @@ -48,8 +48,8 @@ class OvfSet(object): #: the package name of this object (the name of .ovf without extension) self.name = None - self.ovfFile = None #: The OvfFile object - self.archiveFormat = FORMAT_DIR #: The archive type of this (default save type) + self.ovfFile = None #: The OvfFile object + self.archiveFormat = format #: The archive type of this (default save type) self.archivePath = None #: The write path of the archive self.archiveSavePath = None #: The Save Path for the archive (differs from archivePath for tar) self.__tmpdir__ = None #: the temporary dir if tar (cleaned up in __del__) @@ -60,7 +60,7 @@ class OvfSet(object): self.certificate = None if path != None: - self.initializeFromPath(path, mode) + self.initializeFromPath(path) def __del__(self): """ @@ -89,70 +89,21 @@ class OvfSet(object): mode = property(_getMode, _setMode) - def initializeFromPath(self, path, mode="r"): + def initializeFromPath(self, path): """ initialize object from the file or path given in path @raise IOError: The cases are as follow - - I{B{Case 1:}} The path provided in the parameters is not - valid. - - I{B{Case 2:}} The mode parameter has a value of r and the path - already exist. - - I{B{Case 3:}} Unsafe Tar file - - I{B{Case 4:}} The tar file cannot be found. + - I{B{Case 1:}} Invalid archive format + - I{B{Case 2:}} Unsafe Tar file + - I{B{Case 3:}} The tar file cannot be found. @type path: String @param path: a path to a file to open - @type mode: string - @param mode: mode for open, either 'r' or 'w' """ - - exists = True - if os.path.isdir(path): - self.archiveFormat = FORMAT_DIR - elif os.path.isfile(path): - if tarfile.is_tarfile(path): - self.archiveFormat = FORMAT_TAR - else: - # this file is not a tar file, assume that this is a .ovf - self.archiveFormat = FORMAT_DIR - elif os.path.exists(path): - raise IOError("unsupported file type for " + path) - else: - exists = False - if mode == "r": - raise IOError("cannot open for read " + path) - if path.endswith("/") or path.endswith("\\"): - self.archiveFormat = FORMAT_DIR - elif path.endswith(".ovf") or path.endswith(".OVF"): - self.archiveFormat = FORMAT_DIR - else: - self.archiveFormat = FORMAT_TAR - - if exists == True and self.archiveFormat == FORMAT_TAR: - # Here, for now, we make a temporary copy - tmpdir = os.path.dirname(os.path.abspath(path)) - if os.environ.has_key("TMPDIR"): tmpdir = None - tmpd = tempfile.mkdtemp(dir=tmpdir) - self.__tmpdir__ = tmpd - tf = tarfile.open(path, "r") - ti = tf.next() - while ti is not None: - #TODO: need to do safe extraction here this - # on windows need to protect c:// - # also, check that .ovf is first file - # suggestion[ejcasler]: change ".." to "../" - # make absolute refs begin with tempdir path - if ti.name.find("..") != -1 or ti.name.startswith("/"): - raise IOError("Unsafe Tar file" + path) - tf.extract(ti, tmpd) - ti = tf.next() - self.archivePath = tmpd - self.archiveSavePath = path - elif exists == True and self.archiveFormat == FORMAT_DIR: - # for existing, if it is a file path=dirname(path) + if self.archiveFormat == FORMAT_DIR: if os.path.isfile(path): self.archivePath = os.path.dirname(path) # dirname returns "" rather than "." for "filename" @@ -162,46 +113,53 @@ class OvfSet(object): else: self.archivePath = path self.archiveSavePath = self.archivePath - elif exists == False and self.archiveFormat == FORMAT_TAR: - # for non-existant file, this is the file (.ova) - self.archivePath = path - self.archiveSavePath = self.archivePath - self.setName(os.path.basename(path)[0:(len(os.path.basename(path))-4)]) - elif exists == False and self.archiveFormat == FORMAT_DIR: - # for non-existant dir, this is a dir (not .ovf) - self.archivePath = path - self.archiveSavePath = self.archivePath + elif self.archiveFormat == FORMAT_TAR: + if os.path.isfile(path): + # Here, for now, we make a temporary copy + tmpdir = os.path.dirname(os.path.abspath(path)) + if os.environ.has_key("TMPDIR"): tmpdir = None + tmpd = tempfile.mkdtemp(dir=tmpdir) + self.__tmpdir__ = tmpd + tf = tarfile.open(path, "r") + for ti in tf.getmembers(): + #TODO: need to do safe extraction here this + # on windows need to protect c:// + # also, check that .ovf is first file + # suggestion[ejcasler]: change ".." to "../" + # make absolute refs begin with tempdir path + if ti.name.find("..") != -1 or ti.name.startswith("/"): + raise IOError("Unsafe Tar file" + path) + tf.extract(ti, tmpd) + tf.close() + self.archivePath = tmpd + self.archiveSavePath = path + else: + # for non-existant file, this is the file (.ova) + (p, f) = os.path.split(os.path.abspath(path)) + self.archivePath = p + self.archiveSavePath = self.archivePath + self.setName((f.rsplit(".ova", 1))[0]) + else: - raise IOError("shouldn't be here") + raise IOError("Invalid archive format") - if ( not os.path.isfile(path) and self.archiveFormat == FORMAT_DIR and - exists == True ) or self.__tmpdir__ != None: - name = False + if self.name == None: for curFile in os.listdir(self.archivePath): if curFile.endswith(".ovf"): - if name != False: - return False - # set name to filename without .ovf - name = curFile[0:(len(curFile)-4)] - if name == False and mode == "r": - raise IOError("no ovf file in " + path + "(" + self.archivePath + ")") - elif name: - self.setName(name) - - # now self.archivePath, self.archiveSavePath and self.archiveFormat should - # be set. self.name should be set if possible. - # now, self.archivePath/self.name + ".ovf" should have the ovf file - - if self.name != None: - basepath = os.path.join(self.archivePath, self.name) - self.ovfFile = OvfFile.OvfFile(basepath + ".ovf") - if os.path.isfile(basepath + ".mf"): - # we have a manifest - self.manifest = basepath + ".mf" - - if os.path.isfile(basepath + ".cert"): - # we have a certificate - self.certificate = basepath + ".cert" + self.name = curFile[0:(len(curFile)-4)] + + # ovf file name = self.archivePath + / + self.name + .ovf + basepath = os.path.join(self.archivePath, self.name) + self.ovfFile = OvfFile.OvfFile(basepath + ".ovf") + + # Similarly, aux file name = self.archive + / + self.name + .ext + if os.path.isfile(basepath + ".mf"): + # we have a manifest + self.manifest = basepath + ".mf" + + if os.path.isfile(basepath + ".cert"): + # we have a certificate + self.certificate = basepath + ".cert" def toString(self): """Overrides toString for OvfSet""" @@ -285,7 +243,7 @@ class OvfSet(object): os.unlink(ovfName) ovfname = None except: - if ovfname != None: + if ovfName != None: os.unlink(ovfName) raise ++++++ README.SuSE ++++++ --- /var/tmp/diff_new_pack.7ePcC9/_old 2010-02-05 15:10:10.000000000 +0100 +++ /var/tmp/diff_new_pack.7ePcC9/_new 2010-02-05 15:10:10.000000000 +0100 @@ -28,7 +28,7 @@ ----------- The Distributed Management Task Force (DMTF) has defined a vendor-neutral standard for packaging virtual appliances enabling automated installation, -configuration and activation of any virtualization platform. Open Virtual +configuration and activation on any virtualization platform. Open Virtual Machine Format (OVF) specification describes an open, secure, portable, efficient and extensible format for packaging and distribution of virtual machines. Some of the main features of OVF are @@ -96,64 +96,81 @@ are individually used to build different sections of the OVF. These commands closely parallel the standard, so ambiguity regarding the significance or value of arguments may be determined by looking at the OVF specification. +Nonetheless, brief comments about each subcommand are available through the +'help' subcommand: +mkovf --help +mkovf --help <subcommand> The following is an example of how to create an OVF for a SLES-based virtual appliance that targets the Xen hypervisor, using the mkovf command. # Create the Envelope, or root node, for the OVF file. All other sub-sections # are attached to the Envelope -mkovf --init -f sles11.ovf +mkovf --init --file sles11.ovf # Add an external file (e.g. the appliance disk image) to the Reference section -mkovf --efile -f sles11.ovf --ovfID disk0 -n sles11.img -s 4294967296 +# of the OVF envelope. +mkovf --efile --file sles11.ovf --ovfID disk0 --href sles11.img \ + --size 4294967296 + +# Add a DiskSection to OVF meta-data. The DiskSection describes meta- +# data about all virtual disks in the OVF. The fileRef option identifies +# the corresponding File element in Reference section. It should be set +# to the same value as ovfID option used when creating the File element. +mkovf --disk --file sles11.ovf --diskID disk0 --capacity 4294967296 \ + --format "Raw Image" --info "Virtual Disks" --size 4294967296 \ + --fileRef disk0 + +# Add a NetworkSection to OVF meta-data. The NetworkSection describes logical +# networks used in the OVF. +mkovf --net --file sles11.ovf --networkName br0 --netID 1 \ + --description "Bridged network" --info "Networks used by appliance" + +# Add a VirtualSystem to the OVF envelope. An OVF must contain at least one +# VirtualSystem or VirtualSystemCollection. +mkovf --vs --file sles11.ovf --vsID SLES11-vm \ + --info "Single-VM, SLES11-based virtual appliance" + +# Add an OperatingSystemSection to OVF meta-data. The OperatingSystemSection +# specifies the installed guest operating system of a VirtualSystem. It is +# only valid for VirtualSystems and does not apply to VirtualSystemCollections. +mkovf --os --file sles11.ovf --name SLES11 --description "Linux 2.6.31" \ + --info "SuSE Linux Enterprise Server" + +# Add a VirtualHardwareSection to a VirtualSystem. At least one +# VirtualHardwareSection must be specified for each VirtualSystem. Multiple +# VirtualHardwarSections can be specified for a VirtualSystem. This section +# can not be specified for a VirtualHardwareCollection +mkovf --virthw --file sles11.ovf --sysID 275b6cdf-c22d-52c6-5bce-fc17f71644b8 \ + --type xenpv --instanceID 1 --elementName "sles11-xen" \ + --info "Virtual Hardware Requirements: 512Mb, 4 CPUs, 1 disk, 1 nic" \ -# Append the specified disk information to the Disk section -mkovf --disk -f sles11.ovf -i disk0 -c 4294967296 -F "Raw Image" --info \ - "Virtual Disks" -s 4294967296 --fileRef disk0 - -# Append the specified network information to the Network section -mkovf --net -f sles11.ovf --networkName br0 -i 1 -d "Bridged network" \ - --info "Networks used by appliance" - -# Add a virtual system. The --id parameter can specify eitehr the id of -# virtual system collection to which this new collection should be attached -# or the parent section for the virtual system -mkovf --vs -f sles11.ovf -i SLES11-vm -m "Single-VM, SLES11-based virtual appliance" - -# Create an OperatingSystem Section. It is only valid for Virtual Servers. -# secID specifies the os type. This is an enumeration defined by -# CIM_OperatingSystem.osType -mkovf --os -f sles11.ovf --id SLES11-vm --info "SuSE Linux Enterprise Server" \ - --description "Linux 2.6.x" --secID 103 - -# Add a virtual hardware section to a virtual system. At least one virtual -# hardware section must be specified for each virtual system. Multiple virtual -# hardware sections can be specified for a virtual system. This section can not -# be specified for a virtual hardware collection -mkovf --virthw -f sles11.ovf --id SLES11-vm --type xenpv --secID vh0 --info \ - "Virtual Hardware Requirements: 512Mb, 4 CPUs, 1 disk, 1 nic" --instanceID 1 \ - --elementName "sles11-xen" - -# Add virtual resource elements to the VirtualHardware Section +# Add virtual resource elements to the VirtualHardwareSection # CPUs -mkovf --resource -f sles11.ovf --id vh0 --caption "4 VCPUs" \ - --description "Number of VCPUs" --resourceID 1 --resourceType 3 \ - --virtualQuantity 4 --elementName "virtual CPUs" +mkovf --resource --file sles11.ovf --caption "4 VCPUs" \ + --description "Number of VCPUs" --resourceID numVCPU --resourceType 3 \ + --virtualQuantity 4 --elementName "vcpus" # Memory -mkovf --resource -f sles11.ovf --id vh0 --allocUnits MegaBytes \ - --caption "512MB of memory" --description "Memory size" --resourceID 2 \ - --resourceType 4 --virtualQuantity 512 --elementName "Memory" +mkovf --resource --file sles11.ovf --allocUnits "byte * 2^20" \ + --caption "512MB of memory" --description "512MB Memory" \ + --resourceID mem0 --resourceType 4 --virtualQuantity 512 \ + --elementName "Mem0" # NIC -mkovf --resource -f sles11.ovf --id vh0 --automaticAllocation True \ +# The connection option specifies the bridge used by the virtual NIC +mkovf --resource --file sles11.ovf --automaticAllocation True \ --caption "Ethernet adapter on bridge network" --description "Ethernet" \ - --resourceID 3 --resourceType 10 --elementName "eth0" + --connection br0 --resourceID 3 --resourceType 10 --elementName "eth0" # Disk -mkovf --resource -f sles11.ovf --id vh0 --caption "Disk1" \ - --description "Harddisk" --hostResource ovf://disk/sles11.img \ - --resourceID 4 --resourceType 17 --elementName "xvda" +# The hostResource option specifies the backing disk. Use ovf://disk/<diskId> +# where <diskID> is the disk ID specified in the DiskSection. +# The address option is used to specify the virtual block device name +# presented to the guest, e.g. xvda. +mkovf --resource --file sles11.ovf --caption "Disk1" --description "Harddisk" \ + --hostResource ovf://disk/sles11.img --resourceID 4 --resourceType 17 \ + --elementName xvda --address xvda Creating an OVA @@ -166,7 +183,7 @@ packing of an appliance into this OVA file. # Create an ova with no manifest or certificate file -ova --pack -f sles11.ovf -o sles10sp2-hvm.ova --no-manifest --no-certificate +ova --pack --file sles11.ovf --output sles11.ova --no-manifest --no-certificate Activating an OVA @@ -178,10 +195,10 @@ 'virsh create <libvirt-xml-output>' # First, the ova must be unpacked -ova --unpack -f sles11.ova +ova --unpack --directory /tmp/foo --file /tmp/sles11.ova # Next, extract libvirt XML to a file -ova --runtime -f sles11.ovf --virt xenpv --ofile sles11-libvirt.xml +ova --runtime --file sles11.ovf --virt xenpv --ofile sles11-libvirt.xml # Finally, activate the guest using libvirt's virsh command virsh create sles11-libvirt.xml @@ -189,4 +206,4 @@ Alternatively, once unpacked, the appliance can be activated directly using the ova runtime subcommand by not specifying the --ofile option: -ova --runtime -f sles11.ovf --virt xenpv +ova --runtime --file sles11.ovf --virt xenpv ++++++ rmovf.patch ++++++ ++++ 786 lines (skipped) ++++++ xenpv-libvirtxml.patch ++++++ Index: open-ovf-0.1/py/ovf/OvfLibvirt.py =================================================================== --- open-ovf-0.1.orig/py/ovf/OvfLibvirt.py +++ open-ovf-0.1/py/ovf/OvfLibvirt.py @@ -1135,20 +1135,22 @@ def getOvfDisks(virtualHardware, dir, re raise ValueError(hostResource) #target bus - parentId = int(ovfDisk['rasd:Parent']) - for presource in rasd: - if presource['name'] == 'Item': - instId = int(presource['rasd:InstanceID']) - if instId == parentId: - parentType = presource['rasd:ResourceType'] - break - - if(parentType == '5'): - bus = 'ide' - elif(parentType == '6'): - bus = 'scsi' - else: - raise ValueError + bus = None + if ovfDisk.has_key('rasd:Parent'): + parentId = int(ovfDisk['rasd:Parent']) + for presource in rasd: + if presource['name'] == 'Item': + instId = int(presource['rasd:InstanceID']) + if instId == parentId: + parentType = presource['rasd:ResourceType'] + break + + if(parentType == '5'): + bus = 'ide' + elif(parentType == '6'): + bus = 'scsi' + else: + raise ValueError #default not read-only ro = False @@ -1157,15 +1159,18 @@ def getOvfDisks(virtualHardware, dir, re if(device == 'cdrom'): ro = True dev = 'hdc' + if ovfDisk.has_key('rasd:Address'): + dev = ovfDisk['rasd:Address'] else: dev = logicalNames.pop(0) libvirtDisk = dict(diskType='file', diskDevice=device, sourceFile=source, - targetBus=bus, targetDev=dev, readonly=ro) + if bus: + libvirtDisk['targetBus'] = bus disks += (libvirtDisk,) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org