Exemplo n.º 1
0
 def _install_upstream_deb(self):
     log.info('Found upstream deb, installing that instead')
     filename = os.path.basename(self.config.getopt('upstream_deb'))
     try:
         utils.container_run(
             self.container_name,
             'sudo dpkg -i /home/ubuntu/.cloud-install/{}'.format(filename))
     except:
         # Make sure deps are installed if any new ones introduced by
         # the upstream packaging.
         utils.container_run(self.container_name,
                             'sudo apt-get install -qyf')
 def _install_upstream_deb(self):
     log.info('Found upstream deb, installing that instead')
     filename = os.path.basename(self.config.getopt('upstream_deb'))
     try:
         utils.container_run(
             self.container_name,
             'sudo dpkg -i /home/ubuntu/.cloud-install/{}'.format(
                 filename))
     except:
         # Make sure deps are installed if any new ones introduced by
         # the upstream packaging.
         utils.container_run(
             self.container_name, 'sudo apt-get install -qyf')
    def cloud_init_finished(self):
        """checks cloud-init result.json in container to find out status

        returns True if cloud-init finished with no errors, False if
        it's not done yet, and raises an exception if it had errors.
        """
        cmd = 'sudo cat /run/cloud-init/result.json'
        try:
            result_json = utils.container_run(self.container_name, cmd)
            # convert from bytes for json to process
            result_json = result_json.decode("utf-8")
            log.debug(result_json)
        except:
            log.debug("Waiting for cloud-init status result")
            return False

        if result_json == '':
            return False

        ret = json.loads(result_json)
        errors = ret['v1']['errors']
        if len(errors):
            log.error("Container cloud-init finished with "
                      "errors: {}".format(errors))
            # FIXME: Log errors for now, don't be fatal as the main
            # error is coming from a pollinate command unable
            # to run which doesn't seem to effect the installer.
            # raise Exception("Container cloud-init returned errors")
        return True
Exemplo n.º 4
0
 def read_juju_log(self):
     try:
         return utils.container_run(self.container_name, 'tail -n 10 '
                                    '/var/log/juju-ubuntu-local'
                                    '/all-machines.log')
     except Exception:
         return "Waiting..."
Exemplo n.º 5
0
 def read_cloud_init_output(self):
     try:
         s = utils.container_run(self.container_name, 'tail -n 10 '
                                 '/var/log/cloud-init-output.log')
         return s.replace('\r', '')
     except Exception:
         return "Waiting..."
    def cloud_init_finished(self, tries, maxlenient=20):
        """checks cloud-init result.json in container to find out status

        For the first `maxlenient` tries, it treats a container with
        no IP and SSH errors as non-fatal, assuming initialization is
        still ongoing. Afterwards, will raise exceptions for those
        errors, so as not to loop forever.

        returns True if cloud-init finished with no errors, False if
        it's not done yet, and raises an exception if it had errors.

        """
        cmd = 'sudo cat /run/cloud-init/result.json'
        try:
            result_json = utils.container_run(self.container_name, cmd)

        except utils.NoContainerIPException as e:
            log.debug("Container has no IPs according to lxc-info. "
                      "Will retry.")
            return False

        except utils.ContainerRunException as e:
            _, returncode = e.args
            if returncode == 255:
                if tries < maxlenient:
                    log.debug("Ignoring initial SSH error.")
                    return False
                raise e
            if returncode == 1:
                # the 'cat' did not find the file.
                if tries < 1:
                    log.debug("Waiting for cloud-init status result")
                return False
            else:
                log.debug("Unexpected return code from reading "
                          "cloud-init status in container.")
                raise e

        if result_json == '':
            return False

        try:
            ret = json.loads(result_json)
        except Exception as e:
            if tries < maxlenient + 10:
                log.debug("exception trying to parse '{}'"
                          " - retrying".format(result_json))
                return False

            log.error(str(e))
            log.debug("exception trying to parse '{}'".format(result_json))
            raise e

        errors = ret['v1']['errors']
        if len(errors):
            log.error("Container cloud-init finished with "
                      "errors: {}".format(errors))
            raise Exception("Top-level container OS did not initialize "
                            "correctly.")
        return True
Exemplo n.º 7
0
    def do_install(self):
        self.display_controller.info_message("Building environment")
        if os.path.exists(self.container_abspath):
            # Container exists, handle return code in installer
            raise Exception("Container exists, please uninstall or kill "
                            "existing cloud before proceeding.")

        utils.ssh_genkey()

        # Preparations
        self.prep_userdata()

        # setup charm configurations
        utils.render_charm_config(self.config, self.opts)

        self.prep_juju()

        # Set permissions
        self.set_perms()

        # Start container
        self.create_container_and_wait()

        # Install local copy of openstack installer if provided
        if self.opts.upstream_deb and os.path.isfile(self.opts.upstream_deb):
            shutil.copy(self.opts.upstream_deb, self.config.cfg_path)
            self._install_upstream_deb()

        # start the party
        cloud_status_bin = ['openstack-status']
        self.display_controller.info_message("Bootstrapping Juju")
        self.start_task("Bootstrapping Juju")
        utils.container_run(
            self.container_name, "JUJU_HOME={} juju bootstrap".format(
                self.config.cfg_path))
        utils.container_run(
            self.container_name, "JUJU_HOME={} juju status".format(
                self.config.cfg_path))

        if self.opts.install_only:
            log.info("Done installing, stopping here per --install-only.")
            sys.exit(0)

        self.display_controller.info_message("Starting cloud deployment")
        utils.container_run_status(
            self.container_name, " ".join(cloud_status_bin))
Exemplo n.º 8
0
    def cloud_init_finished(self, tries, maxlenient=20):
        """checks cloud-init result.json in container to find out status

        For the first `maxlenient` tries, it treats a container with
        no IP and SSH errors as non-fatal, assuming initialization is
        still ongoing. Afterwards, will raise exceptions for those
        errors, so as not to loop forever.

        returns True if cloud-init finished with no errors, False if
        it's not done yet, and raises an exception if it had errors.

        """
        cmd = 'sudo cat /run/cloud-init/result.json'
        try:
            result_json = utils.container_run(self.container_name, cmd)

        except utils.NoContainerIPException as e:
            log.debug("Container has no IPs according to lxc-info. "
                      "Will retry.")
            return False

        except utils.ContainerRunException as e:
            _, returncode = e.args
            if returncode == 255:
                if tries < maxlenient:
                    log.debug("Ignoring initial SSH error.")
                    return False
                raise e
            if returncode == 1:
                # the 'cat' did not find the file.
                if tries < 1:
                    log.debug("Waiting for cloud-init status result")
                return False
            else:
                log.debug("Unexpected return code from reading "
                          "cloud-init status in container.")
                raise e

        if result_json == '':
            return False

        ret = json.loads(result_json)
        errors = ret['v1']['errors']
        if len(errors):
            log.error("Container cloud-init finished with "
                      "errors: {}".format(errors))
            raise Exception("Top-level container OS did not initialize "
                            "correctly.")
        return True
    def do_install(self):
        self.display_controller.info_message("Building environment")
        if os.path.exists(self.container_abspath):
            # Container exists, handle return code in installer
            raise Exception("Container exists, please uninstall or kill "
                            "existing cloud before proceeding.")

        utils.ssh_genkey()

        # Prepare cloud-init file for creation
        self.prep_userdata()

        # Start container
        self.create_container_and_wait()

        # configure juju environment for bootstrap
        single_env = utils.load_template('juju-env/single.yaml')
        single_env_modified = single_env.render(
            openstack_password=self.config.openstack_password)
        utils.spew('/tmp/single.yaml', single_env_modified)
        utils.container_run(self.container_name,
                            'mkdir -p .juju')
        utils.container_cp(self.container_name,
                           '/tmp/single.yaml',
                           '.juju/environments.yaml')

        # Set permissions
        self.copy_installdata_and_set_perms()

        # start the party
        cloud_status_bin = ['openstack-status']
        if self.opts.enable_swift:
            cloud_status_bin.append('--enable-swift')
        self.display_controller.info_message("Bootstrapping Juju ..")
        self.start_task("Starting Juju server")
        utils.container_run(self.container_name, "juju bootstrap")
        utils.container_run(self.container_name, "juju status")

        if self.opts.install_only:
            log.info("Done installing, stopping here per --install-only.")
            sys.exit(0)

        self.display_controller.info_message("Starting cloud deployment ..")
        utils.container_run_status(
            self.container_name, " ".join(cloud_status_bin))
    def copy_installdata_and_set_perms(self):
        """ copies install data and sets permissions on files/dirs
        """
        try:
            utils.chown(self.config.cfg_path,
                        utils.install_user(),
                        utils.install_user(),
                        recursive=True)
        except:
            raise SingleInstallException(
                "Unable to set ownership for {}".format(self.config.cfg_path))

        # copy over the rest of our installation data from host
        # and setup permissions

        # setup charm configurations
        charm_conf = utils.load_template('charmconf.yaml')
        charm_conf_modified = charm_conf.render(
            openstack_password=self.config.openstack_password)
        utils.spew(os.path.join(self.config.cfg_path,
                                'charmconf.yaml'),
                   charm_conf_modified)

        utils.container_run(
            self.container_name, 'mkdir -p .cloud-install')
        utils.container_run(
            self.container_name, 'sudo mkdir -p /etc/openstack')

        utils.container_cp(self.container_name,
                           os.path.join(
                               utils.install_home(), '.cloud-install/*'),
                           '.cloud-install/.')

        # our ssh keys too
        utils.container_cp(self.container_name,
                           os.path.join(utils.install_home(),
                                        '.ssh/id_rsa*'),
                           '.ssh/.')
        utils.container_run(self.container_name, "chmod 600 .ssh/id_rsa*")
Exemplo n.º 11
0
    def do_install(self):
        self.display_controller.status_info_message("Building environment")
        if os.path.exists(self.container_abspath):
            raise Exception("Container exists, please uninstall or kill "
                            "existing cloud before proceeding.")

        # check for deb early, will actually install it later
        upstream_deb = self.config.getopt('upstream_deb')
        if upstream_deb and not os.path.isfile(upstream_deb):
            raise Exception("Upstream deb '{}' "
                            "not found.".format(upstream_deb))

        utils.ssh_genkey()

        self.prep_userdata()

        utils.render_charm_config(self.config)

        self.prep_juju()

        self.set_perms()

        self.create_container_and_wait()

        # Copy over host ssh keys
        utils.container_cp(self.container_name,
                           os.path.join(utils.install_home(), '.ssh/id_rsa*'),
                           '.ssh/.')

        # Install local copy of openstack installer if provided
        if upstream_deb:
            shutil.copy(upstream_deb, self.config.cfg_path)
            self._install_upstream_deb()

        # Stop before we attempt to access container
        if self.config.getopt('install_only'):
            log.info("Done installing, stopping here per --install-only.")
            self.config.setopt('install_only', True)
            self.loop.exit(0)

        # Update jujus no-proxy setting if applicable
        if self.config.getopt('http_proxy') or \
           self.config.getopt('https_proxy'):
            log.info("Updating juju environments for proxy support")
            lxc_net = self.config.getopt('lxc_network')
            self.config.update_environments_yaml(
                key='no-proxy',
                val='{},localhost,{}'.format(
                    utils.container_ip(self.container_name),
                    netutils.get_ip_set(lxc_net)))

        # start the party
        cloud_status_bin = ['openstack-status']
        self.tasker.start_task("Bootstrapping Juju")
        utils.container_run(self.container_name,
                            "{0} juju bootstrap".format(
                                self.config.juju_home(use_expansion=True)),
                            use_ssh=True)
        utils.container_run(
            self.container_name,
            "{0} juju status".format(
                self.config.juju_home(use_expansion=True)),
            use_ssh=True)
        self.tasker.stop_current_task()

        self.display_controller.status_info_message(
            "Starting cloud deployment")
        utils.container_run_status(
            self.container_name, " ".join(cloud_status_bin), self.config)
Exemplo n.º 12
0
    def create_container_and_wait(self):
        """ Creates container and waits for cloud-init to finish
        """
        self.tasker.start_task("Creating Container")

        utils.container_create(self.container_name, self.userdata)

        with open(os.path.join(self.container_abspath, 'fstab'), 'w') as f:
            f.write("{0} {1} none bind,create=dir\n".format(
                self.config.cfg_path,
                'home/ubuntu/.cloud-install'))
            f.write("/var/cache/lxc var/cache/lxc none bind,create=dir\n")
            # Detect additional charm plugins and make available to the
            # container.
            charm_plugin_dir = self.config.getopt('charm_plugin_dir')
            if charm_plugin_dir \
               and self.config.cfg_path not in charm_plugin_dir:
                plug_dir = os.path.abspath(
                    self.config.getopt('charm_plugin_dir'))
                plug_base = os.path.basename(plug_dir)
                f.write("{d} home/ubuntu/{m} "
                        "none bind,create=dir\n".format(d=plug_dir,
                                                        m=plug_base))

            extra_mounts = os.getenv("EXTRA_BIND_DIRS", None)
            if extra_mounts:
                for d in extra_mounts.split(','):
                    mountpoint = os.path.basename(d)
                    f.write("{d} home/ubuntu/{m} "
                            "none bind,create=dir\n".format(d=d,
                                                            m=mountpoint))

        # update container config
        with open(os.path.join(self.container_abspath, 'config'), 'a') as f:
            f.write("lxc.mount.auto = cgroup:mixed\n"
                    "lxc.start.auto = 1\n"
                    "lxc.start.delay = 5\n"
                    "lxc.mount = {}/fstab\n".format(self.container_abspath))

        lxc_logfile = os.path.join(self.config.cfg_path, 'lxc.log')

        utils.container_start(self.container_name, lxc_logfile)

        utils.container_wait_checked(self.container_name,
                                     lxc_logfile)

        tries = 0
        while not self.cloud_init_finished(tries):
            time.sleep(1)
            tries += 1

        # we do this here instead of using cloud-init, for greater
        # control over ordering
        log.debug("Container started, cloud-init done.")

        lxc_network = self.write_lxc_net_config()
        self.add_static_route(lxc_network)

        self.tasker.start_task("Installing Dependencies")
        log.debug("Installing openstack & openstack-single directly, "
                  "and juju-local, libvirt-bin and lxc via deps")
        utils.container_run(self.container_name,
                            "env DEBIAN_FRONTEND=noninteractive apt-get -qy "
                            "-o Dpkg::Options::=--force-confdef "
                            "-o Dpkg::Options::=--force-confold "
                            "install openstack openstack-single")
Exemplo n.º 13
0
 def _install_upstream_deb(self):
     log.debug('Found upstream deb, installing that instead')
     filename = os.path.basename(self.opts.upstream_deb)
     utils.container_run(
         self.container_name, 'sudo dpkg -i .cloud-install/{}'.format(
             filename))
Exemplo n.º 14
0
    def do_install(self):
        self.display_controller.status_info_message("Building environment")
        if os.path.exists(self.container_abspath):
            raise Exception("Container exists, please uninstall or kill "
                            "existing cloud before proceeding.")

        # check for deb early, will actually install it later
        upstream_deb = self.config.getopt('upstream_deb')
        if upstream_deb and not os.path.isfile(upstream_deb):
            raise Exception("Upstream deb '{}' "
                            "not found.".format(upstream_deb))

        utils.ssh_genkey()

        self.prep_userdata()

        utils.render_charm_config(self.config)

        self.prep_juju()

        self.set_perms()

        self.create_container_and_wait()

        # Copy over host ssh keys
        utils.container_cp(self.container_name,
                           os.path.join(utils.install_home(), '.ssh/id_rsa*'),
                           '.ssh/.')

        # Install local copy of openstack installer if provided
        if upstream_deb:
            shutil.copy(upstream_deb, self.config.cfg_path)
            self._install_upstream_deb()

        # Stop before we attempt to access container
        if self.config.getopt('install_only'):
            log.info("Done installing, stopping here per --install-only.")
            self.config.setopt('install_only', True)
            self.loop.exit(0)

        # Update jujus no-proxy setting if applicable
        if self.config.getopt('http_proxy') or \
           self.config.getopt('https_proxy'):
            log.info("Updating juju environments for proxy support")
            lxc_net = self.config.getopt('lxc_network')
            self.config.update_environments_yaml(
                key='no-proxy',
                val='{},localhost,{}'.format(
                    utils.container_ip(self.container_name),
                    netutils.get_ip_set(lxc_net)))

        # start the party
        cloud_status_bin = ['openstack-status']
        self.tasker.start_task("Bootstrapping Juju")
        utils.container_run(self.container_name,
                            "{0} juju bootstrap".format(
                                self.config.juju_home(use_expansion=True)),
                            use_ssh=True)
        utils.container_run(self.container_name,
                            "{0} juju status".format(
                                self.config.juju_home(use_expansion=True)),
                            use_ssh=True)
        self.tasker.stop_current_task()

        self.display_controller.status_info_message(
            "Starting cloud deployment")
        utils.container_run_status(self.container_name,
                                   " ".join(cloud_status_bin), self.config)
Exemplo n.º 15
0
    def create_container_and_wait(self):
        """ Creates container and waits for cloud-init to finish
        """
        self.tasker.start_task("Creating Container")

        utils.container_create(self.container_name, self.userdata)

        with open(os.path.join(self.container_abspath, 'fstab'), 'w') as f:
            f.write("{0} {1} none bind,create=dir\n".format(
                self.config.cfg_path, 'home/ubuntu/.cloud-install'))
            f.write("/var/cache/lxc var/cache/lxc none bind,create=dir\n")
            # Detect additional charm plugins and make available to the
            # container.
            charm_plugin_dir = self.config.getopt('charm_plugin_dir')
            if charm_plugin_dir \
               and self.config.cfg_path not in charm_plugin_dir:
                plug_dir = os.path.abspath(
                    self.config.getopt('charm_plugin_dir'))
                plug_base = os.path.basename(plug_dir)
                f.write("{d} home/ubuntu/{m} "
                        "none bind,create=dir\n".format(d=plug_dir,
                                                        m=plug_base))

            extra_mounts = os.getenv("EXTRA_BIND_DIRS", None)
            if extra_mounts:
                for d in extra_mounts.split(','):
                    mountpoint = os.path.basename(d)
                    f.write("{d} home/ubuntu/{m} "
                            "none bind,create=dir\n".format(d=d, m=mountpoint))

        # update container config
        with open(os.path.join(self.container_abspath, 'config'), 'a') as f:
            f.write("lxc.mount.auto = cgroup:mixed\n"
                    "lxc.start.auto = 1\n"
                    "lxc.start.delay = 5\n"
                    "lxc.mount = {}/fstab\n".format(self.container_abspath))

        lxc_logfile = os.path.join(self.config.cfg_path, 'lxc.log')

        utils.container_start(self.container_name, lxc_logfile)

        utils.container_wait_checked(self.container_name, lxc_logfile)

        tries = 0
        while not self.cloud_init_finished(tries):
            time.sleep(1)
            tries += 1

        # we do this here instead of using cloud-init, for greater
        # control over ordering
        log.debug("Container started, cloud-init done.")

        lxc_network = self.write_lxc_net_config()
        self.add_static_route(lxc_network)

        self.tasker.start_task("Installing Dependencies")
        log.debug("Installing openstack & openstack-single directly, "
                  "and juju-local, libvirt-bin and lxc via deps")
        utils.container_run(
            self.container_name,
            "env DEBIAN_FRONTEND=noninteractive apt-get -qy "
            "-o Dpkg::Options::=--force-confdef "
            "-o Dpkg::Options::=--force-confold "
            "install openstack openstack-single")