import logging
import os
import re
-import time
import shutil
import subprocess
import tempfile
class VmDebootstrap(cliapp.Application):
def add_settings(self):
- default_arch = 'amd64'
+ default_arch = subprocess.check_output(
+ ["dpkg", "--print-architecture"]).strip()
self.settings.boolean(['verbose'], 'report what is going on')
self.settings.string(['image'], 'put created disk image in FILE',
self.settings.boolean(['configure-apt'],
'Create an apt source based on the distribution '
'and mirror selected.')
+ self.settings.boolean(['mbr'],
+ 'Run install-mbr (no longer done by default)')
+ self.settings.boolean(['grub'],
+ 'Install and configure grub2 - disables '
+ 'extlinux.')
def process_args(self, args):
if not self.settings['image'] and not self.settings['tarball']:
if self.settings['image']:
self.create_empty_image()
self.partition_image()
- self.install_mbr()
+ if self.settings['mbr']:
+ self.install_mbr()
(rootdev, bootdev) = self.setup_kpartx()
self.mkfs(rootdev, type=roottype)
rootdir = self.mount(rootdev)
self.create_users(rootdir)
self.remove_udev_persistent_rules(rootdir)
self.setup_networking(rootdir)
- self.configure_apt(rootdir)
+ if self.settings['configure-apt']:
+ self.configure_apt(rootdir)
self.customize(rootdir)
if self.settings['image']:
- if self.settings['extlinux']:
+ if self.settings['grub']:
+ self.install_grub2(rootdev, rootdir)
+ elif self.settings['extlinux']:
self.install_extlinux(rootdev, rootdir)
self.append_serial_console(rootdir)
self.optimize_image(rootdir)
if self.settings['verbose']:
print msg
- def runcmd(self, argv, stdin='', ignore_fail=False, **kwargs):
- logging.debug('runcmd: %s %s' % (argv, kwargs))
+ def runcmd(self, argv, stdin='', ignore_fail=False, env=None, **kwargs):
+ logging.debug('runcmd: %s %s %s' % (argv, env, kwargs))
p = subprocess.Popen(argv, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- **kwargs)
+ env=env, **kwargs)
out, err = p.communicate(stdin)
if p.returncode != 0:
msg = 'command failed: %s\n%s\n%s' % (argv, out, err)
'set', '1', 'boot', 'on'])
def install_mbr(self):
- self.message('Installing MBR')
- self.runcmd(['install-mbr', self.settings['image']])
+ if os.path.exists("/sbin/install-mbr"):
+ self.message('Installing MBR')
+ self.runcmd(['install-mbr', self.settings['image']])
def setup_kpartx(self):
out = self.runcmd(['kpartx', '-avs', self.settings['image']])
else:
necessary_packages = ['acpid']
+ if self.settings['grub']:
+ necessary_packages.append('grub2')
+
include = self.settings['package']
if not self.settings['no-kernel']:
include.append('sudo')
args = ['debootstrap', '--arch=%s' % self.settings['arch']]
- args.append(
- '--include=%s' % ','.join(necessary_packages + include))
+ if self.settings['package'] and len(necessary_packages) > 0:
+ args.append(
+ '--include=%s' % ','.join(necessary_packages + include))
if self.settings['foreign']:
args.append('--foreign')
if self.settings['variant']:
logging.debug(" ".join(args))
self.runcmd(args)
if self.settings['foreign']:
+ # set a noninteractive debconf environment for secondstage
+ env = {
+ "DEBIAN_FRONTEND": "noninteractive",
+ "DEBCONF_NONINTERACTIVE_SEEN": "true",
+ "LC_ALL": "C"
+ }
+ # add the mapping to the complete environment.
+ env.update(os.environ)
# First copy the binfmt handler over
+ self.message('Setting up binfmt handler')
shutil.copy(self.settings['foreign'], '%s/usr/bin/' % rootdir)
# Next, run the package install scripts etc.
self.message('Running debootstrap second stage')
self.runcmd(['chroot', rootdir,
- '/debootstrap/debootstrap', '--second-stage'])
+ '/debootstrap/debootstrap', '--second-stage'],
+ env=env)
def set_hostname(self, rootdir):
hostname = self.settings['hostname']
with open(inittab, 'a') as f:
f.write('\nS0:23:respawn:%s\n' % serial_command)
+ def install_grub2(self, rootdev, rootdir):
+ self.message("Configuring grub2")
+ # rely on kpartx using consistent naming to map loop0p1 to loop0
+ install_dev = os.path.join('/dev', os.path.basename(rootdev)[:-2])
+ self.runcmd(['mount', '/dev', '-t', 'devfs', '-obind',
+ '%s' % os.path.join(rootdir, 'dev')])
+ self.runcmd(['mount', '/proc', '-t', 'proc', '-obind',
+ '%s' % os.path.join(rootdir, 'proc')])
+ self.runcmd(['mount', '/sys', '-t', 'sysfs', '-obind',
+ '%s' % os.path.join(rootdir, 'sys')])
+ try:
+ self.runcmd(['chroot', rootdir, 'update-grub'])
+ self.runcmd(['chroot', rootdir, 'grub-install', install_dev])
+ except cliapp.AppException as e:
+ self.message("Failed to configure grub2. Using extlinux.")
+ self.runcmd(['umount', os.path.join(rootdir, 'sys')])
+ self.runcmd(['umount', os.path.join(rootdir, 'proc')])
+ self.runcmd(['umount', os.path.join(rootdir, 'dev')])
+ self.install_extlinux(rootdev, rootdir)
+
def install_extlinux(self, rootdev, rootdir):
+ if not os.path.exists("/usr/bin/extlinux"):
+ self.message("extlinux not installed, skipping.")
+ return
self.message('Installing extlinux')
def find(pattern):
return os.path.join('boot', basename)
raise cliapp.AppException('Cannot find match: %s' % pattern)
- kernel_image = find('vmlinuz-.*')
- initrd_image = find('initrd.img-.*')
+ try:
+ kernel_image = find('vmlinuz-.*')
+ initrd_image = find('initrd.img-.*')
+ except cliapp.AppException as e:
+ self.message("Unable to find kernel. Not installing extlinux.")
+ logging.debug("No kernel found. %s. Skipping install of extlinux." % e)
+ return
out = self.runcmd(['blkid', '-c', '/dev/null', '-o', 'value',
'-s', 'UUID', rootdev])
def customize(self, rootdir):
script = self.settings['customize']
- if script:
- self.message('Running customize script %s' % script)
- with open('/dev/tty', 'w') as tty:
- cliapp.runcmd([script, rootdir], stdout=tty, stderr=tty)
+ if not script:
+ return
+ if not os.path.exists(script):
+ example = os.path.join("/usr/share/vmdebootstrap/examples/", script)
+ if not os.path.exists(example):
+ self.message("Unable to find %s" % script)
+ return
+ script = example
+ self.message('Running customize script %s' % script)
+ with open('/dev/tty', 'w') as tty:
+ cliapp.runcmd([script, rootdir], stdout=tty, stderr=tty)
def create_tarball(self, rootdir):
# Create a tarball of the disk's contents
logging.debug('configure apt %s' % conf)
f = open(conf, 'w')
f.write('''
- deb %(mirror)s %(distribution)s main
- #deb-src %(mirror)s %(distribution)s main
- ''' % {
+deb %(mirror)s %(distribution)s main
+#deb-src %(mirror)s %(distribution)s main
+''' % {
'mirror': self.settings['mirror'],
'distribution': self.settings['distribution']
})