Ejemplo n.º 1
0
    def __init__(self, vm, filename, size=None):
        self.vm = vm
        "The hypervisor to which the disk belongs."

        self.filename = filename
        "The filename of the disk image."

        self.partitions = []
        "The list of partitions on the disk. Is kept in order by L{add_part}."

        self.preallocated = False
        "Whether the file existed already (True if it did, False if we had to create it)."

        self.size = 0
        "The size of the disk. For preallocated disks, this is detected."

        if not os.path.exists(self.filename):
            if not size:
                raise VMBuilderUserError('%s does not exist, but no size was given.' % (self.filename))
            self.size = parse_size(size)
        else:
            if size:
                raise VMBuilderUserError('%s exists, but size was given.' % (self.filename))
            self.preallocated = True
            self.size = detect_size(self.filename)

        self.format_type = None
        "The format type of the disks. Only used for converted disks."
Ejemplo n.º 2
0
    def add_part(self, begin, length, type, mntpnt):
        """
        Add a partition to the disk

        @type  begin: number
        @param begin: Start offset of the new partition (in megabytes)
        @type  length: 
        @param length: Size of the new partition (in megabytes)
        @type  type: string
        @param type: Type of the new partition. Valid options are: ext2 ext3 xfs swap linux-swap
        @type  mntpnt: string
        @param mntpnt: Intended mountpoint inside the guest of the new partition
        """
        length = parse_size(length)
        end = begin+length-1
        logging.debug("add_part - begin %d, length %d, end %d, type %s, mntpnt %s" % (begin, length, end, type, mntpnt))
        for part in self.partitions:
            if (begin >= part.begin and begin <= part.end) or \
                (end >= part.begin and end <= part.end):
                raise VMBuilderUserError('Partitions are overlapping')
        if begin < 0 or end > self.size:
            raise VMBuilderUserError('Partition is out of bounds. start=%d, end=%d, disksize=%d' % (begin,end,self.size))
        part = self.Partition(disk=self, begin=begin, end=end, type=str_to_type(type), mntpnt=mntpnt)
        self.partitions.append(part)

        # We always keep the partitions in order, so that the output from kpartx matches our understanding
        self.partitions.sort(cmp=lambda x,y: x.begin - y.begin)
Ejemplo n.º 3
0
    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:
                raise VMBuilderUserError(
                    'You specified a "%s" config option in a config file, but that is not valid. Perhaps you meant "%s"?'
                    % (opt, opt.replace('-', '_')))

        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()
Ejemplo n.º 4
0
    def preflight_check(self):
        """While not all of these are strictly checks, their failure would inevitably
        lead to failure, and since we can check them before we start setting up disk
        and whatnot, we might as well go ahead an do this now."""

        suite = self.get_setting('suite') 
        if not suite in self.suites:
            raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites)))
        
        modname = 'VMBuilder.plugins.debian.%s' % (suite, )
        mod = __import__(modname, fromlist=[suite])
        self.suite = getattr(mod, suite.capitalize())(self)

        arch = self.get_setting('arch') 
        if arch not in self.valid_archs[self.host_arch] or  \
            not self.suite.check_arch_validity(arch):
            raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch,
                                                                                                      ' '.join(self.valid_archs[self.host_arch])))

        components = self.get_setting('components')
        if not components:
            self.set_config_value_list = ['main', 'contrib']
        else:
            if type(components) is str:
                self.vm.components = self.vm.components.split(',')

        self.context.virtio_net = self.use_virtio_net()

        # check if the seedfile exists if one is to be used
        seedfile = self.context.get_setting('seedfile')
        if seedfile and not os.path.exists(seedfile):
            raise VMBuilderUserError("Seedfile '%s' does not exist" % seedfile)

        lang = self.get_setting('lang')
Ejemplo n.º 5
0
    def xen_kernel_version(self):
        if self.suite.xen_kernel_flavour:
            if not self.xen_kernel:
                rmad = run_cmd(
                    'rmadison',
                    'linux-image-%s' % self.suite.xen_kernel_flavour)
                version = ['0', '0', '0', '0']

                for line in rmad.splitlines():
                    sline = line.split('|')

                    if sline[2].strip().startswith(self.vm.suite):
                        vt = sline[1].strip().split('.')
                        for i in range(4):
                            if int(vt[i]) > int(version[i]):
                                version = vt
                                break

                if version[0] == '0':
                    raise VMBuilderException(
                        'Something is wrong, no valid xen kernel for the suite %s found by rmadison'
                        % self.vm.suite)

                self.xen_kernel = '%s.%s.%s-%s' % (version[0], version[1],
                                                   version[2], version[3])
            return self.xen_kernel
        else:
            raise VMBuilderUserError(
                'There is no valid xen kernel for the suite selected.')
Ejemplo n.º 6
0
    def __init__(self, vm, size='5G', preallocated=False, filename=None):
        """
        @type  size: string or number
        @param size: The size of the disk image (passed to L{parse_size})

        @type  preallocated: boolean
        @param preallocated: if True, the disk image already exists and will not be created (useful for raw devices)

        @type  filename: string
        @param filename: force a certain filename or to give the name of the preallocated disk image
        """

        # We need this for "introspection"
        self.vm = vm

        # Perhaps this should be the frontend's responsibility?
        self.size = parse_size(size)

        self.preallocated = preallocated

        # If filename isn't given, make one up
        if filename:
            self.filename = filename
        else:
            if self.preallocated:
                raise VMBuilderUserError(
                    'Preallocated was set, but no filename given')
            self.filename = 'disk%d.img' % len(self.vm.disks)

        self.partitions = []
Ejemplo n.º 7
0
    def xen_kernel_version(self):
        if self.suite.xen_kernel_flavour:
            # if this is ec2, do not call rmadison.
            # this could be replaced with a method to get most recent
            # stable kernel, but really, this is not used at all for ec2
            if hasattr(self.context, 'ec2') and self.context.ec2:
                logging.debug("selecting ec2 kernel")
                self.xen_kernel = "2.6.ec2-kernel"
                return self.xen_kernel
            if not self.xen_kernel:
                rmad = run_cmd('rmadison', 'linux-image-%s' % self.suite.xen_kernel_flavour)
                version = ['0', '0','0', '0']

                for line in rmad.splitlines():
                    sline = line.split('|')

                    if sline[2].strip().startswith(self.context.get_setting('suite')):
                        vt = sline[1].strip().split('.')
                        for i in range(4):
                            if int(vt[i]) > int(version[i]):
                                version = vt
                                break

                if version[0] == '0':
                    raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite)

                self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3])
            return self.xen_kernel
        else:
            raise VMBuilderUserError('There is no valid xen kernel for the suite selected.')
Ejemplo n.º 8
0
 def set_distro(self, arg):
     if arg in VMBuilder.distros.keys():
         self.distro = VMBuilder.distros[arg](self)
         self.set_defaults()
     else:
         raise VMBuilderUserError("Invalid distro. Valid distros: %s" %
                                  " ".join(VMBuilder.distros.keys()))
Ejemplo n.º 9
0
    def do_disk(self,
                hypervisor,
                curdisk,
                size,
                disk_idx,
                diskpartition=False):
        default_filesystem = hypervisor.distro.preferred_filesystem()

        if self.options.raw:
            disk = hypervisor.add_disk(diskpartition=diskpartition,
                                       filename=self.options.raw[disk_idx])
        else:
            disk = hypervisor.add_disk(
                util.tmp_filename(tmp_root=self.options.tmp_root), size + 1)

        logging.debug("do_disk #%i - size: %d" % (disk_idx, size))
        if diskpartition and len(curdisk) > 1:
            raise VMBuilderUserError(
                'Only one partition is supported on diskpartitions, since there is no partition table!'
            )
        offset = 0
        for pair in curdisk:
            logging.debug("do_disk #%i - part: %s, size: %s, offset: %d" %
                          (disk_idx, pair[0], pair[1], offset))
            if pair[0] == 'root':
                disk.add_part(offset, int(pair[1]), default_filesystem, '/')
            elif pair[0] == 'swap':
                disk.add_part(offset, int(pair[1]), pair[0], pair[0])
            else:
                disk.add_part(offset, int(pair[1]), default_filesystem,
                              pair[0])
            offset += int(pair[1])
Ejemplo n.º 10
0
 def set_hypervisor(self, arg):
     if arg in VMBuilder.hypervisors.keys():
         self.hypervisor = VMBuilder.hypervisors[arg](self)
         self.set_defaults()
     else:
         raise VMBuilderUserError(
             "Invalid hypervisor. Valid hypervisors: %s" %
             " ".join(VMBuilder.hypervisors.keys()))
Ejemplo n.º 11
0
    def preflight_check(self):
        """
        Validate the ip configuration given and set defaults
        """

        ip = self.context.get_setting('ip')
        logging.debug("ip: %s" % ip)

        mac = self.context.get_setting('mac')
        if mac:
            if not validate_mac(mac):
                raise VMBuilderUserError("Malformed MAC address entered: %s" % mac)

        if ip != 'dhcp':
            # num* are numeric representations
            numip = dotted_to_numeric_ip(ip)

            mask = self.context.get_setting('mask')
            if not mask:
                nummask = guess_mask_from_ip(numip)
            else:
                nummask = dotted_to_numeric_ip(mask)

            numnet = calculate_net_address_from_ip_and_netmask(numip, nummask)

            net = self.context.get_setting('net')
            if not net:
                self.context.set_setting_default('net', numeric_to_dotted_ip(numnet))

            bcast = self.context.get_setting('bcast')
            if not bcast:
                numbcast = calculate_broadcast_address_from_ip_and_netmask(numnet, nummask)
                self.context.set_setting_default('bcast', numeric_to_dotted_ip(numbcast))

            gw = self.context.get_setting('gw')
            if not gw:
                numgw = guess_gw_from_ip(numip)
                self.context.set_setting_default('gw', numeric_to_dotted_ip(numgw))

            dns = self.context.get_setting('dns')
            if not dns:
                self.context.set_setting_default('dns', self.context.get_setting('gw'))

            self.context.set_setting_default('mask', numeric_to_dotted_ip(nummask))

            logging.debug("net: %s" % self.context.get_setting('net'))
            logging.debug("netmask: %s" % self.context.get_setting('mask'))
            logging.debug("broadcast: %s" % self.context.get_setting('bcast'))
            logging.debug("gateway: %s" % self.context.get_setting('gw'))
            logging.debug("dns: %s" % self.context.get_setting('dns'))

        ip6 = self.context.get_setting('ip6')
        logging.debug("ip6: %s" % ip6)
        if ip6 not in ['none', 'dhcp']:
            logging.debug("gateway6: %s" % self.context.get_setting('gw6'))
Ejemplo n.º 12
0
def guess_mask_from_ip(numip):
    first_octet = numip & 0xFF

    if (first_octet > 0) and (first_octet <= 127):
        return 0xFF
    elif (first_octet > 128) and (first_octet < 192):
        return 0xFFFF
    elif (first_octet < 224):
        return 0xFFFFFF
    else:
        raise VMBuilderUserError('Could not guess network class of: %s' % numeric_to_dotted_ip(numip))
Ejemplo n.º 13
0
def get_distro(name):
    """
    Get Distro subclass by name

    @type name: string
    @param name: Name of the Distro subclass (defined by its .arg attribute)
    """
    if name in distros:
        return distros[name]
    else:
        raise VMBuilderUserError('No such distro. Available distros: %s' %
                                 (' '.join(distros.keys())))
Ejemplo n.º 14
0
def get_hypervisor(name):
    """
    Get Hypervisor subclass by name

    @type name: string
    @param name: Name of the Hypervisor subclass (defined by its .arg attribute)
    """
    if name in hypervisors:
        return hypervisors[name]
    else:
        raise VMBuilderUserError(
            'No such hypervisor. Available hypervisors: %s' %
            (' '.join(hypervisors.keys())))
Ejemplo n.º 15
0
    def preflight_check(self):
        """While not all of these are strictly checks, their failure would inevitably
        lead to failure, and since we can check them before we start setting up disk
        and whatnot, we might as well go ahead an do this now."""

        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, )
        mod = __import__(modname, fromlist=[self.vm.suite])
        self.suite = getattr(mod, self.vm.suite.capitalize())(self.vm)

        if self.vm.arch not in self.valid_archs[self.host_arch] or  \
            not self.suite.check_arch_validity(self.vm.arch):
            raise VMBuilderUserError(
                '%s is not a valid architecture. Valid architectures are: %s' %
                (self.vm.arch, ' '.join(self.valid_archs[self.host_arch])))

        if not self.vm.components:
            self.vm.components = ['main', 'restricted', 'universe']
        else:
            if type(self.vm.components) is str:
                self.vm.components = self.vm.components.split(',')

        if self.vm.hypervisor.name == 'Xen':
            logging.info('Xen kernel default: linux-image-%s %s',
                         self.suite.xen_kernel_flavour,
                         self.xen_kernel_version())

        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)
Ejemplo n.º 16
0
    def xen_kernel_version(self):
        if self.suite.xen_kernel_flavour:
            if not self.xen_kernel:
                logging.debug("Searching for %s-%s flavour Xen kernel..." %
                              (self.suite.xen_kernel_flavour,
                               self.suite.default_flavour[self.vm.arch]))
                xen_kernel = self.find_linux_kernel(
                    self.vm.suite, self.suite.xen_kernel_flavour,
                    self.suite.default_flavour[self.vm.arch])

                if xen_kernel == None:
                    logging.debug(
                        'Default Xen kernel flavour %s-%s is not available for this suite.'
                        % (self.suite.xen_kernel_flavour,
                           self.suite.default_flavour[self.vm.arch]))
                    if self.suite.valid_flavours[self.vm.arch] > 0:
                        for flavour in self.suite.valid_flavours[self.vm.arch]:
                            if flavour != self.suite.default_flavour[
                                    self.vm.arch]:
                                logging.debug(
                                    "Trying alternate flavour %s-%s..." %
                                    (self.suite.xen_kernel_flavour, flavour))
                                xen_kernel = self.find_linux_kernel(
                                    self.vm.suite,
                                    self.suite.xen_kernel_flavour,
                                    self.suite.default_flavour[self.vm.arch])
                                if xen_kernel != None:
                                    logging.info(
                                        "Using Xen kernel linux-image-2.6-%s-%s, package version %s"
                                        % (self.suite.xen_kernel_flavour,
                                           flavour, xen_kernel))
                                    break
                else:
                    logging.info(
                        "Using Xen kernel linux-image-2.6-%s-%s, package version %s"
                        %
                        (self.suite.xen_kernel_flavour,
                         self.suite.default_flavour[self.vm.arch], xen_kernel))

                if xen_kernel == None:
                    raise VMBuilderException(
                        'There is no valid Xen kernel for the suite selected.')

                self.xen_kernel = xen_kernel
            return self.xen_kernel
        else:
            raise VMBuilderUserError(
                'There is no valid xen kernel for the suite selected.')
Ejemplo n.º 17
0
    def __init__(self, conf=None):
        self.hypervisor = None  #: hypervisor object, representing the hypervisor the vm is destined for
        self.distro = None

        self.disks = []
        self.filesystems = []

        self.result_files = []
        self.plugins = []
        self._cleanup_cbs = []

        #: final destination for the disk images
        self.destdir = None
        #: tempdir where we do all the work
        self.workdir = None
        #: mount point where the disk images will be mounted
        self.rootmnt = None
        #: directory where we build up the guest filesystem
        self.tmproot = None

        self.fsmounted = False

        self.optparser = _MyOptParser(
            epilog=
            "ubuntu-vm-builder is Copyright (C) 2007-2009 Canonical Ltd. and written by Soren Hansen <*****@*****.**>.",
            usage='%prog hypervisor distro [options]')
        self.optparser.arg_help = (('hypervisor', self.hypervisor_help),
                                   ('distro', self.distro_help))

        self.confparser = ConfigParser.SafeConfigParser()

        if conf:
            if not (os.path.isfile(conf)):
                raise VMBuilderUserError(
                    'The path to the configuration file is not valid: %s.' %
                    conf)
        else:
            conf = ''

        self.confparser.read([
            '/etc/vmbuilder.cfg',
            os.path.expanduser('~/.vmbuilder.cfg'), conf
        ])

        self._register_base_settings()

        self.add_clean_cmd('rm', log.logfile)
Ejemplo n.º 18
0
    def create_directory_structure(self):
        """Creates the directory structure where we'll be doing all the work

        When create_directory_structure returns, the following attributes will be set:

         - L{VM.destdir}: The final destination for the disk images
         - L{VM.workdir}: The temporary directory where we'll do all the work
         - L{VM.rootmnt}: The root mount point where all the target filesystems will be mounted
         - L{VM.tmproot}: The directory where we build up the guest filesystem

        ..and the corresponding directories are created.

        Additionally, L{VM.destdir} is created, which is where the files (disk images, filesystem
        images, run scripts, etc.) will eventually be placed.
        """

        self.workdir = self.create_workdir()
        self.add_clean_cmd('rm', '-rf', self.workdir)

        logging.debug('Temporary directory: %s', self.workdir)

        self.rootmnt = '%s/target' % self.workdir
        logging.debug('Creating the root mount directory: %s', self.rootmnt)
        os.mkdir(self.rootmnt)

        self.tmproot = '%s/root' % self.workdir
        logging.debug('Creating temporary root: %s', self.tmproot)
        os.mkdir(self.tmproot)

        # destdir is where the user's files will land when they're done
        if os.path.exists(self.destdir):
            if self.overwrite:
                logging.info(
                    '%s exists, and --overwrite specified. Removing..' %
                    (self.destdir, ))
                shutil.rmtree(self.destdir)
            else:
                raise VMBuilderUserError('%s already exists' %
                                         (self.destdir, ))

        logging.debug('Creating destination directory: %s', self.destdir)
        os.mkdir(self.destdir)
        self.add_clean_cmd('rmdir', self.destdir, ignore_fail=True)

        self.result_files.append(self.destdir)
Ejemplo n.º 19
0
def parse_size(size_str):
    """Takes a size like qemu-img would accept it and returns the size in MB"""
    try:
        return int(size_str)
    except ValueError:
        pass

    try:
        num = int(size_str[:-1])
    except ValueError:
        raise VMBuilderUserError("Invalid size: %s" % size_str)

    if size_str[-1:] == 'g' or size_str[-1:] == 'G':
        return num * 1024
    if size_str[-1:] == 'm' or size_str[-1:] == 'M':
        return num
    if size_str[-1:] == 'k' or size_str[-1:] == 'K':
        return num / 1024
Ejemplo n.º 20
0
 def get_ec2_ramdisk(self):
     if self.suite.ec2_ramdisk_info:
         return self.suite.ec2_ramdisk_info[self.vm.arch]
     else:
         raise VMBuilderUserError(
             'EC2 is not supported for the suite selected')
Ejemplo n.º 21
0
def dotted_to_numeric_ip(dotted_ip):
    try:
        return struct.unpack('I', socket.inet_aton(dotted_ip))[0]
    except socket.error:
        raise VMBuilderUserError('%s is not a valid ip address' % dotted_ip)
Ejemplo n.º 22
0
 def get_ec2_kernel(self):
     if self.suite.ec2_kernel_info:
         return self.suite.ec2_kernel_info[self.context.arch]
     else:
         raise VMBuilderUserError(
             'EC2 is not supported for the suite selected')
Ejemplo n.º 23
0
 def preflight_check(self):
     domain = self.context.get_setting('domain')
     if domain == '':
         raise VMBuilderUserError('Domain is undefined and host has no domain set.')
Ejemplo n.º 24
0
    def ip_defaults(self):
        """
        is called to validate the ip configuration given and set defaults
        """

        logging.debug("ip: %s" % self.ip)

        if self.mac:
            valid_mac_address = re.compile("([0-9a-f]{2}:){5}([0-9a-f]{2})",
                                           re.IGNORECASE)
            if not valid_mac_address.search(self.mac):
                raise VMBuilderUserError("Malformed MAC address entered: %s" %
                                         self.mac)
            else:
                logging.debug("Valid mac given: %s" % self.mac)

        if self.ip != 'dhcp':
            if self.domain == '':
                raise VMBuilderUserError(
                    'Domain is undefined and host has no domain set.')

            try:
                numip = struct.unpack('I', socket.inet_aton(self.ip))[0]
            except socket.error:
                raise VMBuilderUserError('%s is not a valid ip address' %
                                         self.ip)

            if not self.mask:
                ipclass = numip & 0xFF
                if (ipclass > 0) and (ipclass <= 127):
                    mask = 0xFF
                elif (ipclass > 128) and (ipclass < 192):
                    mask = 0xFFFF
                elif (ipclass < 224):
                    mask = 0xFFFFFF
                else:
                    raise VMBuilderUserError(
                        'The class of the ip address specified (%s) does not seem right'
                        % self.ip)
            else:
                mask = struct.unpack('I', socket.inet_aton(self.mask))[0]

            numnet = numip & mask

            if not self.net:
                self.net = socket.inet_ntoa(struct.pack('I', numnet))
            if not self.bcast:
                self.bcast = socket.inet_ntoa(
                    struct.pack('I', numnet + (mask ^ 0xFFFFFFFF)))
            if not self.gw:
                self.gw = socket.inet_ntoa(
                    struct.pack('I', numnet + 0x01000000))
            if not self.dns:
                self.dns = self.gw

            self.mask = socket.inet_ntoa(struct.pack('I', mask))

            logging.debug("net: %s" % self.net)
            logging.debug("netmask: %s" % self.mask)
            logging.debug("broadcast: %s" % self.bcast)
            logging.debug("gateway: %s" % self.gw)
            logging.debug("dns: %s" % self.dns)
Ejemplo n.º 25
0
    def main(self):
        tmpfs_mount_point = None
        try:
            optparser = optparse.OptionParser()

            self.set_usage(optparser)

            optparser.add_option('--version',
                                 action='callback',
                                 callback=self.versioninfo,
                                 help='Show version information')

            group = optparse.OptionGroup(optparser, 'Build options')
            group.add_option('--debug',
                             action='callback',
                             callback=self.set_verbosity,
                             help='Show debug information')
            group.add_option('--verbose',
                             '-v',
                             action='callback',
                             callback=self.set_verbosity,
                             help='Show progress information')
            group.add_option('--quiet',
                             '-q',
                             action='callback',
                             callback=self.set_verbosity,
                             help='Silent operation')
            group.add_option(
                '--overwrite',
                '-o',
                action='store_true',
                help='Remove destination directory before starting build')
            group.add_option('--config',
                             '-c',
                             type='str',
                             help='Configuration file')
            group.add_option('--templates',
                             metavar='DIR',
                             help='Prepend DIR to template search path.')
            group.add_option('--destdir',
                             '-d',
                             type='str',
                             help='Destination directory')
            group.add_option('--only-chroot',
                             action='store_true',
                             help=("Only build the chroot. Don't install it "
                                   "on disk images or anything."))
            group.add_option('--chroot-dir',
                             help="Build the chroot in directory.")
            group.add_option('--existing-chroot', help="Use existing chroot.")
            group.add_option('--tmp',
                             '-t',
                             metavar='DIR',
                             dest='tmp_root',
                             default=tempfile.gettempdir(),
                             help=('Use TMP as temporary working space for '
                                   'image generation. Defaults to $TMPDIR if '
                                   'it is defined or /tmp otherwise. '
                                   '[default: %default]'))
            group.add_option('--tmpfs',
                             metavar="SIZE",
                             help=('Use a tmpfs as the working directory, '
                                   'specifying its size or "-" to use tmpfs '
                                   'default (suid,dev,size=1G).'))
            group.add_option(
                '--skip-hook',
                metavar="HOOK",
                type='str',
                action='append',
                dest='skipped_hooks',
                default=[],
                help=('Skip calling this hook. Use this only if you '
                      'know what you are doing. Disabling hooks will'
                      'mostly result in an unstable or not bootable'
                      'system. Can be specified multiple times to'
                      'disable multiple hooks'))
            optparser.add_option_group(group)

            group = optparse.OptionGroup(optparser, 'Disk')
            group.add_option('--rootsize',
                             metavar='SIZE',
                             default=4096,
                             help=('Size (in MB) of the root filesystem '
                                   '[default: %default]'))
            group.add_option(
                '--optsize',
                metavar='SIZE',
                default=0,
                help=('Size (in MB) of the /opt filesystem. If not'
                      ' set, no /opt filesystem will be added.'))
            group.add_option('--swapsize',
                             metavar='SIZE',
                             default=1024,
                             help=('Size (in MB) of the swap partition '
                                   '[default: %default]'))
            group.add_option(
                '--raw',
                metavar='PATH',
                type='str',
                action='append',
                help=("Specify a file (or block device) to use as "
                      "first disk image (can be specified multiple"
                      " times)."))
            group.add_option(
                '--part',
                metavar='PATH',
                type='str',
                help=("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"
                      "Insert \"diskpartition\" line as partition "
                      "to adisk to use this disk as one partition "
                      "and don't create partition table and MBR"))
            optparser.add_option_group(group)

            optparser.disable_interspersed_args()
            (dummy, args) = optparser.parse_args(sys.argv[1:])
            optparser.enable_interspersed_args()

            hypervisor, distro = self.handle_args(optparser, args)

            self.add_settings_from_context(optparser, distro)
            self.add_settings_from_context(optparser, hypervisor)

            hypervisor.register_hook('fix_ownership', self.fix_ownership)

            config_files = [
                '/etc/vmbuilder.cfg',
                os.path.expanduser('~/.vmbuilder.cfg')
            ]
            (self.options, args) = optparser.parse_args(sys.argv[2:])

            if os.geteuid() != 0:
                raise VMBuilderUserError('Must run as root')

            hypervisor.set_skipped_hooks(self.options.skipped_hooks)
            distro.set_skipped_hooks(self.options.skipped_hooks)

            logging.debug("Launch directory: {}".format(os.getcwd()))

            distro.overwrite = hypervisor.overwrite = self.options.overwrite
            destdir = self.options.destdir or ('%s-%s' %
                                               (distro.arg, hypervisor.arg))
            logging.debug("Output destdir: {}".format(destdir))

            if self.options.tmpfs and self.options.chroot_dir:
                raise VMBuilderUserError(
                    '--chroot-dir and --tmpfs can not be used together.')

            if os.path.exists(destdir):
                if os.path.realpath(destdir) == os.getcwd():
                    raise VMBuilderUserError(
                        'Current working directory cannot be used as a destination directory'
                    )
                if self.options.overwrite:
                    logging.debug('%s existed, but -o was specified. '
                                  'Nuking it.' % destdir)
                    shutil.rmtree(destdir)
                else:
                    raise VMBuilderUserError('%s already exists' % destdir)

            if self.options.config:
                config_files.append(self.options.config)
            util.apply_config_files_to_context(config_files, distro)
            util.apply_config_files_to_context(config_files, hypervisor)

            if self.options.templates:
                distro.template_dirs.insert(0,
                                            '%s/%%s' % self.options.templates)
                hypervisor.template_dirs.insert(
                    0, '%s/%%s' % self.options.templates)

            for option in dir(self.options):
                if option.startswith('_') or option in [
                        'ensure_value', 'read_module', 'read_file'
                ]:
                    continue
                val = getattr(self.options, option)
                option = option.replace('_', '-')
                if val:
                    if (distro.has_setting(option)
                            and distro.get_setting_default(option) != val):
                        distro.set_setting_fuzzy(option, val)
                    elif (hypervisor.has_setting(option)
                          and hypervisor.get_setting_default(option) != val):
                        hypervisor.set_setting_fuzzy(option, val)

            chroot_dir = None
            if self.options.existing_chroot:
                distro.set_chroot_dir(self.options.existing_chroot)
                distro.call_hooks('preflight_check')
            else:
                if self.options.tmpfs is not None:
                    if str(self.options.tmpfs) == '-':
                        tmpfs_size = 1024
                    else:
                        tmpfs_size = int(self.options.tmpfs)
                    tmpfs_mount_point = util.set_up_tmpfs(
                        tmp_root=self.options.tmp_root, size=tmpfs_size)
                    chroot_dir = tmpfs_mount_point
                elif self.options.chroot_dir:
                    os.mkdir(self.options.chroot_dir)
                    chroot_dir = self.options.chroot_dir
                else:
                    chroot_dir = util.tmpdir(tmp_root=self.options.tmp_root)
                distro.set_chroot_dir(chroot_dir)
                distro.build_chroot()

            if self.options.only_chroot:
                print 'Chroot can be found in %s' % distro.chroot_dir
                sys.exit(0)

            self.set_disk_layout(optparser, hypervisor)
            hypervisor.install_os()

            os.mkdir(destdir)
            self.fix_ownership(destdir)
            hypervisor.finalise(destdir)
            # If chroot_dir is not None, it means we created it,
            # and if we reach here, it means the user didn't pass
            # --only-chroot. Hence, we need to remove it to clean
            # up after ourselves.
            if chroot_dir is not None and tmpfs_mount_point is None:
                util.run_cmd('rm', '-rf', '--one-file-system', chroot_dir)
        except VMBuilderException, e:
            logging.error(e)
            raise
Ejemplo n.º 26
0
    def get_index(self):
        """Index of the disk (starting from 0)"""
        return self.vm.filesystems.index(self)


def parse_size(size_str):
    """Takes a size like qemu-img would accept it and returns the size in MB"""
    try:
        return int(size_str)
    except ValueError, e:
        pass

    try:
        num = int(size_str[:-1])
    except ValueError, e:
        raise VMBuilderUserError("Invalid size: %s" % size_str)

    if size_str[-1:] == 'g' or size_str[-1:] == 'G':
        return num * 1024
    if size_str[-1:] == 'm' or size_str[-1:] == 'M':
        return num
    if size_str[-1:] == 'k' or size_str[-1:] == 'K':
        return num / 1024


str_to_type_map = {
    'ext2': TYPE_EXT2,
    'ext3': TYPE_EXT3,
    'xfs': TYPE_XFS,
    'swap': TYPE_SWAP,
    'linux-swap': TYPE_SWAP