[et-mgmt-tools] [PATCH 06 of 11] virt-convert: add format detection

john.levon at sun.com john.levon at sun.com
Thu Jul 10 13:48:36 UTC 2008


# HG changeset patch
# User john.levon at sun.com
# Date 1215697570 25200
# Node ID 91d463e8e9921844271a90f416e0e6d94fd2af40
# Parent  f5e35abf05eb1fa3b64af2cf2cdcfc26139025fd
virt-convert: add format detection

Add format detection, along with detection for VMX

Signed-off-by: John Levon <john.levon at sun.com>

diff --git a/virt-convert b/virt-convert
--- a/virt-convert
+++ b/virt-convert
@@ -1,9 +1,10 @@
 #!/usr/bin/python 
-#
-# Convert a VMware(tm) virtual machine into an XML image description
 #
 # Copyright 2008  Red Hat, Inc.
 # Joey Boggs <jboggs at redhat.com>
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -49,8 +50,7 @@
     opts.add_option("-d", "--debug", action="store_true", dest="debug",
                     help=("Print debugging information"))
     opts.add_option("-i", "--input-format", action="store",
-                    dest="input_format", default="vmx",
-                    help=("Input format, e.g. 'vmx'"))
+                    dest="input_format", help=("Input format, e.g. 'vmx'"))
     opts.add_option("-o", "--output-format", action="store",
                     dest="output_format", default="virt-image",
                     help=("Output format, e.g. 'virt-image'"))
@@ -71,35 +71,45 @@
         options.disk_format not in diskcfg.disk_formats()):
         opts.error("Unknown output disk format \"%s\"" % options.disk_format)
 
-    # hard-code for now
-    if options.input_format != "vmx":
-        opts.error(("Unsupported input format \"%s\"" % options.input_format))
-    if options.output_format != "virt-image":
-        opts.error(("Unsupported output format \"%s\""
-            % options.output_format))
-    if os.path.isdir(args[0]):
-        vmx_files = [x for x in os.listdir(args[0]) if x.endswith(".vmx") ]
-        if (len(vmx_files)) == 0:
-            opts.error(("No VM definition file was found in %s" % args[0]))
-        if (len(vmx_files)) > 1:
-            opts.error(("Too many .vmx definitions found in %s" % args[0]))
-        options.input_file = os.path.join(args[0], vmx_files[0])
-        options.input_dir =  args[0]
-    else:
-        options.input_file = args[0]
-        options.input_dir = os.path.dirname(os.path.realpath(args[0]))
-
     if len(args) == 1:
         options.output_file = None
         options.output_dir = None
         if os.path.isdir(args[0]):
-            options.output_dir = options.input_dir
+            options.output_dir = args[0]
     elif os.path.isdir(args[1]) or args[1].endswith("/"):
         options.output_file = None
         options.output_dir = args[1]
     else:
         options.output_file = args[1]
         options.output_dir = os.path.dirname(os.path.realpath(args[1]))
+
+    if options.output_format not in formats.formats():
+        opts.error(("Unknown output format \"%s\"" % options.output_format))
+    if options.output_format not in formats.output_formats():
+        opts.error(("No output handler for format \"%s\""
+            % options.output_format))
+
+    if not options.input_format:
+        try:
+            (args[0], options.input_format) = formats.find_input(args[0])
+        except StandardError, e:
+            opts.error("Couldn't determine input format for \"%s\": %s" % 
+                (args[0], e.message))
+            sys.exit(1)
+
+    if options.input_format not in formats.formats():
+        opts.error(("Unknown input format \"%s\"" % options.input_format))
+    if options.input_format not in formats.input_formats():
+        opts.error(("No input handler for format \"%s\""
+            % options.input_format))
+
+    if os.path.isdir(args[0]):
+        (options.input_file, _) = formats.find_input(args[0],
+            options.input_format)
+        options.input_dir =  args[0]
+    else:
+        options.input_file = args[0]
+        options.input_dir = os.path.dirname(os.path.realpath(args[0]))
 
     return options
 
@@ -134,19 +144,8 @@
     options = parse_args()
     cli.setupLogging("virt-convert", options.debug)
 
-    try:
-        inp = formats.find_parser_by_name(options.input_format)
-    except:
-        logging.error("No parser of format \"%s\" was found." %
-            options.input_format)
-        sys.exit(1)
- 
-    try:
-        outp = formats.find_parser_by_name(options.output_format)
-    except:
-        logging.error("No parser of format \"%s\" was found." %
-            options.output_format)
-        sys.exit(1)
+    inp = formats.parser_by_name(options.input_format)
+    outp = formats.parser_by_name(options.output_format)
 
     vmdef = None
 
diff --git a/virtconv/formats.py b/virtconv/formats.py
--- a/virtconv/formats.py
+++ b/virtconv/formats.py
@@ -17,6 +17,8 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA 02110-1301 USA.
 #
+
+import os
 
 _parsers = [ ]
 
@@ -66,11 +68,13 @@
     global _parsers
     _parsers += [ parser ]
 
-def find_parser_by_name(name):
+def parser_by_name(name):
     """
-    Return the parser of the given name
+    Return the parser of the given name.
     """
-    return [p for p in _parsers if p.name == name][0] or None
+    parsers = [p for p in _parsers if p.name == name]
+    if len(parsers):
+        return parsers[0]
 
 def find_parser_by_file(input_file):
     """
@@ -80,3 +84,46 @@
         if p.identify_file(input_file):
             return p
     return None
+
+def formats():
+    """
+    Return a list of supported formats.
+    """
+    return [p.name for p in _parsers]
+
+def input_formats():
+    """
+    Return a list of supported input formats.
+    """
+    return [p.name for p in _parsers if p.can_import]
+
+def output_formats():
+    """
+    Return a list of supported output formats.
+    """
+    return [p.name for p in _parsers if p.can_export]
+
+def find_input(path, format = None):
+    """
+    Search for a configuration file automatically. If @format is given,
+    then only search using a matching format parser.
+    """
+
+    if os.path.isdir(path):
+        files = os.listdir(path)
+
+    for p in _parsers:
+        if not p.can_identify:
+            continue
+        if format and format != p.name:
+            continue
+
+        if os.path.isfile(path):
+            if p.identify_file(path):
+                return (path, p.name)
+        elif os.path.isdir(path):
+            for cfgfile in [ x for x in files if x.endswith(p.suffix) ]:
+                if p.identify_file(os.path.join(path, cfgfile)):
+                    return (os.path.join(path, cfgfile), p.name)
+ 
+    raise StandardError("unknown format")
diff --git a/virtconv/parsers/virtimage.py b/virtconv/parsers/virtimage.py
--- a/virtconv/parsers/virtimage.py
+++ b/virtconv/parsers/virtimage.py
@@ -81,6 +81,9 @@
     """
     name = "virt-image"
     suffix = ".virt-image.xml"
+    can_import = False
+    can_export = True
+    can_identify = False
 
     @staticmethod
     def identify_file(input_file):
diff --git a/virtconv/parsers/vmx.py b/virtconv/parsers/vmx.py
--- a/virtconv/parsers/vmx.py
+++ b/virtconv/parsers/vmx.py
@@ -22,6 +22,8 @@
 import virtconv.vmcfg as vmcfg
 import virtconv.diskcfg as diskcfg
 
+import re
+
 class vmx_parser(formats.parser):
     """
     Support for VMWare .vmx files.  Note that documentation is
@@ -31,13 +33,23 @@
 
     name = "vmx"
     suffix = ".vmx"
+    can_import = True
+    can_export = False
+    can_identify = True
 
     @staticmethod
     def identify_file(input_file):
         """
         Return True if the given file is of this format.
         """
-        raise NotImplementedError
+        infile = open(input_file, "r")
+        line = infile.readline()
+        infile.close()
+
+        # some .vmx files don't bother with the header
+        if re.match(r'^config.version\s+=', line):
+            return True
+        return re.match(r'^#!\s*/usr/bin/vm(ware|player)', line) is not None
 
     @staticmethod
     def import_file(input_file):




More information about the et-mgmt-tools mailing list