Esempio n. 1
0
 def download_apt_file(self, pkg_name, pool_dir, fatal):
     if not self.cache:
         raise cliapp.AppException('No cache available.')
     pkg = self.cache[pkg_name]
     if not hasattr(pkg, 'versions'):
         if fatal:
             raise cliapp.AppException('%s has no available versions.' %
                                       pkg_name)
         return
     # Pick the highest version of the package, in case there are >1
     version = max(pkg.versions)
     if not version.uri:
         if fatal:
             raise cliapp.AppException('Not able to download %s' % pkg_name)
         return
     prefix = version.source_name[0]
     # pool_dir is just a base, need to add main/[index]/[name]
     if version.source_name[:3] == 'lib':
         prefix = version.source_name[:4]
     pkg_dir = os.path.join(pool_dir, prefix, version.source_name)
     if not os.path.exists(pkg_dir):
         os.makedirs(pkg_dir)
     try:
         version.fetch_binary(destdir=pkg_dir)
     except TypeError as exc:
         return
     except apt.package.FetchError as exc:
         raise cliapp.AppException('Unable to fetch %s: %s' %
                                   (pkg_name, exc))
Esempio n. 2
0
 def download_package(self, name, destdir):
     if not self.cache:
         raise cliapp.AppException('No cache available.')
     if name not in self.cache:
         raise cliapp.AppException('%s is not available' % name)
     pkg = self.cache[name]
     if not hasattr(pkg, 'versions'):
         raise cliapp.AppException('%s has no available versions.' % name)
     if len(pkg.versions) > 1:
         # files appear in this list without URIs.  This happened when
         # libfuse2 was in stretch/updates/main and in stretch/main; the
         # updates version had no uri.  was this coming from the outside
         # system's apt cache or something?
         versions = [p for p in pkg.versions if p.uri]
         versions.sort()
         version = versions[-1]
         print("Multiple versions returned for %s - using newest: %s" %
               (name, version))
     else:
         version = pkg.versions[0]
     if not version.uri:
         raise cliapp.AppException('Not able to download %s' % name)
     try:
         version.fetch_binary(destdir=destdir)
     except TypeError as exc:
         return None
     except apt.package.FetchError as exc:
         raise cliapp.AppException('Unable to fetch %s: %s' % (name, exc))
     filename = os.path.join(destdir,
                             os.path.basename(version.record['Filename']))
     if os.path.exists(filename):
         return filename
     return None
    def branch(self, args):
        '''Create a new system branch.

        Command line arguments:

        * `REPO` is a repository URL.
        * `NEW` is the name of the new system branch.
        * `OLD` is the point from which to branch, and defaults to `master`.

        This creates a new system branch. It needs to be run in an
        existing workspace (see `morph workspace`). It creates a new
        git branch in the clone of the repository in the workspace. The
        system branch will not be visible on the git server until you
        push your changes to the repository.

        Example:

            cd /src/workspace
            morph branch baserock:baserock/morphs jrandom/new-feature

        '''

        if len(args) not in [2, 3]:
            raise cliapp.AppException(
                'morph branch needs name of branch as parameter')

        root_url = args[0]
        system_branch = args[1]
        base_ref = 'master' if len(args) == 2 else args[2]
        origin_base_ref = 'origin/%s' % base_ref

        self._require_git_user_config()

        # Open the workspace first thing, so user gets a quick error if
        # we're not inside a workspace.
        ws = morphlib.workspace.open('.')

        # Make sure the root repository is in the local git repository
        # cache, and is up to date.
        lrc, rrc = morphlib.util.new_repo_caches(self.app)
        cached_repo = lrc.get_updated_repo(root_url)

        # Make sure the system branch doesn't exist yet.
        if cached_repo.ref_exists(system_branch):
            raise cliapp.AppException(
                'branch %s already exists in repository %s' %
                (system_branch, root_url))

        # Make sure the base_ref exists.
        cached_repo.resolve_ref(base_ref)

        with self._initializing_system_branch(ws, root_url, system_branch,
                                              cached_repo,
                                              base_ref) as (sb, gd):

            gd.branch(system_branch, base_ref)
            gd.checkout(system_branch)
            if gd.has_fat():
                gd.fat_init()
                gd.fat_pull()
Esempio n. 4
0
    def render_diff(self, state1, state2, view):
        try:
            if state1 == 'admin' or state2 == 'admin':
                raise cliapp.AppException(
                    'Browsing this branch is not permitted')

            state1 = self.state_cache.get(state1)
            state2 = self.state_cache.get(state2)

            if state1 == state2:
                raise cliapp.AppException('Need two different states')

            if state1.identifier == 'UNCOMMITTED':
                raw_tree1 = mustard.rawtree.Tree(state1)
                element_tree1 = mustard.elementtree.Tree(raw_tree1)
                element_tree2 = self.element_tree_cache.get(state2)

                return bottle.template('diff',
                                       tree=element_tree1,
                                       other_tree=element_tree2)
            else:
                content_id = (state1, state2, view)
                if not content_id in self.content:
                    tree1 = self.element_tree_cache.get(state1)
                    tree2 = self.element_tree_cache.get(state2)

                    self.content[content_id] = bottle.template(
                        'diff', tree=tree1, other_tree=tree2)
                else:
                    print('using cached rendering of (%s, %s, %s)' %
                          content_id)
                return self.content[content_id]
        except cliapp.AppException as err:
            return bottle.template('error', error=err)
Esempio n. 5
0
    def foreach(self, args):
        '''Run a command in each repository checked out in a system branch.

        Use -- before specifying the command to separate its arguments from
        Morph's own arguments.

        Command line arguments:

        * `--` indicates the end of option processing for Morph.
        * `COMMAND` is a command to run.
        * `ARGS` is a list of arguments or options to be passed onto
          `COMMAND`.

        This runs the given `COMMAND` in each git repository belonging
        to the current system branch that exists locally in the current
        workspace.  This can be a handy way to do the same thing in all
        the local git repositories.

        For example:

            morph foreach -- git push

        The above command would push any committed changes in each
        repository to the git server.

        '''

        if not args:
            raise cliapp.AppException('morph foreach expects a command to run')

        ws = morphlib.workspace.open('.')
        sb = morphlib.sysbranchdir.open_from_within('.')

        for gd in sorted(sb.list_git_directories(), key=lambda gd: gd.dirname):
            # Get the repository's original name
            # Continue in the case of error, since the previous iteration
            # worked in the case of the user cloning a repository in the
            # system branch's directory.
            try:
                repo = gd.get_config('morph.repository')
            except cliapp.AppException:
                continue

            self.app.output.write('%s\n' % repo)
            status, output, error = self.app.runcmd_unchecked(
                args, cwd=gd.dirname)
            self.app.output.write(output)
            if status != 0:
                self.app.output.write(error)
                pretty_command = ' '.join(cliapp.shell_quote(arg)
                                          for arg in args)
                raise cliapp.AppException(
                    'Command failed at repo %s: %s'
                    % (repo, pretty_command))
            self.app.output.write('\n')
            self.app.output.flush()
Esempio n. 6
0
 def process_args(self, args):
     if os.path.exists(self.settings['image_output']):
         raise cliapp.AppException("Image '%s' already exists" %
                                   self.settings['image_output'])
     if not self.settings['isolinux'] and not self.settings['grub']:
         raise cliapp.AppException(
             "You must enable at least one bootloader!")
     if self.settings['grub'] and self.settings['grub-loopback-only']:
         self.settings['grub'] = False
     if os.geteuid() != 0:
         sys.exit("You need to have root privileges to run this script.")
     # FIXME: cleanup on error.
     self.start_ops()
Esempio n. 7
0
    def prepare_apt(self):
        distroinfo = distro_info.DebianDistroInfo()
        if distroinfo.testing() == self.codename:
            self.suite = "testing"
        elif self.codename == "sid":
            self.suite = "unstable"
        else:
            self.suite = "stable"
        if not self.codename or not self.mirror:
            raise cliapp.AppException(
                "Misconfiguration: no codename or mirror set")
        state_dir = tempfile.mkdtemp()
        os.mkdir(os.path.join(state_dir, 'lists'))
        self.dirlist.append(state_dir)
        cache_dir = tempfile.mkdtemp()
        os.makedirs(os.path.join(cache_dir, 'archives', 'partial'))
        self.dirlist.append(cache_dir)
        etc_dir = tempfile.mkdtemp()
        os.mkdir(os.path.join(etc_dir, 'apt.conf.d'))
        os.mkdir(os.path.join(etc_dir, 'preferences.d'))
        os.mkdir(os.path.join(etc_dir, 'trusted.gpg.d'))
        copy_files('/etc/apt/trusted.gpg.d',
                   os.path.join(etc_dir, 'trusted.gpg.d'))
        with open(os.path.join(etc_dir, 'sources.list'), 'w') as sources:
            sources.write(
                'deb %s %s %s\n' %
                (self.mirror, self.codename, ' '.join(self.components)))
        self.dirlist.append(etc_dir)
        updates = {
            'APT::Architecture': str(self.architecture),
            'APT::Architectures': str(self.architecture),
            'Dir::State': state_dir,
            'Dir::Cache': cache_dir,
            'Dir::Etc': etc_dir,
        }
        for key, value in updates.items():
            try:
                apt_pkg.config[key] = value  # pylint: disable=no-member
            except TypeError as exc:
                print(key, value, exc)
            continue

        self.cache = apt.cache.Cache()
        try:
            self.cache.update()
            self.cache.open()
        except apt.cache.FetchFailedException as exc:
            raise cliapp.AppException('Unable to update cache: %s' % exc)
        if not os.path.exists(self.destdir):
            raise cliapp.AppException(
                'Destination directory %s does not exist' % self.destdir)
Esempio n. 8
0
 def validate_deployment_options(self, env_vars, all_deployments,
                                 all_subsystems):
     for var in env_vars:
         for subsystem in all_subsystems:
             if subsystem == var:
                 raise cliapp.AppException(
                     'Cannot directly deploy subsystems. Create a top '
                     'level deployment for the subsystem %s instead.' %
                     subsystem)
             if (not any(deployment in var
                         for deployment in all_deployments)
                     and not subsystem in var):
                 raise cliapp.AppException(
                     'Variable referenced a non-existent deployment '
                     'name: %s' % var)
Esempio n. 9
0
 def download_udebs(self, exclude_list):
     if not self.cache:
         raise cliapp.AppException('No cache available.')
     main_pool = os.path.join(self.destdir, '..', 'pool', 'main')
     if not os.path.exists(main_pool): os.makedirs(main_pool)
     for pkg_name in self.cache.keys():
         prefix = pkg_name[0]
         # destdir is just a base, needs pool/main/[index]/[name]
         if pkg_name[:3] == 'lib':
             prefix = pkg_name[:4]
         pkg_dir = os.path.join(main_pool, prefix, pkg_name)
         if pkg_name in exclude_list:
             continue
         pkg = self.cache[pkg_name]
         if not hasattr(pkg, 'versions'):
             continue
         if len(pkg.versions) > 1:
             pkg.version_list.sort(apt_pkg.version_compare)  # pylint: disable=no-member
             version = pkg.version_list[0]
             print("Multiple versions returned for %s - using newest: %s" %
                   (pkg_name, pkg.version_list[0]))
         else:
             version = pkg.versions[0]
         if not version.uri:
             continue
         os.makedirs(pkg_dir)
         try:
             version.fetch_binary(destdir=pkg_dir)
         except TypeError as exc:
             continue
         except apt.package.FetchError as exc:
             raise cliapp.AppException('Unable to fetch %s: %s' %
                                       (pkg_name, exc))
     # FIXME: still need a Packages file and Release.
     # Horribe hardcoded mess --------------------------------------
     packages = check_output([
         'apt-ftparchive', '-o', 'Packages::Extensions=.udeb', 'packages',
         os.path.join(self.destdir, '..', 'pool', 'main')
     ])
     meta_dir = os.path.normpath(
         os.path.join(self.destdir, '..', 'dists', self.codename, 'main',
                      'debian-installer',
                      'binary-%s' % (self.architecture, )))
     if not os.path.exists(meta_dir):
         os.makedirs(meta_dir)
     packages = re.sub(r"/tmp.*pool", "pool", packages)
     with open(os.path.join(meta_dir, 'Packages'), 'w') as pkgout:
         pkgout.write(packages)
Esempio n. 10
0
def install_isolinux(cdroot, mirror, suite, architecture, bootconfig):
    """
    Download and unpack the correct syslinux-common
    and isolinux packages for isolinux support.
    ISOLINUX looks first in boot/isolinux/ then isolinux/ then /
    This function puts all files into isolinux/
    """
    destdir = tempfile.mkdtemp()
    handler = get_apt_handler(destdir, mirror, suite, architecture)
    filename = handler.download_package('syslinux-common', destdir)
    # these files are put directly into cdroot/isolinux
    syslinux_files = [
        'ldlinux.c32', 'libcom32.c32', 'vesamenu.c32',
        'libutil.c32', 'libmenu.c32', 'libgpl.c32', 'hdt.c32'
    ]
    if filename:
        runcmd(['dpkg', '-x', filename, destdir])
        for syslinux_file in syslinux_files:
            shutil.copyfile(
                os.path.join(destdir, "usr/lib/syslinux/modules/bios/%s" % syslinux_file),
                "%s/%s" % (cdroot, syslinux_file))
        shutil.copyfile(
            os.path.join(destdir, "usr/lib/syslinux/memdisk"),
            "%s/memdisk" % (cdroot,))
    else:
        handler.clean_up_apt()
        shutil.rmtree(destdir)
        raise cliapp.AppException('Unable to download syslinux-common')
    filename = handler.download_package('isolinux', destdir)
    if filename:
        runcmd(['dpkg', '-x', filename, destdir])
        shutil.copyfile(
            os.path.join(destdir, "usr/lib/ISOLINUX/isolinux.bin"),
            "%s/isolinux.bin" % cdroot)
    else:
        handler.clean_up_apt()
        shutil.rmtree(destdir)
        raise cliapp.AppException('Unable to download isolinux')
    handler.clean_up_apt()
    shutil.rmtree(destdir)

    cfg = generate_cfg(bootconfig)
    with open("%s/%s" % (cdroot, "menu.cfg"), "w") as cfgout:
        cfgout.write(cfg)

    # Fix the menu display size in stdmeny.cfg (#861421)
    runcmd(['sed', '-i', 's,menu rows 12,menu rows 8,g',
                os.path.join(cdroot, 'stdmenu.cfg')])
Esempio n. 11
0
    def _find_or_create_lorry_file(self, kind, name):
        # Note that the lorry file may already exist for 'name', but lorry
        # files are named for project name rather than package name. In this
        # case we will generate the lorry, and try to add it to the set, at
        # which point LorrySet will notice the existing one and merge the two.
        lorry = self.lorry_set.find_lorry_for_package(kind, name)

        if lorry is None:
            lorry = self._generate_lorry_for_package(kind, name)

            if len(lorry) != 1:
                raise Exception(
                    'Expected generated lorry file with one entry.')

            lorry_filename = lorry.keys()[0]

            if '/' in lorry_filename:
                # We try to be a bit clever and guess that if there's a prefix
                # in the name, e.g. 'ruby-gems/chef' then it should go in a
                # mega-lorry file, such as ruby-gems.lorry.
                parts = lorry_filename.split('/', 1)
                lorry_filename = parts[0]

            if lorry_filename == '':
                raise cliapp.AppException('Invalid lorry data for %s: %s' %
                                          (name, lorry))

            self.lorry_set.add(lorry_filename, lorry)
        else:
            lorry_filename = lorry.keys()[0]
            logging.info('Found existing lorry file for %s: %s', name,
                         lorry_filename)

        return lorry
Esempio n. 12
0
 def configure_apt(self):
     rootdir = self.devices['rootdir']
     if not self.settings['configure-apt'] or not self.settings[
             'apt-mirror']:
         return
     if not rootdir:
         raise cliapp.AppException("rootdir not set")
     # use the distribution and mirror to create an apt source
     self.message("Configuring apt to use distribution and mirror")
     conf = os.path.join(str(rootdir), 'etc', 'apt', 'sources.list.d',
                         'base.list')
     logging.debug('configure apt %s', conf)
     mirror = self.settings['mirror']
     if self.settings['apt-mirror']:
         mirror = self.settings['apt-mirror']
         self.message("Setting apt mirror to %s" % mirror)
     os.unlink(os.path.join(str(rootdir), 'etc', 'apt', 'sources.list'))
     source = open(conf, 'w')
     line = 'deb %s %s main\n' % (mirror, self.settings['distribution'])
     source.write(line)
     line = '#deb-src %s %s main\n' % (mirror,
                                       self.settings['distribution'])
     source.write(line)
     source.close()
     # ensure the apt sources have valid lists
     runcmd(['chroot', rootdir, 'apt-get', '-qq', 'update'])
Esempio n. 13
0
 def check_ssh_connectivity(self, ssh_host):
     try:
         cliapp.ssh_runcmd(ssh_host, ['true'])
     except cliapp.AppException as e:
         logging.error("Error checking SSH connectivity: %s", str(e))
         raise cliapp.AppException('Unable to SSH to %s: %s' %
                                   (ssh_host, e))
Esempio n. 14
0
    def run_system_integration_commands(self, rootdir):  # pragma: no cover
        ''' Run the system integration commands '''

        sys_integration_dir = os.path.join(rootdir, SYSTEM_INTEGRATION_PATH)
        if not os.path.isdir(sys_integration_dir):
            return

        env = {'PATH': '/bin:/usr/bin:/sbin:/usr/sbin'}

        self.app.status(msg='Running the system integration commands')

        to_mount = (
            ('dev/shm', 'tmpfs', 'none'),
            ('tmp', 'tmpfs', 'none'),
        )
        try:
            for bin in sorted(os.listdir(sys_integration_dir)):
                argv = [os.path.join(SYSTEM_INTEGRATION_PATH, bin)]
                container_config = dict(root=rootdir,
                                        mounts=to_mount,
                                        mount_proc=True)
                cmdline = morphlib.util.containerised_cmdline(
                    argv, **container_config)
                exit, out, err = self.app.runcmd_unchecked(cmdline, env=env)
                if exit != 0:
                    logging.debug('Command returned code %i', exit)
                    msg = error_message_for_containerised_commandline(
                        argv, err, container_config)
                    raise cliapp.AppException(msg)
        except BaseException, e:
            self.app.status(
                msg='Error while running system integration commands',
                error=True)
            raise
Esempio n. 15
0
    def serialise_artifact(self, args):
        '''Internal use only: Serialise Artifact build graph as JSON.'''

        distbuild.add_crash_conditions(self.app.settings['crash-condition'])

        if len(args) not in [3, 4]:
            raise cliapp.AppException(
                'This command takes a repo/ref/morph triplet, and optionally '
                'a ref name.')

        repo_name, ref, morph_name = args[0:3]

        if len(args) == 4:
            original_ref = args[3]
        else:
            original_ref = ref

        filename = morphlib.util.sanitise_morphology_path(morph_name)
        build_command = morphlib.buildcommand.BuildCommand(self.app)
        srcpool = build_command.create_source_pool(repo_name,
                                                   ref,
                                                   filename,
                                                   original_ref=original_ref)
        artifact = build_command.resolve_artifacts(srcpool)
        self.app.output.write(distbuild.serialise_artifact(artifact))
        self.app.output.write('\n')
Esempio n. 16
0
 def gen_fstab(self):
     rootdir = self.devices['rootdir']
     if not rootdir:
         raise cliapp.AppException("rootdir not set")
     # https://bbs.archlinux.org/viewtopic.php?id=220215 and
     # https://stackoverflow.com/questions/36379789/python-subprocess-unable-to-escape-quotes
     runcmd("bash -c 'genfstab -U %s >> %s/etc/fstab'" % (rootdir, rootdir),
            shell=True)
Esempio n. 17
0
 def find(pattern):
     dirname = os.path.join(rootdir, 'boot')
     basenames = os.listdir(dirname)
     logging.debug('find: %s', basenames)
     for basename in basenames:
         if re.search(pattern, basename):
             return os.path.join('boot', basename)
     raise cliapp.AppException('Cannot find match: %s' % pattern)
Esempio n. 18
0
    def upgrade(self, args):
        '''Upgrade an existing set of instances using built images.

        See `morph help deploy` for documentation.

        '''

        if not args:
            raise cliapp.AppException(
                'Too few arguments to upgrade command (see `morph help '
                'deploy`)')

        if self.app.settings['upgrade']:
            raise cliapp.AppException(
                'Running `morph upgrade --upgrade` does not make sense.')

        self.app.settings['upgrade'] = True
        self.deploy(args)
Esempio n. 19
0
    def branch_from_image(self, args):
        '''Produce a branch of an existing system image.

        Given the metadata specified by --metadata-dir, create a new
        branch then petrify it to the state of the commits at the time
        the system was built.

        If --metadata-dir is not specified, it defaults to your currently
        running system.

        '''
        if len(args) != 1:
            raise cliapp.AppException(
                "branch-from-image needs exactly 1 argument "
                "of the new system branch's name")
        system_branch = args[0]
        metadata_path = self.app.settings['metadata-dir']
        alias_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
            self.app.settings['repo-alias'])

        self._require_git_user_config()

        ws = morphlib.workspace.open('.')

        system, metadata = self._load_system_metadata(metadata_path)
        resolved_refs = dict(self._resolve_refs_from_metadata(alias_resolver,
                                                              metadata))
        self.app.status(msg='Resolved refs: %r' % resolved_refs)
        base_ref = system['sha1']
        # The previous version would fall back to deducing this from the repo
        # url and the repo alias resolver, but this does not always work, and
        # new systems always have repo-alias in the metadata
        root_url = system['repo-alias']

        lrc, rrc = morphlib.util.new_repo_caches(self.app)
        cached_repo = lrc.get_updated_repo(root_url)


        with self._initializing_system_branch(
            ws, root_url, system_branch, cached_repo, base_ref) as (sb, gd):

            # TODO: It's nasty to clone to a sha1 then create a branch
            #       of that sha1 then check it out, a nicer API may be the
            #       initial clone not checking out a branch at all, then
            #       the user creates and checks out their own branches
            gd.branch(system_branch, base_ref)
            gd.checkout(system_branch)

            loader = morphlib.morphloader.MorphologyLoader()
            morphs = self._load_all_sysbranch_morphologies(sb, loader)

            morphs.repoint_refs(sb.root_repository_url,
                                sb.system_branch_name)

            morphs.petrify_chunks(resolved_refs)

            self._save_dirty_morphologies(loader, sb, morphs.morphologies)
Esempio n. 20
0
 def set_hostname(self):
     rootdir = self.devices['rootdir']
     if not rootdir:
         raise cliapp.AppException("rootdir not set")
     hostname = self.settings['hostname']
     etc_hosts_template = self.env.get_template("hosts.j2")
     etc_hosts = os.path.join(str(rootdir), 'etc', 'hosts')
     etc_hosts_template.stream(settings_hostname=hostname).dump(etc_hosts)
     with open(os.path.join(str(rootdir), 'etc', 'hostname'), 'w') as fhost:
         fhost.write('%s\n' % hostname)
Esempio n. 21
0
 def install_mbr(self):
     if not self.settings['mbr'] or not self.settings['extlinux']:
         return
     if os.path.exists("/sbin/install-mbr"):
         self.message('Installing MBR')
         runcmd(['install-mbr', self.settings['image']])
     else:
         msg = "mbr enabled but /sbin/install-mbr not found" \
               " - please install the mbr package."
         raise cliapp.AppException(msg)
Esempio n. 22
0
 def cat_file(self, ref, filename):
     output = {
         'e28a23812eadf2fce6583b8819b9c5dbd36b9fb9:foo.morph':
         self.EXAMPLE_MORPH
     }
     try:
         return output['%s:%s' % (ref, filename)]
     except KeyError:
         raise cliapp.AppException('git cat-file blob %s:%s' %
                                   (ref, filename))
Esempio n. 23
0
 def run_extlinux_install(self, rootdir):
     if os.path.exists("/usr/bin/extlinux"):
         self.message('Running extlinux --install')
         runcmd(['extlinux', '--install', rootdir])
         runcmd(['sync'])
         time.sleep(2)
     else:
         msg = "extlinux enabled but /usr/bin/extlinux not found" \
               " - please install the extlinux package."
         raise cliapp.AppException(msg)
Esempio n. 24
0
def check_url(url):
    """
    Check that constructed URLs actually give a HTTP 200.
    """
    res = requests.head(url, allow_redirects=True, timeout=30)
    if res.status_code != requests.codes.OK:  # pylint: disable=no-member
        # try using (the slower) get for services with broken redirect support
        res = requests.get(url, allow_redirects=True, stream=True, timeout=30)
        if res.status_code != requests.codes.OK:  # pylint: disable=no-member
            raise cliapp.AppException("Resources not available at '%s'" % url)
Esempio n. 25
0
 def created_disk_image(self, location):
     size = self.get_disk_size()
     if not size:
         raise cliapp.AppException('DISK_SIZE is not defined')
     self.create_raw_disk_image(location, size)
     try:
         yield
     except BaseException:
         os.unlink(location)
         raise
Esempio n. 26
0
    def import_omnibus(self, args):
        '''Import a software component from an Omnibus project.

        Omnibus is a tool for generating application bundles for various
        platforms. See <https://github.com/opscode/omnibus> for more
        information.

        '''
        if len(args) != 3:
            raise cliapp.AppException(
                'Please give the location of the Omnibus definitions repo, '
                'and the name of the project and the top-level software '
                'component.')

        def running_inside_bundler():
            return 'BUNDLE_GEMFILE' in os.environ

        def command_to_run_python_in_directory(directory, args):
            # Bundler requires that we run it from the Omnibus project
            # directory. That messes up any relative paths the user may have
            # passed on the commandline, so we do a bit of a hack to change
            # back to the original directory inside the `bundle exec` process.
            return "cd %s; exec python %s" % (pipes.quote(directory), ' '.join(
                map(pipes.quote, args)))

        def reexecute_self_with_bundler(path):
            script = sys.argv[0]

            logging.info(
                'Reexecuting %s within Bundler, so that extensions '
                'use the correct dependencies for Omnibus and the '
                'Omnibus project definitions.', script)
            command = command_to_run_python_in_directory(os.getcwd(), sys.argv)

            logging.debug('Running: `bundle exec %s` in dir %s', command, path)
            os.chdir(path)
            os.execvp('bundle', [script, 'exec', command])

        # Omnibus definitions are spread across multiple repos, and there is
        # no stability guarantee for the definition format. The official advice
        # is to use Bundler to execute Omnibus, so let's do that.
        if not running_inside_bundler():
            reexecute_self_with_bundler(args[0])

        definitions_dir = args[0]
        project_name = args[1]

        loop = baserockimport.mainloop.ImportLoop(app=self,
                                                  goal_kind='omnibus',
                                                  goal_name=args[2],
                                                  goal_version='master')
        loop.enable_importer('omnibus',
                             extra_args=[definitions_dir, project_name])
        loop.enable_importer('rubygems')
        loop.run()
Esempio n. 27
0
 def _help_topic(self, topic):
     if topic in self.subcommands:
         usage = self._format_usage_for(topic)
         description = self._format_subcommand_help(topic)
         text = '%s\n\n%s' % (usage, description)
         self.output.write(text)
     elif topic in extensions.list_extensions():
         name, kind = os.path.splitext(topic)
         try:
             with extensions.get_extension_filename(
                     name, kind + '.help', executable=False) as fname:
                 with open(fname, 'r') as f:
                     help_data = morphlib.yamlparse.load(f.read())
                     print help_data['help']
         except extensions.ExtensionError:
             raise cliapp.AppException(
                 'Help not available for extension %s' % topic)
     else:
         raise cliapp.AppException('Unknown subcommand or extension %s' %
                                   topic)
Esempio n. 28
0
    def get_environment_boolean(self, variable):
        '''Parse a yes/no boolean passed through the environment.'''

        value = os.environ.get(variable, 'no').lower()
        if value in ['no', '0', 'false']:
            return False
        elif value in ['yes', '1', 'true']:
            return True
        else:
            raise cliapp.AppException('Unexpected value for %s: %s' %
                                      (variable, value))
Esempio n. 29
0
    def install_bootloader(self, real_root):
        install_function_dict = {
            'extlinux': self.install_bootloader_extlinux,
        }

        install_type = self.get_bootloader_install()
        if install_type in install_function_dict:
            install_function_dict[install_type](real_root)
        elif install_type != 'none':
            raise cliapp.AppException('Invalid BOOTLOADER_INSTALL %s' %
                                      install_type)
Esempio n. 30
0
File: app.py Progetto: nowster/morph
    def itertriplets(self, args):
        '''Generate repo, ref, filename triples from args.'''

        if (len(args) % 3) != 0:
            raise cliapp.AppException('Argument list must have full triplets')

        while args:
            assert len(args) >= 2, args
            yield (args[0], args[1],
                   morphlib.util.sanitise_morphology_path(args[2]))
            args = args[3:]