[Pkg-escience-soc2009] [SCM] Tool for creating VM images. branch, master, updated. 5fc9757950d15e9be3439111cb731711106ab819

David Wendt dcrkid at yahoo.com
Tue Jun 9 20:26:50 UTC 2009


The following commit has been merged in the master branch:
commit e0aecfb30324560330af83482605bf2737a691ad
Author: David Wendt <dcrkid at yahoo.com>
Date:   Tue Jun 9 16:14:40 2009 -0400

    Another source trunk, obtained from bzr lp:~bzed/vmbuilder/debian

diff --git a/AUTHORS b/AUTHORS
index bd88ffb..d65c727 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,3 +2,5 @@ Main authors and original conceptor: Soren Hansen <soren at canonical.com>
 
 Other contributors:
  * Nicolas Barcet <nicolas.barcet at ubuntu.com>
+ * Bernd Zeimetz <bzed at debian.org>
+ 
\ No newline at end of file
diff --git a/VMBuilder/__init__.py b/VMBuilder/__init__.py
index 87e2721..f44eea1 100644
--- a/VMBuilder/__init__.py
+++ b/VMBuilder/__init__.py
@@ -21,10 +21,9 @@
 #    The publically exposed bits of VMBuilder
 #
 import logging
-import VMBuilder.plugins
+from   VMBuilder.plugins    import load_plugins, Plugin
 from   VMBuilder.distro     import Distro
 from   VMBuilder.hypervisor import Hypervisor
-from   VMBuilder.plugins    import Plugin
 from   VMBuilder.frontend   import Frontend
 from   VMBuilder.vm         import VM
 from   VMBuilder.exception  import VMBuilderException, VMBuilderUserError
@@ -66,4 +65,4 @@ def run():
     frontend.run()
 
 logging.debug('Loading plugins')
-VMBuilder.plugins.load_plugins()
+load_plugins()
diff --git a/VMBuilder/disk.py b/VMBuilder/disk.py
index 627c710..9dd482f 100644
--- a/VMBuilder/disk.py
+++ b/VMBuilder/disk.py
@@ -59,7 +59,7 @@ class Disk(object):
             self.filename = filename
         else:
             if self.preallocated:
-                raise VMBuilderException('Preallocated was set, but no filename given')
+                raise VMBuilderUserError('Preallocated was set, but no filename given')
             self.filename = 'disk%d.img' % len(self.vm.disks)
 
         self.partitions = []
@@ -180,7 +180,7 @@ class Disk(object):
         @type  destdir: string
         @param destdir: Target location of converted disk image
         @type  format: string
-        @param format: The target format (as understood by qemu-img)
+        @param format: The target format (as understood by qemu-img or vdi)
         @rtype:  string
         @return: the name of the converted image
         """
@@ -194,7 +194,10 @@ class Disk(object):
         destfile = '%s/%s.%s' % (destdir, filename, format)
 
         logging.info('Converting %s to %s, format %s' % (self.filename, format, destfile))
-        run_cmd(qemu_img_path(), 'convert', '-O', format, self.filename, destfile)
+        if format == 'vdi':
+            run_cmd(vbox_manager_path(), 'convertfromraw', '-format', 'VDI', self.filename, destfile)
+        else:
+            run_cmd(qemu_img_path(), 'convert', '-O', format, self.filename, destfile)
         os.unlink(self.filename)
         self.filename = os.path.abspath(destfile)
         return destfile
@@ -290,7 +293,7 @@ class Filesystem(object):
             self.uuid = run_cmd('vol_id', '--uuid', self.filename).rstrip()
 
     def mkfs_fstype(self):
-        if self.vm.suite in ['dapper', 'edgy', 'feisty', 'gutsy']:
+        if self.vm.suite in ['dapper', 'edgy', 'feisty', 'gutsy', 'etch']:
             logging.debug('%s: 128 bit inode' % self.vm.suite)
             return { TYPE_EXT2: ['mkfs.ext2', '-F'], TYPE_EXT3: ['mkfs.ext3', '-I 128', '-F'], TYPE_XFS: ['mkfs.xfs'], TYPE_SWAP: ['mkswap'] }[self.type]
         else:
@@ -426,3 +429,10 @@ def qemu_img_path():
             path = '%s%s%s' % (dir, os.path.sep, exe)
             if os.access(path, os.X_OK):
                 return path
+
+def vbox_manager_path():
+    exe = 'VBoxManage'
+    for dir in os.environ['PATH'].split(os.path.pathsep):
+        path = '%s%s%s' % (dir, os.path.sep, exe)
+        if os.access(path, os.X_OK):
+            return path
diff --git a/VMBuilder/distro.py b/VMBuilder/distro.py
index b88c029..0c62a29 100644
--- a/VMBuilder/distro.py
+++ b/VMBuilder/distro.py
@@ -32,3 +32,6 @@ class Distro(VMBuilder.plugins.Plugin):
 
     def post_mount(self, fs):
         """Called each time a filesystem is mounted to let the distro add things to the filesystem"""
+
+    def install_vmbuilder_log(self, logfile):
+        """Let the distro copy the install logfile to the guest"""
diff --git a/VMBuilder/frontend.py b/VMBuilder/frontend.py
index 8af774b..4dad024 100644
--- a/VMBuilder/frontend.py
+++ b/VMBuilder/frontend.py
@@ -18,22 +18,20 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #    Frontend interface and classes
-
-import VMBuilder
-import optparse
+from VMBuilder.exception import VMBuilderException
 
 class Frontend(object):
     def __init__(self):
         self.settings = []
 
-    def setting_group(self, help=None):
-        return self.SettingsGroup(help)
+    def setting_group(self, setting_help=None):
+        return self.SettingsGroup(setting_help)
     
     def add_setting_group(self, group):
         self.settings.append(group)
 
     def add_setting(self, **kwargs):
-        self.settings.append(Setting(**kwargs))
+        self.settings.append(self.Setting(**kwargs))
 
     setting_types =  ['store', 'store']
     class Setting(object):
@@ -42,8 +40,8 @@ class Frontend(object):
             self.longarg = kwargs.get('shortarg', None)
             self.default = kwargs.get('default', None)
             self.help = kwargs.get('help', None)
-            type = kwargs.get('type', 'store')
-            if type not in setting_types:
+            store_type = kwargs.get('type', 'store')
+            if store_type not in Frontend.setting_types:
                 raise VMBuilderException("Invalid option type: %s" % type)
 
     class SettingsGroup(Setting):
diff --git a/VMBuilder/hypervisor.py b/VMBuilder/hypervisor.py
index cd0dfe2..6a104a6 100644
--- a/VMBuilder/hypervisor.py
+++ b/VMBuilder/hypervisor.py
@@ -19,12 +19,12 @@
 #
 #    Hypervisor super class
 
-import VMBuilder.plugins
+from VMBuilder import Plugin
 
 STORAGE_DISK_IMAGE = 0
 STORAGE_FS_IMAGE = 1
 
-class Hypervisor(VMBuilder.plugins.Plugin):
+class Hypervisor(Plugin):
     def finalize(self):
         raise NotImplemented('Hypervisor subclasses need to implement the finalize method')
 
diff --git a/VMBuilder/log.py b/VMBuilder/log.py
index fb2c53a..4551cbe 100644
--- a/VMBuilder/log.py
+++ b/VMBuilder/log.py
@@ -20,14 +20,25 @@
 #    Logging
 
 import logging
+import os
+import tempfile
 
-FORMAT='%(asctime)s %(levelname)-8s %(message)s'
-logging.basicConfig(format=FORMAT, level=logging.INFO)
+format = '%(asctime)s %(levelname)-8s: %(message)s'
+
+fd, logfile = tempfile.mkstemp()
+
+# Log everything to the logfile
+logging.basicConfig(format=format, level=logging.DEBUG, datefmt='%Y-%m-%d %H:%M', stream=os.fdopen(fd, 'a+'), filemode='w')
+
+console = logging.StreamHandler()
+console.setLevel(logging.INFO)
+console.setFormatter(logging.Formatter(format))
+logging.getLogger('').addHandler(console)
 
 def set_verbosity(option, opt_str, value, parser):
     if opt_str == '--debug':
-        logging.getLogger().setLevel(logging.DEBUG)
+        console.setLevel(logging.DEBUG)
     elif opt_str == '--verbose':
-        logging.getLogger().setLevel(logging.INFO)
+        console.setLevel(logging.INFO)
     elif opt_str == '--quiet':
-        logging.getLogger().setLevel(logging.CRITICAL)
+        console.setLevel(logging.CRITICAL)
diff --git a/VMBuilder/plugins/__init__.py b/VMBuilder/plugins/__init__.py
index c938e1c..67ef9cf 100644
--- a/VMBuilder/plugins/__init__.py
+++ b/VMBuilder/plugins/__init__.py
@@ -20,6 +20,7 @@
 import os
 import VMBuilder
 from VMBuilder.util import run_cmd
+from VMBuilder.exception import VMBuilderException
 
 def load_plugins():
     for plugin in find_plugins():
diff --git a/VMBuilder/plugins/cli/__init__.py b/VMBuilder/plugins/cli/__init__.py
index 30f0602..8601b08 100644
--- a/VMBuilder/plugins/cli/__init__.py
+++ b/VMBuilder/plugins/cli/__init__.py
@@ -1,5 +1,6 @@
 #    Uncomplicated VM Builder
 #    Copyright (C) 2007-2008 Canonical Ltd.
+#    Copyright (C) 2009      Bernd Zeimetz <bzed at debian.org>
 #    
 #    See AUTHORS for list of contributors
 #
@@ -23,13 +24,13 @@ import optparse
 import sys
 import textwrap
 import VMBuilder
-import VMBuilder.hypervisor
+from VMBuilder.disk import parse_size
 _ = gettext
 
 
 class CLI(VMBuilder.Frontend):
     arg = 'cli'
-       
+    
     def run(self):
         try:
             next = False
@@ -42,15 +43,16 @@ class CLI(VMBuilder.Frontend):
                     break
 
             vm = VMBuilder.VM(conf)
-            vm.register_setting('--rootsize', metavar='SIZE', type='int', default=4096, help='Size (in MB) of the root filesystem [default: %default]')
-            vm.register_setting('--optsize', metavar='SIZE', type='int', default=0, help='Size (in MB) of the /opt filesystem. If not set, no /opt filesystem will be added.')
-            vm.register_setting('--swapsize', metavar='SIZE', type='int', default=1024, help='Size (in MB) of the swap partition [default: %default]')
+            vm.register_setting('--version', action='callback', callback=self.versioninfo, callback_kwargs={ 'vm' : vm }, help='Show version information')
+            vm.register_setting('--rootsize', metavar='SIZE', default=4096, help='Size (in MB) of the root filesystem [default: %default]')
+            vm.register_setting('--optsize', metavar='SIZE', default=0, help='Size (in MB) of the /opt filesystem. If not set, no /opt filesystem will be added.')
+            vm.register_setting('--swapsize', metavar='SIZE', default=1024, help='Size (in MB) of the swap partition [default: %default]')
             vm.register_setting('--raw', metavar='PATH', type='string', help="Specify a file (or block device) to as first disk image.")
             vm.register_setting('--part', metavar='PATH', type='string', help="Allows to specify a partition table in PATH each line of partfile should specify (root first): \n    mountpoint size \none per line, separated by space, where size is in megabytes. You can have up to 4 virtual disks, a new disk starts on a line containing only '---'. ie: \n    root 2000 \n    /boot 512 \n    swap 1000 \n    --- \n    /var 8000 \n    /var/log 2000")
             self.set_usage(vm)
 
             vm.optparser.disable_interspersed_args()
-            (foo, args) = vm.optparser.parse_args()
+            args = vm.optparser.parse_args()[1]
             self.handle_args(vm, args)
             vm.optparser.enable_interspersed_args()
 
@@ -68,6 +70,10 @@ class CLI(VMBuilder.Frontend):
         except VMBuilder.VMBuilderUserError, e:
             print >> sys.stderr, e
 
+    def versioninfo(self, option, opt, value, parser, vm=None):
+        print '%(major)d.%(minor)d.r%(revno)d' % vm.get_version_info()
+        sys.exit(0)
+
     def set_usage(self, vm):
         vm.optparser.set_usage('%prog hypervisor distro [options]')
         vm.optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('distro', vm.distro_help))
@@ -80,11 +86,14 @@ class CLI(VMBuilder.Frontend):
 
     def set_disk_layout(self, vm):
         if not vm.part:
+            vm.rootsize = parse_size(vm.rootsize)
+            vm.swapsize = parse_size(vm.swapsize)
+            vm.optsize = parse_size(vm.optsize)
             if vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
                 vm.add_filesystem(size='%dM' % vm.rootsize, type='ext3', mntpnt='/')
                 vm.add_filesystem(size='%dM' % vm.swapsize, type='swap', mntpnt=None)
                 if vm.optsize > 0:
-                    vm.add_filesystem(size='%dM' % optsize, type='ext3', mntpnt='/opt')
+                    vm.add_filesystem(size='%dM' % vm.optsize, type='ext3', mntpnt='/opt')
             else:
                 if vm.raw:
                     disk = vm.add_disk(filename=vm.raw, preallocated=True)
@@ -152,22 +161,38 @@ class CLI(VMBuilder.Frontend):
                 disk.add_part(offset, int(pair[1]), 'ext3', pair[0])
             offset += int(pair[1])
 
-class UVB(CLI):
-    arg = 'ubuntu-vm-builder'
+class VB(CLI):
+    arg = 'vb'
+    suites = []
+    distro = ''
 
     def set_usage(self, vm):
         vm.optparser.set_usage('%prog hypervisor suite [options]')
         vm.optparser.arg_help = (('hypervisor', vm.hypervisor_help), ('suite', self.suite_help))
 
     def suite_help(self):
-        return 'Suite. Valid options: %s' % " ".join(VMBuilder.plugins.ubuntu.distro.Ubuntu.suites)
+        return 'Suite. Valid options: %s' % " ".join(self.suites)
 
     def handle_args(self, vm, args):
         if len(args) < 2:
             vm.optparser.error("You need to specify at least the hypervisor type and the suite")
         vm.set_hypervisor(args[0])
-        vm.set_distro('ubuntu')
+        vm.set_distro(self.distro)
         vm.suite = args[1]
  
+class UVB(VB):
+    arg = 'ubuntu-vm-builder'
+    import VMBuilder.plugins.ubuntu as ubuntu
+    suites = ubuntu.distro.Ubuntu.suites
+    distro = 'ubuntu'
+
+class DVB(VB):
+    arg = 'debian-vm-builder'
+    import VMBuilder.plugins.debian as debian
+    suites = debian.distro.Debian.suites
+    distro = 'debian'
+
+
 VMBuilder.register_frontend(CLI)
 VMBuilder.register_frontend(UVB)
+VMBuilder.register_frontend(DVB)
diff --git a/VMBuilder/plugins/ubuntu/__init__.py b/VMBuilder/plugins/debian/__init__.py
similarity index 92%
copy from VMBuilder/plugins/ubuntu/__init__.py
copy to VMBuilder/plugins/debian/__init__.py
index 77e89ea..6a3b438 100644
--- a/VMBuilder/plugins/ubuntu/__init__.py
+++ b/VMBuilder/plugins/debian/__init__.py
@@ -1,6 +1,7 @@
 #
 #    Uncomplicated VM Builder
 #    Copyright (C) 2007-2008 Canonical Ltd.
+#    Copyright (C) 2009      Bernd Zeimetz <bzed at debian.org>
 #    
 #    See AUTHORS for list of contributors
 #
diff --git a/VMBuilder/plugins/ubuntu/distro.py b/VMBuilder/plugins/debian/distro.py
similarity index 73%
copy from VMBuilder/plugins/ubuntu/distro.py
copy to VMBuilder/plugins/debian/distro.py
index e24b1e2..199994a 100644
--- a/VMBuilder/plugins/ubuntu/distro.py
+++ b/VMBuilder/plugins/debian/distro.py
@@ -1,6 +1,7 @@
 #
 #    Uncomplicated VM Builder
 #    Copyright (C) 2007-2008 Canonical Ltd.
+#    Copyright (C) 2009      Bernd Zeimetz <bzed at debian.org>
 #    
 #    See AUTHORS for list of contributors
 #
@@ -17,24 +18,26 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
+import logging
+import os
+import socket
+import types
 import VMBuilder
 from   VMBuilder           import register_distro, Distro
 from   VMBuilder.util      import run_cmd
-from   VMBuilder.exception import VMBuilderUserError
-import socket
-import logging
-import types
-import os
+from   VMBuilder.exception import VMBuilderUserError, VMBuilderException
 
-class Ubuntu(Distro):
-    name = 'Ubuntu'
-    arg = 'ubuntu'
-    suites = ['dapper', 'gutsy', 'hardy', 'intrepid', 'jaunty']
+class Debian(Distro):
+    name = 'Debian'
+    arg = 'debian'
+    suites = ['etch']
     
     # Maps host arch to valid guest archs
-    valid_archs = { 'amd64' : ['amd64', 'i386', 'lpia' ],
-                    'i386' : [ 'i386', 'lpia' ],
-                    'lpia' : [ 'i386', 'lpia' ] }
+    # FIXME: Running a amd64 kernel with an i386 userspace allows us to run
+    #        amd64 guests
+     
+    valid_archs = { 'amd64' : ['amd64', 'i386' ],
+                    'i386' : [ 'i386' ] }
 
     xen_kernel = ''
 
@@ -46,27 +49,31 @@ class Ubuntu(Distro):
 
         group = self.vm.setting_group('General OS options')
         self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip()
-        group.add_option('-a', '--arch', default=self.host_arch, help='Specify the target architecture.  Valid options: amd64 i386 lpia (defaults to host arch)')
-        group.add_option('--hostname', default='ubuntu', help='Set NAME as the hostname of the guest. Default: ubuntu. Also uses this name as the VM name.')
+        group.add_option('-a', '--arch', default=self.host_arch, help='Specify the target architecture.  Valid options: amd64 i386 (defaults to host arch)')
+        group.add_option('--hostname', default='debian', help='Set NAME as the hostname of the guest. Default: debian. Also uses this name as the VM name.')
         self.vm.register_setting_group(group)
 
+        # FIXME: Add Debian ports 
+        # FIXME: Add volatile
         group = self.vm.setting_group('Installation options')
-        group.add_option('--suite', default='jaunty', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
+        group.add_option('--suite', default='etch', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
         group.add_option('--flavour', '--kernel-flavour', help='Kernel flavour to use. Default and valid options depend on architecture and suite')
+        group.add_option('--variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
         group.add_option('--iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm.  This requires suite and kernel parameter to match what is available on the iso, obviously.')
-        group.add_option('--mirror', metavar='URL', help='Use Ubuntu mirror at URL instead of the default, which is http://archive.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
-        group.add_option('--install-mirror', metavar='URL', help='Use Ubuntu mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
-        group.add_option('--security-mirror', metavar='URL', help='Use Ubuntu security mirror at URL instead of the default, which is http://security.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise.')
+        group.add_option('--mirror', metavar='URL', help='Use Debian mirror at URL instead of the default, which is http://ftp.debian.org for official arches.')
+        group.add_option('--proxy', metavar='URL', help='Use proxy at URL for cached packages')
+        group.add_option('--install-mirror', metavar='URL', help='Use Debian mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
+        group.add_option('--security-mirror', metavar='URL', help='Use Debian security mirror at URL instead of the default, which is http://security.debian.org/debian-security/ for official arches.')
         group.add_option('--install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
-        group.add_option('--components', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
-        group.add_option('--ppa', metavar='PPA', action='append', help='Add ppa belonging to PPA to the vm\'s sources.list.')
+        group.add_option('--components', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,contrib,non-free).')
         group.add_option('--lang', metavar='LANG', default=self.get_locale(), help='Set the locale to LANG [default: %default]')
         self.vm.register_setting_group(group)
 
         group = self.vm.setting_group('Settings for the initial user')
-        group.add_option('--user', default='ubuntu', help='Username of initial user [default: %default]')
-        group.add_option('--name', default='Ubuntu', help='Full name of initial user [default: %default]')
-        group.add_option('--pass', default='ubuntu', help='Password of initial user [default: %default]')
+        group.add_option('--user', default='debian', help='Username of initial user [default: %default]')
+        group.add_option('--name', default='Debian', help='Full name of initial user [default: %default]')
+        group.add_option('--pass', default='debian', help='Password of initial user [default: %default]')
+        group.add_option('--rootpass', help='Initial root password (WARNING: this has strong security implications).')
         self.vm.register_setting_group(group)
 
         group = self.vm.setting_group('Other options')
@@ -76,27 +83,24 @@ class Ubuntu(Distro):
 
     def set_defaults(self):
         if not self.vm.mirror:
-            if self.vm.arch == 'lpia':
-                self.vm.mirror = 'http://ports.ubuntu.com/ubuntu-ports'
-            else:
-                self.vm.mirror = 'http://archive.ubuntu.com/ubuntu'
+            #if self.vm.arch == 'lpia':
+            #    self.vm.mirror = 'http://ports.ubuntu.com/ubuntu-ports'
+            #else:
+            self.vm.mirror = 'http://ftp.debian.org/debian'
 
         if not self.vm.security_mirror:
-            if self.vm.arch == 'lpia':
-                self.vm.security_mirror = 'http://ports.ubuntu.com/ubuntu-ports'
-            else:
-                self.vm.security_mirror = 'http://security.ubuntu.com/ubuntu'
+            #if self.vm.arch == 'lpia':
+            #    self.vm.security_mirror = 'http://ports.ubuntu.com/ubuntu-ports'
+            #else:
+            self.vm.security_mirror = 'http://security.debian.org/debian-security'
 
         if not self.vm.components:
-            self.vm.components = ['main', 'restricted', 'universe']
+            self.vm.components = ['main']
         else:
             self.vm.components = self.vm.components.split(',')
 
     def get_locale(self):
-        try:
-            return os.environ['LANG']
-        except:
-            return None
+        return os.getenv('LANG')
 
     def preflight_check(self):
         """While not all of these are strictly checks, their failure would inevitably
@@ -106,7 +110,7 @@ class Ubuntu(Distro):
         if not self.vm.suite in self.suites:
             raise VMBuilderUserError('Invalid suite. Valid suites are: %s' % ' '.join(self.suites))
         
-        modname = 'VMBuilder.plugins.ubuntu.%s' % (self.vm.suite, )
+        modname = 'VMBuilder.plugins.debian.%s' % (self.vm.suite, )
         mod = __import__(modname, fromlist=[self.vm.suite])
         self.suite = getattr(mod, self.vm.suite.capitalize())(self.vm)
 
@@ -126,10 +130,20 @@ class Ubuntu(Distro):
 
         self.vm.virtio_net = self.use_virtio_net()
 
+        if self.vm.lang:
+            try:
+                run_cmd('locale-gen', '%s' % self.vm.lang)
+            except VMBuilderException, e:
+                msg = "locale-gen does not recognize your locale '%s'" % self.vm.lang
+                raise VMBuilderUserError(msg)
+
     def install(self, destdir):
         self.destdir = destdir
         self.suite.install(destdir)
 
+    def install_vmbuilder_log(self, logfile, rootdir):
+        self.suite.install_vmbuilder_log(logfile, rootdir)
+
     def post_mount(self, fs):
         self.suite.post_mount(fs)
 
@@ -179,4 +193,4 @@ EOT''')
         return path
 
 
-register_distro(Ubuntu)
+register_distro(Debian)
diff --git a/VMBuilder/plugins/ubuntu/dapper.py b/VMBuilder/plugins/debian/etch.py
similarity index 74%
copy from VMBuilder/plugins/ubuntu/dapper.py
copy to VMBuilder/plugins/debian/etch.py
index 91cd351..3f61faf 100644
--- a/VMBuilder/plugins/ubuntu/dapper.py
+++ b/VMBuilder/plugins/debian/etch.py
@@ -1,6 +1,7 @@
 #
 #    Uncomplicated VM Builder
 #    Copyright (C) 2007-2008 Canonical Ltd.
+#    Copyright (C) 2009      Bernd Zeimetz <bzed at debian.org>
 #    
 #    See AUTHORS for list of contributors
 #
@@ -20,21 +21,28 @@
 import glob
 import logging
 import os
-import suite
 import shutil
 import socket
+import tempfile
 import VMBuilder
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 
-class Dapper(suite.Suite):
-    updategrub = "/sbin/update-grub"
-    grubroot = "/lib/grub"
-    valid_flavours = { 'i386' :  ['386', '686', '686-smp', 'k7', 'k7-smp', 'server', 'server-bigiron'],
-                       'amd64' : ['amd64-generic', 'amd64-k8', 'amd64-k8-smp', 'amd64-server', 'amd64-xeon']}
-    default_flavour = { 'i386' : 'server', 'amd64' : 'amd64-server' }
-    disk_prefix = 'hd'
-    xen_kernel_flavour = None
+class Etch(suite.Suite):
+    updategrub = "/usr/sbin/update-grub"
+    grubroot = "/usr/lib/grub"
+
+    valid_flavours = { 'i386' :  ['486', '686', '686-bigmem',
+                                  '686-bigmem-etchnhalf', '686-etchnhalf',
+                                  '686-smp', 'vserver-686'],
+                       'amd64' : ['amd64', 'amd64-etchnhalf', 'amd64-generic',
+                                  'amd64-k8', 'amd64-k8-smp', 'vserver-amd64',
+                                  'vserver-amd64-k8-smp']}
+    
+    default_flavour = { 'i386' : '686-etchnhalf', 'amd64' : 'amd64-etchnhalf' }
+    disk_prefix = 'sd'
+    xen_kernel_flavour = 'xen'
     virtio_net = False
 
     def check_kernel_flavour(self, arch, flavour):
@@ -52,6 +60,9 @@ class Dapper(suite.Suite):
         logging.debug("Setting up sources.list")
         self.install_sources_list()
 
+        logging.debug("Setting up apt proxy")
+        self.install_apt_proxy()
+
         logging.debug("Installing fstab")
         self.install_fstab()
 
@@ -78,15 +89,18 @@ class Dapper(suite.Suite):
             logging.debug("Creating device.map")
             self.install_device_map()
 
-        logging.debug("Installing ssh keys")
-        self.install_authorized_keys()
-
         logging.debug("Installing extra packages")
         self.install_extras()
 
         logging.debug("Creating initial user")
         self.create_initial_user()
 
+        logging.debug("Installing ssh keys")
+        self.install_authorized_keys()
+
+        logging.debug("Installing locales")
+        self.install_locales()
+
         logging.debug("Copy host settings")
         self.copy_settings()
 
@@ -103,7 +117,8 @@ class Dapper(suite.Suite):
         self.unprevent_daemons_starting()
 
     def update(self):
-        self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade')
+        self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade',
+                           env={ 'DEBIAN_FRONTEND' : 'noninteractive' })
         
     def install_authorized_keys(self):
         if self.vm.ssh_key:
@@ -114,14 +129,25 @@ class Dapper(suite.Suite):
             os.mkdir('%s/home/%s/.ssh' % (self.destdir, self.vm.user), 0700)
             shutil.copy(self.vm.ssh_user_key, '%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user))
             os.chmod('%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user), 0644)
+            self.run_in_target('chown', '-R', '%s:%s' % (self.vm.user,)*2, '/home/%s/.ssh/' % (self.vm.user)) 
+
         if self.vm.ssh_user_key or self.vm.ssh_key:
             if not self.vm.addpkg:
                 self.vm.addpkg = []
             self.vm.addpkg += ['openssh-server']
 
+    def update_passwords(self):
+        # Set the user password, using md5
+        self.run_in_target('chpasswd', '-m', stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))))
+
+        # Lock root account only if we didn't set the root password
+        if self.vm.rootpass:
+            self.run_in_target('chpasswd', '-m', stdin=('%s:%s\n' % ('root', self.vm.rootpass)))
+        else:
+            self.run_in_target('chpasswd', '-e', stdin='root:!\n')
+
     def create_initial_user(self):
         self.run_in_target('adduser', '--disabled-password', '--gecos', self.vm.name, self.vm.user)
-        self.run_in_target('chpasswd', stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))))
         self.run_in_target('addgroup', '--system', 'admin')
         self.run_in_target('adduser', self.vm.user, 'admin')
 
@@ -129,11 +155,10 @@ class Dapper(suite.Suite):
         for group in ['adm', 'audio', 'cdrom', 'dialout', 'floppy', 'video', 'plugdev', 'dip', 'netdev', 'powerdev', 'lpadmin', 'scanner']:
             self.run_in_target('adduser', self.vm.user, group, ignore_fail=True)
 
-        # Lock root account
-        self.run_in_target('chpasswd', '-e', stdin='root:!\n')
+        self.update_passwords()
 
     def kernel_name(self):
-        return 'linux-image-%s' % (self.vm.flavour or self.default_flavour[self.vm.arch],)
+        return 'linux-image-2.6-%s' % (self.vm.flavour or self.default_flavour[self.vm.arch],)
 
     def config_network(self):
         self.vm.install_file('/etc/hostname', self.vm.hostname)
@@ -176,7 +201,7 @@ class Dapper(suite.Suite):
 
     def mangle_grub_menu_lst(self):
         bootdev = disk.bootpart(self.vm.disks)
-        run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=\/dev\/hd%s%d\\2/g' % (bootdev.disk.devletters(), bootdev.get_index()+1), '%s/boot/grub/menu.lst' % self.destdir)
+        run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
         run_cmd('sed', '-ie', 's/^# groot.*/# groot %s/g' % bootdev.get_grub_id(), '%s/boot/grub/menu.lst' % self.destdir)
         run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
 
@@ -193,22 +218,32 @@ class Dapper(suite.Suite):
         # final vm is going to be on).
         self.run_in_target('apt-get', 'update', ignore_fail=final)
 
+    def install_apt_proxy(self):
+        if self.vm.proxy is not None:
+            self.vm.install_file('/etc/apt/apt.conf', '// Proxy added by vmbuilder\nAcquire::http { Proxy "%s"; };' % self.vm.proxy)
+
     def install_fstab(self):
         if self.vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
-            self.install_from_template('/etc/fstab', 'dapper_fstab_fsimage', { 'fss' : disk.get_ordered_filesystems(self.vm), 'prefix' : self.disk_prefix })
+            self.install_from_template('/etc/fstab', 'etch_fstab_fsimage', { 'fss' : disk.get_ordered_filesystems(self.vm), 'prefix' : self.disk_prefix })
         else:
-            self.install_from_template('/etc/fstab', 'dapper_fstab', { 'parts' : disk.get_ordered_partitions(self.vm.disks), 'prefix' : self.disk_prefix })
+            self.install_from_template('/etc/fstab', 'etch_fstab', { 'parts' : disk.get_ordered_partitions(self.vm.disks), 'prefix' : self.disk_prefix })
 
     def install_device_map(self):
         self.install_from_template('/boot/grub/device.map', 'devicemap', { 'prefix' : self.disk_prefix })
 
     def debootstrap(self):
-        cmd = ['/usr/sbin/debootstrap', '--arch=%s' % self.vm.arch, self.vm.suite, self.destdir, self.debootstrap_mirror()]
-        run_cmd(*cmd)
+        cmd = ['/usr/sbin/debootstrap', '--arch=%s' % self.vm.arch]
+        if self.vm.variant:
+            cmd += ['--variant=%s' % self.vm.variant]
+        cmd += [self.vm.suite, self.destdir, self.debootstrap_mirror()]
+        kwargs = { 'env' : { 'DEBIAN_FRONTEND' : 'noninteractive' } }
+        if self.vm.proxy:
+            kwargs['env']['http_proxy'] = self.vm.proxy
+        run_cmd(*cmd, **kwargs)
     
     def debootstrap_mirror(self):
         if self.vm.iso:
-            os.mkdir(isodir)
+            isodir = tempfile.mkdtemp()
             self.vm.add_clean_cb(lambda:os.rmdir(isodir))
             run_cmd('mount', '-o', 'loop', '-t', 'iso9660', self.vm.iso, isodir)
             self.vm.add_clean_cmd('umount', isodir)
@@ -247,6 +282,10 @@ class Dapper(suite.Suite):
         self.run_in_target('apt-get', '--force-yes', '-y', 'install', 'grub')
         run_cmd('cp', '-a', '%s%s/%s/' % (self.destdir, self.grubroot, self.vm.arch == 'amd64' and 'x86_64-pc' or 'i386-pc'), '%s/boot/grub' % self.destdir) 
 
+
+    def install_locales(self):
+        self.run_in_target('apt-get', '--force-yes', '-y', 'install', 'locales')
+
     def create_devices(self):
         import VMBuilder.plugins.xen
 
@@ -264,6 +303,7 @@ class Dapper(suite.Suite):
         self.vm.distro.run_in_target(*args, **kwargs)
 
     def copy_to_target(self, infile, destpath):
+        logging.debug("Copying %s on host to %s in guest" % (infile, destpath))
         dir = '%s/%s' % (self.destdir, os.path.dirname(destpath))
         if not os.path.isdir(dir):
             os.makedirs(dir)
@@ -279,12 +319,24 @@ class Dapper(suite.Suite):
             logging.debug("Creating /var/lock in root filesystem")
             os.makedirs('%s/var/lock' % fs.mntpath)
 
+
     def copy_settings(self):
         self.copy_to_target('/etc/default/locale', '/etc/default/locale')
+        csdir = '%s/etc/console-setup' % self.destdir
+        have_cs = os.path.isdir(csdir)
+        if have_cs:
+            shutil.rmtree(csdir)
+            self.copy_to_target('/etc/console-setup', '/etc/console-setup')
+            self.copy_to_target('/etc/default/console-setup', '/etc/default/console-setup')
         self.copy_to_target('/etc/timezone', '/etc/timezone')
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'libc6')
-        self.run_in_target('locale-gen', 'en_US')
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'tzdata')
+        self.run_in_target('locale-gen', 'en_US.UTF-8')
         if self.vm.lang:
             self.run_in_target('locale-gen', self.vm.lang)
             self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.vm.lang })
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'locales')
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
+        if have_cs:
+            self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'console-setup')
+
+    def install_vmbuilder_log(self, logfile, rootdir):
+        shutil.copy(logfile, '%s/var/log/vmbuilder-install.log' % (rootdir,))
diff --git a/VMBuilder/plugins/ubuntu/templates/devicemap.tmpl b/VMBuilder/plugins/debian/templates/devicemap.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/devicemap.tmpl
copy to VMBuilder/plugins/debian/templates/devicemap.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/etc_hosts.tmpl b/VMBuilder/plugins/debian/templates/etc_hosts.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/etc_hosts.tmpl
copy to VMBuilder/plugins/debian/templates/etc_hosts.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl b/VMBuilder/plugins/debian/templates/etch_fstab.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/dapper_fstab.tmpl
copy to VMBuilder/plugins/debian/templates/etch_fstab.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/dapper_fstab_fsimage.tmpl b/VMBuilder/plugins/debian/templates/etch_fstab_fsimage.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/dapper_fstab_fsimage.tmpl
copy to VMBuilder/plugins/debian/templates/etch_fstab_fsimage.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/interfaces.tmpl b/VMBuilder/plugins/debian/templates/interfaces.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/interfaces.tmpl
copy to VMBuilder/plugins/debian/templates/interfaces.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/kernelimg.tmpl b/VMBuilder/plugins/debian/templates/kernelimg.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/kernelimg.tmpl
copy to VMBuilder/plugins/debian/templates/kernelimg.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/locale.tmpl b/VMBuilder/plugins/debian/templates/locale.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/locale.tmpl
copy to VMBuilder/plugins/debian/templates/locale.tmpl
diff --git a/VMBuilder/plugins/ubuntu/templates/nostart-policy-rc.d.tmpl b/VMBuilder/plugins/debian/templates/nostart-policy-rc.d.tmpl
similarity index 100%
copy from VMBuilder/plugins/ubuntu/templates/nostart-policy-rc.d.tmpl
copy to VMBuilder/plugins/debian/templates/nostart-policy-rc.d.tmpl
diff --git a/VMBuilder/plugins/debian/templates/sources.list.tmpl b/VMBuilder/plugins/debian/templates/sources.list.tmpl
new file mode 100644
index 0000000..4e86dd1
--- /dev/null
+++ b/VMBuilder/plugins/debian/templates/sources.list.tmpl
@@ -0,0 +1,6 @@
+deb $mirror $suite #slurp
+#echo ' '.join($components)
+
+deb $security_mirror $suite/updates #slurp
+#echo ' '.join($components)
+
diff --git a/VMBuilder/plugins/debian/templates/sudoers.tmpl b/VMBuilder/plugins/debian/templates/sudoers.tmpl
new file mode 100644
index 0000000..c57a3ef
--- /dev/null
+++ b/VMBuilder/plugins/debian/templates/sudoers.tmpl
@@ -0,0 +1,33 @@
+# sudoers file.
+#
+# This file MUST be edited with the 'visudo' command as root.
+# Failure to use 'visudo' may result in syntax or file permission errors
+# that prevent sudo from running.
+#
+# See the sudoers man page for the details on how to write a sudoers file.
+#
+
+# Defaults syslog=auth, secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin"
+
+# Host alias specification
+
+# User alias specification
+
+# Cmnd alias specification
+
+# Defaults specification
+
+# Runas alias specification
+
+# User privilege specification
+root	ALL=(ALL) ALL
+
+# Uncomment to allow people in group wheel to run all commands
+# %wheel	ALL=(ALL) ALL
+
+# Same thing without a password
+# %wheel	ALL=(ALL) NOPASSWD: ALL
+
+# Samples
+# %users  ALL=/sbin/mount /cdrom,/sbin/umount /cdrom
+# %users  localhost=/sbin/shutdown -h now
diff --git a/VMBuilder/plugins/ec2/__init__.py b/VMBuilder/plugins/ec2/__init__.py
index 09593b2..64f0ba8 100644
--- a/VMBuilder/plugins/ec2/__init__.py
+++ b/VMBuilder/plugins/ec2/__init__.py
@@ -20,6 +20,7 @@
 from VMBuilder import register_plugin, Plugin, VMBuilderUserError
 from VMBuilder.util import run_cmd
 import logging
+import os
 
 class EC2(Plugin):
     name = 'EC2 integration'
@@ -49,10 +50,16 @@ class EC2(Plugin):
             raise VMBuilderUserError('When building for EC2 you must supply the name for the image.')
 
         if not self.vm.ec2_cert:
-            raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded public key certificate')
+            if "EC2_CERT" in os.environ:
+                self.vm.ec2_cert = os.environ["EC2_CERT"]
+            else:
+                raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded public key certificate')
 
         if not self.vm.ec2_key:
-            raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded private key file')
+            if "EC2_PRIVATE_KEY" in os.environ:
+                self.vm.ec2_key = os.environ["EC2_PRIVATE_KEY"]
+            else:
+                raise VMBuilderUserError('When building for EC2 you must provide your PEM encoded private key file')
 
         if not self.vm.ec2_user:
             raise VMBuilderUserError('When building for EC2 you must provide your EC2 user ID (your AWS account number, not your AWS access key ID)')
@@ -108,10 +115,12 @@ class EC2(Plugin):
         if not self.vm.ec2:
             return False
 
+        logging.info("Building EC2 bundle")
         bundle_cmdline = ['ec2-bundle-image', '--image', self.vm.filesystems[0].filename, '--cert', self.vm.ec2_cert, '--privatekey', self.vm.ec2_key, '--user', self.vm.ec2_user, '--prefix', self.vm.ec2_name, '-r', ['i386', 'x86_64'][self.vm.arch == 'amd64'], '-d', self.vm.workdir, '--kernel', self.vm.ec2_kernel, '--ramdisk', self.vm.ec2_ramdisk]
 
         run_cmd(*bundle_cmdline)
 
+        logging.info("Uploading EC2 bundle")
         upload_cmdline = ['ec2-upload-bundle', '--retry', '--manifest', '%s/%s.manifest.xml' % (self.vm.workdir, self.vm.ec2_name), '--bucket', self.vm.ec2_bucket, '--access-key', self.vm.ec2_access_key, '--secret-key', self.vm.ec2_secret_key]
         run_cmd(*upload_cmdline)
 
diff --git a/VMBuilder/plugins/ubuntu/dapper.py b/VMBuilder/plugins/ubuntu/dapper.py
index 91cd351..60b0b6a 100644
--- a/VMBuilder/plugins/ubuntu/dapper.py
+++ b/VMBuilder/plugins/ubuntu/dapper.py
@@ -20,11 +20,12 @@
 import glob
 import logging
 import os
-import suite
 import shutil
 import socket
+import tempfile
 import VMBuilder
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 
 class Dapper(suite.Suite):
@@ -52,6 +53,9 @@ class Dapper(suite.Suite):
         logging.debug("Setting up sources.list")
         self.install_sources_list()
 
+        logging.debug("Setting up apt proxy")
+        self.install_apt_proxy()
+
         logging.debug("Installing fstab")
         self.install_fstab()
 
@@ -78,15 +82,15 @@ class Dapper(suite.Suite):
             logging.debug("Creating device.map")
             self.install_device_map()
 
-        logging.debug("Installing ssh keys")
-        self.install_authorized_keys()
-
         logging.debug("Installing extra packages")
         self.install_extras()
 
         logging.debug("Creating initial user")
         self.create_initial_user()
 
+        logging.debug("Installing ssh keys")
+        self.install_authorized_keys()
+
         logging.debug("Copy host settings")
         self.copy_settings()
 
@@ -103,7 +107,8 @@ class Dapper(suite.Suite):
         self.unprevent_daemons_starting()
 
     def update(self):
-        self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade')
+        self.run_in_target('apt-get', '-y', '--force-yes', 'dist-upgrade',
+                           env={ 'DEBIAN_FRONTEND' : 'noninteractive' })
         
     def install_authorized_keys(self):
         if self.vm.ssh_key:
@@ -114,14 +119,25 @@ class Dapper(suite.Suite):
             os.mkdir('%s/home/%s/.ssh' % (self.destdir, self.vm.user), 0700)
             shutil.copy(self.vm.ssh_user_key, '%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user))
             os.chmod('%s/home/%s/.ssh/authorized_keys' % (self.destdir, self.vm.user), 0644)
+            self.run_in_target('chown', '-R', '%s:%s' % (self.vm.user,)*2, '/home/%s/.ssh/' % (self.vm.user)) 
+
         if self.vm.ssh_user_key or self.vm.ssh_key:
             if not self.vm.addpkg:
                 self.vm.addpkg = []
             self.vm.addpkg += ['openssh-server']
 
+    def update_passwords(self):
+        # Set the user password, using md5
+        self.run_in_target('chpasswd', '-m', stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))))
+
+        # Lock root account only if we didn't set the root password
+        if self.vm.rootpass:
+            self.run_in_target('chpasswd', '-m', stdin=('%s:%s\n' % ('root', self.vm.rootpass)))
+        else:
+            self.run_in_target('chpasswd', '-e', stdin='root:!\n')
+
     def create_initial_user(self):
         self.run_in_target('adduser', '--disabled-password', '--gecos', self.vm.name, self.vm.user)
-        self.run_in_target('chpasswd', stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))))
         self.run_in_target('addgroup', '--system', 'admin')
         self.run_in_target('adduser', self.vm.user, 'admin')
 
@@ -129,8 +145,7 @@ class Dapper(suite.Suite):
         for group in ['adm', 'audio', 'cdrom', 'dialout', 'floppy', 'video', 'plugdev', 'dip', 'netdev', 'powerdev', 'lpadmin', 'scanner']:
             self.run_in_target('adduser', self.vm.user, group, ignore_fail=True)
 
-        # Lock root account
-        self.run_in_target('chpasswd', '-e', stdin='root:!\n')
+        self.update_passwords()
 
     def kernel_name(self):
         return 'linux-image-%s' % (self.vm.flavour or self.default_flavour[self.vm.arch],)
@@ -193,6 +208,10 @@ class Dapper(suite.Suite):
         # final vm is going to be on).
         self.run_in_target('apt-get', 'update', ignore_fail=final)
 
+    def install_apt_proxy(self):
+        if self.vm.proxy is not None:
+            self.vm.install_file('/etc/apt/apt.conf', '// Proxy added by vmbuilder\nAcquire::http { Proxy "%s"; };' % self.vm.proxy)
+
     def install_fstab(self):
         if self.vm.hypervisor.preferred_storage == VMBuilder.hypervisor.STORAGE_FS_IMAGE:
             self.install_from_template('/etc/fstab', 'dapper_fstab_fsimage', { 'fss' : disk.get_ordered_filesystems(self.vm), 'prefix' : self.disk_prefix })
@@ -203,12 +222,18 @@ class Dapper(suite.Suite):
         self.install_from_template('/boot/grub/device.map', 'devicemap', { 'prefix' : self.disk_prefix })
 
     def debootstrap(self):
-        cmd = ['/usr/sbin/debootstrap', '--arch=%s' % self.vm.arch, self.vm.suite, self.destdir, self.debootstrap_mirror()]
-        run_cmd(*cmd)
+        cmd = ['/usr/sbin/debootstrap', '--arch=%s' % self.vm.arch]
+        if self.vm.variant:
+            cmd += ['--variant=%s' % self.vm.variant]
+        cmd += [self.vm.suite, self.destdir, self.debootstrap_mirror()]
+        kwargs = { 'env' : { 'DEBIAN_FRONTEND' : 'noninteractive' } }
+        if self.vm.proxy:
+            kwargs['env']['http_proxy'] = self.vm.proxy
+        run_cmd(*cmd, **kwargs)
     
     def debootstrap_mirror(self):
         if self.vm.iso:
-            os.mkdir(isodir)
+            isodir = tempfile.mkdtemp()
             self.vm.add_clean_cb(lambda:os.rmdir(isodir))
             run_cmd('mount', '-o', 'loop', '-t', 'iso9660', self.vm.iso, isodir)
             self.vm.add_clean_cmd('umount', isodir)
@@ -264,6 +289,7 @@ class Dapper(suite.Suite):
         self.vm.distro.run_in_target(*args, **kwargs)
 
     def copy_to_target(self, infile, destpath):
+        logging.debug("Copying %s on host to %s in guest" % (infile, destpath))
         dir = '%s/%s' % (self.destdir, os.path.dirname(destpath))
         if not os.path.isdir(dir):
             os.makedirs(dir)
@@ -282,9 +308,13 @@ class Dapper(suite.Suite):
     def copy_settings(self):
         self.copy_to_target('/etc/default/locale', '/etc/default/locale')
         self.copy_to_target('/etc/timezone', '/etc/timezone')
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'libc6')
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'libc6')
         self.run_in_target('locale-gen', 'en_US')
         if self.vm.lang:
             self.run_in_target('locale-gen', self.vm.lang)
             self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.vm.lang })
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
         self.run_in_target('dpkg-reconfigure', '-pcritical', 'locales')
+
+    def install_vmbuilder_log(self, logfile, rootdir):
+        shutil.copy(logfile, '%s/var/log/vmbuilder-install.log' % (rootdir,))
diff --git a/VMBuilder/plugins/ubuntu/distro.py b/VMBuilder/plugins/ubuntu/distro.py
index e24b1e2..bb47ff3 100644
--- a/VMBuilder/plugins/ubuntu/distro.py
+++ b/VMBuilder/plugins/ubuntu/distro.py
@@ -17,14 +17,14 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
+import logging
+import os
+import socket
+import types
 import VMBuilder
 from   VMBuilder           import register_distro, Distro
 from   VMBuilder.util      import run_cmd
-from   VMBuilder.exception import VMBuilderUserError
-import socket
-import logging
-import types
-import os
+from   VMBuilder.exception import VMBuilderUserError, VMBuilderException
 
 class Ubuntu(Distro):
     name = 'Ubuntu'
@@ -53,8 +53,10 @@ class Ubuntu(Distro):
         group = self.vm.setting_group('Installation options')
         group.add_option('--suite', default='jaunty', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
         group.add_option('--flavour', '--kernel-flavour', help='Kernel flavour to use. Default and valid options depend on architecture and suite')
+        group.add_option('--variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
         group.add_option('--iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm.  This requires suite and kernel parameter to match what is available on the iso, obviously.')
         group.add_option('--mirror', metavar='URL', help='Use Ubuntu mirror at URL instead of the default, which is http://archive.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
+        group.add_option('--proxy', metavar='URL', help='Use proxy at URL for cached packages')
         group.add_option('--install-mirror', metavar='URL', help='Use Ubuntu mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
         group.add_option('--security-mirror', metavar='URL', help='Use Ubuntu security mirror at URL instead of the default, which is http://security.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise.')
         group.add_option('--install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
@@ -67,6 +69,7 @@ class Ubuntu(Distro):
         group.add_option('--user', default='ubuntu', help='Username of initial user [default: %default]')
         group.add_option('--name', default='Ubuntu', help='Full name of initial user [default: %default]')
         group.add_option('--pass', default='ubuntu', help='Password of initial user [default: %default]')
+        group.add_option('--rootpass', help='Initial root password (WARNING: this has strong security implications).')
         self.vm.register_setting_group(group)
 
         group = self.vm.setting_group('Other options')
@@ -93,10 +96,7 @@ class Ubuntu(Distro):
             self.vm.components = self.vm.components.split(',')
 
     def get_locale(self):
-        try:
-            return os.environ['LANG']
-        except:
-            return None
+        return os.getenv('LANG')
 
     def preflight_check(self):
         """While not all of these are strictly checks, their failure would inevitably
@@ -126,10 +126,20 @@ class Ubuntu(Distro):
 
         self.vm.virtio_net = self.use_virtio_net()
 
+        if self.vm.lang:
+            try:
+                run_cmd('locale-gen', '%s' % self.vm.lang)
+            except VMBuilderException, e:
+                msg = "locale-gen does not recognize your locale '%s'" % self.vm.lang
+                raise VMBuilderUserError(msg)
+
     def install(self, destdir):
         self.destdir = destdir
         self.suite.install(destdir)
 
+    def install_vmbuilder_log(self, logfile, rootdir):
+        self.suite.install_vmbuilder_log(logfile, rootdir)
+
     def post_mount(self, fs):
         self.suite.post_mount(fs)
 
diff --git a/VMBuilder/plugins/ubuntu/edgy.py b/VMBuilder/plugins/ubuntu/edgy.py
index 180ab0f..3e3fba9 100644
--- a/VMBuilder/plugins/ubuntu/edgy.py
+++ b/VMBuilder/plugins/ubuntu/edgy.py
@@ -18,9 +18,10 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 import logging
-import suite
 import shutil
+import os
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 from   VMBuilder.plugins.ubuntu.dapper import Dapper
 
@@ -49,14 +50,18 @@ proc                                            /proc           proc    defaults
 
     def copy_settings(self):
         self.copy_to_target('/etc/default/locale', '/etc/default/locale')
-        shutil.rmtree('%s/etc/console-setup' % self.destdir)
-        self.copy_to_target('/etc/console-setup', '/etc/console-setup')
-        self.copy_to_target('/etc/default/console-setup', '/etc/default/console-setup')
+        csdir = '%s/etc/console-setup' % self.destdir
+        have_cs = os.path.isdir(csdir)
+        if have_cs:
+            shutil.rmtree(csdir)
+            self.copy_to_target('/etc/console-setup', '/etc/console-setup')
+            self.copy_to_target('/etc/default/console-setup', '/etc/default/console-setup')
         self.copy_to_target('/etc/timezone', '/etc/timezone')
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'tzdata')
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'tzdata')
         self.run_in_target('locale-gen', 'en_US')
         if self.vm.lang:
             self.run_in_target('locale-gen', self.vm.lang)
             self.install_from_template('/etc/default/locale', 'locale', { 'lang' : self.vm.lang })
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'locales')
-        self.run_in_target('dpkg-reconfigure', '-pcritical', 'console-setup')
+        self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'locales')
+        if have_cs:
+            self.run_in_target('dpkg-reconfigure', '-fnoninteractive', '-pcritical', 'console-setup')
diff --git a/VMBuilder/plugins/ubuntu/feisty.py b/VMBuilder/plugins/ubuntu/feisty.py
index bcab738..c89ab5b 100644
--- a/VMBuilder/plugins/ubuntu/feisty.py
+++ b/VMBuilder/plugins/ubuntu/feisty.py
@@ -18,8 +18,8 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 import logging
-import suite
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 from   VMBuilder.plugins.ubuntu.edgy import Edgy
 
diff --git a/VMBuilder/plugins/ubuntu/gutsy.py b/VMBuilder/plugins/ubuntu/gutsy.py
index 9f0ce58..5cefcd1 100644
--- a/VMBuilder/plugins/ubuntu/gutsy.py
+++ b/VMBuilder/plugins/ubuntu/gutsy.py
@@ -18,8 +18,8 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 import logging
-import suite
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 from   VMBuilder.plugins.ubuntu.feisty import Feisty
 
diff --git a/VMBuilder/plugins/ubuntu/hardy.py b/VMBuilder/plugins/ubuntu/hardy.py
index 5ed63f1..76b2f97 100644
--- a/VMBuilder/plugins/ubuntu/hardy.py
+++ b/VMBuilder/plugins/ubuntu/hardy.py
@@ -17,7 +17,7 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-import suite
+import VMBuilder.suite as suite
 from VMBuilder.plugins.ubuntu.gutsy import Gutsy
 
 class Hardy(Gutsy):
diff --git a/VMBuilder/plugins/ubuntu/intrepid.py b/VMBuilder/plugins/ubuntu/intrepid.py
index 99d9c82..ee27598 100644
--- a/VMBuilder/plugins/ubuntu/intrepid.py
+++ b/VMBuilder/plugins/ubuntu/intrepid.py
@@ -17,14 +17,18 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-import suite
 import logging
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 from   VMBuilder.plugins.ubuntu.hardy import Hardy
 
 class Intrepid(Hardy):
-    xen_kernel_flavour = 'server'
+    valid_flavours = { 'i386' :  ['386', 'generic', 'server', 'virtual'],
+                       'amd64' : ['generic', 'server', 'virtual'],
+                       'lpia'  : ['lpia', 'lpiacompat'] }
+    default_flavour = { 'i386' : 'virtual', 'amd64' : 'virtual', 'lpia' : 'lpia' }
+    xen_kernel_flavour = 'virtual'
 
     def mangle_grub_menu_lst(self):
         bootdev = disk.bootpart(self.vm.disks)
diff --git a/VMBuilder/plugins/ubuntu/jaunty.py b/VMBuilder/plugins/ubuntu/jaunty.py
index ac9a544..50f9041 100644
--- a/VMBuilder/plugins/ubuntu/jaunty.py
+++ b/VMBuilder/plugins/ubuntu/jaunty.py
@@ -17,9 +17,9 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-import suite
 import logging
 import VMBuilder.disk as disk
+import VMBuilder.suite as suite
 from   VMBuilder.util import run_cmd
 from   VMBuilder.plugins.ubuntu.intrepid import Intrepid
 
@@ -31,3 +31,14 @@ class Jaunty(Intrepid):
         run_cmd('sed', '-ie', 's/^# kopt=root=\([^ ]*\)\(.*\)/# kopt=root=UUID=%s\\2/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
         run_cmd('sed', '-ie', 's/^# groot.*/# groot=%s/g' % bootdev.fs.uuid, '%s/boot/grub/menu.lst' % self.destdir)
         run_cmd('sed', '-ie', '/^# kopt_2_6/ d', '%s/boot/grub/menu.lst' % self.destdir)
+
+    def update_passwords(self):
+        # Set the user password, using using defaults from /etc/login.defs (ie, no need to specify '-m')
+        self.run_in_target('chpasswd', stdin=('%s:%s\n' % (self.vm.user, getattr(self.vm, 'pass'))))
+
+        # Lock root account only if we didn't set the root password
+        if self.vm.rootpass:
+            self.run_in_target('chpasswd', stdin=('%s:%s\n' % ('root', self.vm.rootpass)))
+        else:
+            self.run_in_target('chpasswd', '-e', stdin='root:!\n')
+
diff --git a/VMBuilder/plugins/kvm/__init__.py b/VMBuilder/plugins/virtualbox/__init__.py
similarity index 100%
copy from VMBuilder/plugins/kvm/__init__.py
copy to VMBuilder/plugins/virtualbox/__init__.py
diff --git a/VMBuilder/plugins/virtualbox/templates/vm_deploy_script.tmpl b/VMBuilder/plugins/virtualbox/templates/vm_deploy_script.tmpl
new file mode 100644
index 0000000..baad6f8
--- /dev/null
+++ b/VMBuilder/plugins/virtualbox/templates/vm_deploy_script.tmpl
@@ -0,0 +1,57 @@
+#raw
+#! /usr/bin/env sh
+###############################################################################
+#
+# This script is used to create und register a new VM
+# in VirtualBox
+#
+###############################################################################
+#end raw
+#import os
+#import os.path
+
+os_type="Linux"
+
+disk_path="#echo os.path.abspath(os.path.dirname($vm_disks[0]))#/"
+
+
+VBoxManage createvm -name $vm_name -ostype \$os_type -register
+
+VBoxManage openmedium #slurp
+#set $i = 0
+#for $disk in $vm_disks
+    #set $i = $i + 1
+    #set $disk = os.path.basename(disk)
+disk \${disk_path}/$disk -type normal #slurp
+#end for
+
+VBoxManage modifyvm $vm_name -memory $memory -sata on #slurp
+#set $i = 0
+#for $disk in $vm_disks
+    #set $i = $i + 1
+    #set $disk = os.path.basename(disk)
+    #if $i >= 31
+    	#break
+    #end if
+    #if $i == 1
+    	-hda \${disk_path}/$disk #slurp
+    #else if $i == 2
+    	-hdb \${disk_path}/$disk #slurp
+    #else if $i == 3
+    	-hdd \${disk_path}/$disk #slurp
+    #else
+        -sataport${i} \${disk_path}/$disk #slurp
+    #end if
+#end for
+
+#if $mac
+VBoxManage modifyvm $vm_name -macaddress1 $mac
+#end if
+
+#if $ip
+#if $ip == "dhcp"
+VBoxManage modifyvm $vm_name -nic1 nat
+#else
+VBoxManage modifyvm $vm_name -nic1 intnet 
+#end if
+#end if
diff --git a/VMBuilder/plugins/kvm/vm.py b/VMBuilder/plugins/virtualbox/vm.py
similarity index 52%
copy from VMBuilder/plugins/kvm/vm.py
copy to VMBuilder/plugins/virtualbox/vm.py
index 83cddc3..ad16490 100644
--- a/VMBuilder/plugins/kvm/vm.py
+++ b/VMBuilder/plugins/virtualbox/vm.py
@@ -17,38 +17,38 @@
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-from   VMBuilder import register_hypervisor, Hypervisor
-import VMBuilder
-import VMBuilder.hypervisor
+
 import os
-import os.path
 import stat
+import VMBuilder.hypervisor
+from   VMBuilder            import register_hypervisor
 
-class KVM(Hypervisor):
-    name = 'KVM'
-    arg = 'kvm'
-    filetype = 'qcow2'
+class VirtualBox(VMBuilder.hypervisor.Hypervisor):
     preferred_storage = VMBuilder.hypervisor.STORAGE_DISK_IMAGE
     needs_bootloader = True
+    name = 'VirtualBox'
+    arg = 'vbox'
+
+    def register_options(self):
+        group = self.vm.setting_group('VirtualBox options')
+        group.add_option('--vbox-disk-format', metavar='FORMAT', default='vdi', help='Desired disk format. Valid options are: vdi vmdk. [default: %default]')
+        self.vm.register_setting_group(group)
 
     def finalize(self):
         self.imgs = []
-        self.cmdline = ['kvm', '-m', str(self.vm.mem), '-smp', str(self.vm.cpus) ]
         for disk in self.vm.disks:
-            img_path = disk.convert(self.vm.destdir, self.filetype)
+            img_path = disk.convert(self.vm.destdir, self.vm.vbox_disk_format)
             self.imgs.append(img_path)
             self.vm.result_files.append(img_path)
-            self.cmdline += ['-drive', 'file=%s' % os.path.basename(img_path)]
-
-    
-        self.cmdline += ['"$@"']
 
     def deploy(self):
-        script = '%s/run.sh' % self.vm.destdir
-        fp = open(script, 'w')
-        fp.write("#!/bin/sh\n\nexec %s\n" % ' '.join(self.cmdline))
+        vm_deploy_script = VMBuilder.util.render_template('virtualbox', self.vm, 'vm_deploy_script', { 'os_type' : self.vm.distro ,'vm_name' : self.vm.hostname, 'vm_disks' : self.imgs, 'memory' : self.vm.mem })
+
+        script_file = '%s/deploy_%s.sh' % (self.vm.destdir, self.vm.hostname)
+        fp = open(script_file, 'w')
+        fp.write(vm_deploy_script)
         fp.close()
-        os.chmod(script, stat.S_IRWXU | stat.S_IRWXU | stat.S_IROTH | stat.S_IXOTH)
-        self.vm.result_files.append(script)
+        os.chmod(script_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
+        self.vm.result_files.append(script_file)
 
-register_hypervisor(KVM)
+register_hypervisor(VirtualBox)
diff --git a/VMBuilder/plugins/vmware/templates/esxi.vmx.tmpl b/VMBuilder/plugins/vmware/templates/esxi.vmx.tmpl
index 0af8cbb..cb655c9 100644
--- a/VMBuilder/plugins/vmware/templates/esxi.vmx.tmpl
+++ b/VMBuilder/plugins/vmware/templates/esxi.vmx.tmpl
@@ -12,7 +12,7 @@ powerType.reset = "default"
 
 displayName = "$hostname $arch"
 
-numvcpus = "$cpu"
+numvcpus = "$cpus"
 scsi0.present = "true"
 scsi0.sharedBus = "none"
 scsi0.virtualDev = "lsilogic"
diff --git a/VMBuilder/plugins/vmware/templates/vmware.tmpl b/VMBuilder/plugins/vmware/templates/vmware.tmpl
index e79ce56..b76a8ea 100644
--- a/VMBuilder/plugins/vmware/templates/vmware.tmpl
+++ b/VMBuilder/plugins/vmware/templates/vmware.tmpl
@@ -3,6 +3,7 @@ virtualHW.version = "$vmhwversion"
 scsi0.present = "FALSE"
 scsi0.virtualDev = "lsilogic"
 memsize = "$mem"
+numvcpus = "$cpus"
 Ethernet0.virtualDev = "vlance"
 Ethernet0.present = "TRUE"
 Ethernet0.connectionType = "bridged"
diff --git a/VMBuilder/plugins/vmware/vm.py b/VMBuilder/plugins/vmware/vm.py
index 2afecb6..1112222 100644
--- a/VMBuilder/plugins/vmware/vm.py
+++ b/VMBuilder/plugins/vmware/vm.py
@@ -43,7 +43,7 @@ class VMWare(Hypervisor):
         return self.vm.disks
 
     def deploy(self):
-        vmdesc = VMBuilder.util.render_template('vmware', self.vm, vmxtemplate, { 'disks' : self.disks(), 'vmhwversion' : self.vmhwversion, 'cpu' : self.vm.cpu, 'mem' : self.vm.mem, 'hostname' : self.vm.hostname, 'arch' : self.vm.arch, 'guestos' : (self.vm.arch == 'amd64' and 'ubuntu-64' or 'ubuntu') })
+        vmdesc = VMBuilder.util.render_template('vmware', self.vm, self.vmxtemplate, { 'disks' : self.disks(), 'vmhwversion' : self.vmhwversion, 'cpus' : self.vm.cpus, 'mem' : self.vm.mem, 'hostname' : self.vm.hostname, 'arch' : self.vm.arch, 'guestos' : (self.vm.arch == 'amd64' and 'ubuntu-64' or 'ubuntu') })
 
         vmx = '%s/%s.vmx' % (self.vm.destdir, self.vm.hostname)
         fp = open(vmx, 'w')
diff --git a/VMBuilder/plugins/ubuntu/suite.py b/VMBuilder/suite.py
similarity index 95%
copy from VMBuilder/plugins/ubuntu/suite.py
copy to VMBuilder/suite.py
index 7cdbc20..1dd0d95 100644
--- a/VMBuilder/plugins/ubuntu/suite.py
+++ b/VMBuilder/suite.py
@@ -27,6 +27,7 @@ import sys
 class Suite(object):
     def __init__(self, vm):
         self.vm = vm
+        self.isodir = '/media/vmbuilder_inst_image'
         self.iso_mounted = False
 
     def check_arch_validity(self, arch):
diff --git a/VMBuilder/util.py b/VMBuilder/util.py
index 3e02c33..2ebaf35 100644
--- a/VMBuilder/util.py
+++ b/VMBuilder/util.py
@@ -169,8 +169,8 @@ def render_template(plugin, vm, tmplname, context=None):
         searchList.append(context)
     searchList.append(vm)
 
-    tmpldirs = ['VMBuilder/plugins/%s/templates',
-                os.path.expanduser('~/.vmbuilder/%s'),
+    tmpldirs = [os.path.expanduser('~/.vmbuilder/%s'),
+                os.path.dirname(__file__) + '/plugins/%s/templates',
                 '/etc/vmbuilder/%s']
 
     if vm.templates:
@@ -180,10 +180,13 @@ def render_template(plugin, vm, tmplname, context=None):
 
     for dir in tmpldirs:
         tmplfile = '%s/%s.tmpl' % (dir, tmplname)
+        logging.debug('Trying template \'%s\'' %(tmplfile))
         if os.path.exists(tmplfile):
             t = Template(file=tmplfile, searchList=searchList)
             output = t.respond()
             logging.debug('Output from template \'%s\': %s' % (tmplfile, output))
             return output
+        else:
+            logging.debug('Template \'%s\' not found' %(tmplfile))
 
     raise VMBuilderException('Template %s.tmpl not found in any of %s' % (tmplname, ', '.join(tmpldirs)))
diff --git a/VMBuilder/vm.py b/VMBuilder/vm.py
index c6d425b..ab116f5 100644
--- a/VMBuilder/vm.py
+++ b/VMBuilder/vm.py
@@ -29,6 +29,7 @@ import tempfile
 import textwrap
 import socket
 import struct
+import urllib
 import VMBuilder
 import VMBuilder.util      as util
 import VMBuilder.log       as log
@@ -90,6 +91,15 @@ class VM(object):
 
         self._register_base_settings()
 
+        self.add_clean_cmd('rm', log.logfile)
+
+    def get_version_info(self):
+        import vcsversion
+        info = vcsversion.version_info
+        info['major'] = 0
+        info['minor'] = 10
+        return info
+       
     def cleanup(self):
         logging.info("Cleaning up")
         while len(self._cleanup_cbs) > 0:
@@ -137,10 +147,10 @@ class VM(object):
         self.register_setting('--in-place', action='store_true', default=False, help='Install directly into the filesystem images. This is needed if your $TMPDIR is nodev and/or nosuid, but will result in slightly larger file system images.')
         self.register_setting('--tmpfs', metavar="OPTS", help='Use a tmpfs as the working directory, specifying its size or "-" to use tmpfs default (suid,dev,size=1G).')
         self.register_setting('-m', '--mem', type='int', default=128, help='Assign MEM megabytes of memory to the guest vm. [default: %default]')
-        self.register_setting('--cpus', type='int', default=1, help='Number of virtual CPU's. [default: %default]')
+        self.register_setting('--cpus', type='int', default=1, help='Number of virtual CPU\'s. [default: %default]')
 
         group = self.setting_group('Network related options')
-        domainname = '.'.join(socket.gethostbyname_ex(socket.gethostname())[0].split('.')[1:])
+        domainname = '.'.join(socket.gethostbyname_ex(socket.gethostname())[0].split('.')[1:]) or "defaultdomain"
         group.add_option('--domain', metavar='DOMAIN', default=domainname, help='Set DOMAIN as the domain name of the guest [default: The domain of the machine running this script: %default].')
         group.add_option('--ip', metavar='ADDRESS', default='dhcp', help='IP address in dotted form [default: %default].')
         group.add_option('--mac', metavar='VALUE', help='MAC address of the guest [default: one will be automatically generated on first run].')
@@ -237,7 +247,7 @@ class VM(object):
         is called to give all the plugins and the distro and hypervisor plugin a chance to set
         some reasonable defaults, which the frontend then can inspect and present
         """
-
+        multiline_split = re.compile("\s*,\s*")
         if self.distro and self.hypervisor:
             for plugin in VMBuilder._plugins:
                 self.plugins.append(plugin(self))
@@ -250,7 +260,8 @@ class VM(object):
                 if confvalue:
                     if self.optparser.get_option('--%s' % k):
                         if self.optparser.get_option('--%s' % k).action == 'append':
-                            setattr(self, k, confvalue.split(', '))
+                            values = multiline_split.split(confvalue)
+                            setattr(self, k, values)
                         else:
                             setattr(self, k, confvalue)
                     else:
@@ -290,7 +301,7 @@ class VM(object):
                 if (ipclass > 0) and (ipclass <= 127):
                     mask = 0xFF
                 elif (ipclass > 128) and (ipclass < 192):
-                    mask = OxFFFF
+                    mask = 0xFFFF
                 elif (ipclass < 224):
                     mask = 0xFFFFFF
                 else:
@@ -405,6 +416,8 @@ class VM(object):
             logging.info("Installing bootloader")
             self.distro.install_bootloader()
 
+        self.distro.install_vmbuilder_log(log.logfile, self.rootmnt)
+
     def preflight_check(self):
         for opt in sum([self.confparser.options(section) for section in self.confparser.sections()], []) + [k for (k,v) in self.confparser.defaults().iteritems()]:
             if '-' in opt:
@@ -413,6 +426,20 @@ class VM(object):
         self.ip_defaults()
         self.call_hooks('preflight_check')
 
+        # Check repository availability
+        if self.mirror:
+            testurl = self.mirror
+        else:
+            testurl = 'http://archive.ubuntu.com/'
+
+        try:
+            logging.debug('Testing access to %s' % testurl)
+            testnet = urllib.urlopen(testurl)
+        except IOError:
+            raise VMBuilderUserError('Could not connect to %s. Please check your connectivity and try again.' % testurl)
+
+        testnet.close()
+
     def install_file(self, path, contents=None, source=None, mode=None):
         fullpath = '%s%s' % (self.installdir, path)
         if source and not contents:
diff --git a/ubuntu-vm-builder b/debian-vm-builder
similarity index 93%
copy from ubuntu-vm-builder
copy to debian-vm-builder
index e06f3e4..564e928 100755
--- a/ubuntu-vm-builder
+++ b/debian-vm-builder
@@ -2,6 +2,7 @@
 #
 #    Uncomplicated VM Builder
 #    Copyright (C) 2007-2008 Canonical Ltd.
+#    Copyright (C) 2009      Bernd Zeimetz <bzed at debian.org>
 #    
 #    See AUTHORS for list of contributors
 #
diff --git a/debian-vm-builder.1 b/debian-vm-builder.1
new file mode 100644
index 0000000..9cd68db
--- /dev/null
+++ b/debian-vm-builder.1
@@ -0,0 +1,7 @@
+.TH DEBIAN-VM-BUILDER 1 "Jun 2009"
+.SH NAME
+debian-vm-builder \- builds virtual machines from the command line
+.SH DESCRIPTION
+debian-vm-builder is now a wrapper to vmbuilder (part of the python-vm-builder package) and is only maintained for compatibility wih previous scripts.  Please see the vmbuilder man page for more information or run 
+.B vmbuilder <hypervisor> <distro> --help
+for a full list of options.
diff --git a/setup.py b/setup.py
index 475894e..b488597 100755
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,21 @@
+#!/usr/bin/python
+
 from distutils.core import setup
 import VMBuilder.plugins
 from glob import glob
+import os.path
+import subprocess
 
+if os.path.exists('.bzr'):
+    try:
+        o = subprocess.Popen(('bzr','version-info', '--python'), stdout=subprocess.PIPE).stdout
+        f = open('VMBuilder/vcsversion.py', 'w')
+        f.write(o.read())
+        f.close()
+        o.close()
+    except Exception, e:
+        print repr(e)
+    
 setup(name='VMBuilder',
       version='0.9',
       description='Uncomplicated VM Builder',
diff --git a/tests.py b/tests.py
index 88305d5..41bcc68 100644
--- a/tests.py
+++ b/tests.py
@@ -57,6 +57,16 @@ class TestUbuntuPlugin(unittest.TestCase):
         ubuntu = Ubuntu(vm)
         self.assertRaises(VMBuilderUserError, ubuntu.preflight_check)
 
+
+class TestUtils(unittest.TestCase):
+    def test_run_cmd(self):
+        import VMBuilder
+        from VMBuilder.util import run_cmd
+        self.assertTrue("foobarbaztest" in 
+                        run_cmd("env", env={'foobarbaztest' : 'bar' }))
+
+
+
 if __name__ == '__main__':
     unittest.main()
 
diff --git a/ubuntu-vm-builder.1 b/ubuntu-vm-builder.1
new file mode 100644
index 0000000..484a4c0
--- /dev/null
+++ b/ubuntu-vm-builder.1
@@ -0,0 +1,7 @@
+.TH UBUNTU-VM-BUILDER 1 "Oct 2008"
+.SH NAME
+ubuntu-vm-builder \- builds virtual machines from the command line
+.SH DESCRIPTION
+ubuntu-vm-builder is now a wrapper to vmbuilder (part of the python-vm-builder package) and is only maintained for compatibility wih previous scripts.  Please see the vmbuilder man page for more information or run 
+.B vmbuilder <hypervisor> <distro> --help
+for a full list of options.

-- 
Tool for creating VM images.



More information about the Pkg-escience-soc2009 mailing list