示例#1
0
文件: utils.py 项目: jvalinas/fuel-qa
def replace_rpm_package(package):
    """Replaced rpm package.rpm on master node with package.rpm
    from review
    """
    ssh = SSHManager()
    logger.info("Patching {}".format(package))
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    try:
        # Upload package
        target_path = '/var/www/nailgun/{}/'.format(package)
        ssh.upload_to_remote(ip=ssh.admin_ip,
                             source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                             target=target_path)

        package_name = package
        package_ext = '*.noarch.rpm'
        pkg_path = os.path.join(target_path,
                                '{}{}'.format(package_name, package_ext))
        full_package_name = get_full_filename(wildcard_name=pkg_path)
        logger.debug('Package name is {0}'.format(full_package_name))
        full_package_path = os.path.join(os.path.dirname(pkg_path),
                                         full_package_name)

        # Update package on master node
        if not does_new_pkg_equal_to_installed_pkg(
                installed_package=package_name, new_package=full_package_path):
            update_rpm(path=full_package_path)

    except Exception:
        logger.error("Could not upload package")
        raise
示例#2
0
def replace_rpm_package(package):
    """Replaced rpm package.rpm on master node with package.rpm
    from review
    """
    ssh = SSHManager()
    logger.info("Patching {}".format(package))
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    try:
        # Upload package
        target_path = '/var/www/nailgun/{}/'.format(package)
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.UPDATE_FUEL_PATH.rstrip('/'),
            target=target_path)

        package_name = package
        package_ext = '*.noarch.rpm'
        pkg_path = os.path.join(target_path,
                                '{}{}'.format(package_name, package_ext))
        full_package_name = get_full_filename(wildcard_name=pkg_path)
        logger.debug('Package name is {0}'.format(full_package_name))
        full_package_path = os.path.join(os.path.dirname(pkg_path),
                                         full_package_name)

        # Update package on master node
        if not does_new_pkg_equal_to_installed_pkg(
                installed_package=package_name,
                new_package=full_package_path):
            update_rpm(path=full_package_path)

    except Exception:
        logger.error("Could not upload package")
        raise
示例#3
0
def update_ostf():
    logger.info("Uploading new package from {0}".format(
        settings.UPDATE_FUEL_PATH))
    ssh = SSHManager()
    pack_path = '/var/www/nailgun/fuel-ostf/'
    full_pack_path = os.path.join(pack_path, 'fuel-ostf*.noarch.rpm')
    ssh.upload_to_remote(
        ssh.admin_ip,
        source=settings.UPDATE_FUEL_PATH.rstrip('/'), target=pack_path)

    # Check old fuel-ostf package
    cmd = "rpm -q fuel-ostf"

    old_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info(
        'Current package version of '
        'fuel-ostf: {0}'.format(old_package))

    cmd = "rpm -qp {0}".format(full_pack_path)
    new_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info('Package from review {0}'.format(new_package))

    if old_package == new_package:
        logger.info('Package {0} is installed'.format(new_package))
        return

    cmd = "service ostf stop"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "service ostf status"
    helpers.wait(lambda: "dead" in ssh.execute_on_remote(
        ssh.admin_ip, cmd=cmd,
        raise_on_assert=False,
        assert_ec_equal=[3])['stdout_str'], timeout=60)
    logger.info("OSTF status: inactive")
    cmd = "rpm -e fuel-ostf"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "rpm -q fuel-ostf"
    installed_package = ssh.execute_on_remote(
        ssh.admin_ip, cmd=cmd)['stdout_str']

    assert_equal(
        installed_package, new_package,
        "The new package {0} was not installed. Actual {1}".format(
            new_package, installed_package))
    cmd = "service ostf start"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "service ostf status"
    helpers.wait(
        lambda: "running" in
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str'],
        timeout=60)
    cmd = "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8777"
    helpers.wait(
        lambda: "401" in ssh.execute_on_remote(
            ssh.admin_ip, cmd=cmd, raise_on_assert=False)['stdout_str'],
        timeout=60)
    logger.info("OSTF status: RUNNING")
示例#4
0
    def centos_setup_fuel(self, hostname):
        logger.info("upload fuel-release packet")
        if not settings.FUEL_RELEASE_PATH:
            raise exceptions.FuelQAVariableNotSet('FUEL_RELEASE_PATH', '/path')
        try:
            ssh = SSHManager()
            pack_path = '/tmp/'
            full_pack_path = os.path.join(pack_path,
                                          'fuel-release*.noarch.rpm')
            ssh.upload_to_remote(
                ip=ssh.admin_ip,
                source=settings.FUEL_RELEASE_PATH.rstrip('/'),
                target=pack_path)

        except Exception:
            logger.exception("Could not upload package")

        logger.debug("Update host information")
        cmd = "echo HOSTNAME={} >> /etc/sysconfig/network".format(hostname)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "echo {0} {1} {2} >> /etc/hosts".format(
            ssh.admin_ip,
            hostname,
            settings.FUEL_MASTER_HOSTNAME)

        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "hostname {}".format(hostname)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        logger.debug("setup MOS repositories")
        cmd = "rpm -ivh {}".format(full_pack_path)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "yum install -y fuel-setup"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "yum install -y screen"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        logger.info("Install Fuel services")

        cmd = "screen -dm bash -c 'showmenu=no wait_for_external_config=yes " \
              "bootstrap_admin_node.sh'"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        self.env.wait_for_external_config()
        self.env.admin_actions.modify_configs(self.env.d_env.router())
        self.env.kill_wait_for_external_config()

        self.env.wait_bootstrap()

        logger.debug("Check Fuel services")
        self.env.admin_actions.wait_for_fuel_ready()

        logger.debug("post-installation configuration of Fuel services")
        self.fuel_post_install_actions()
示例#5
0
文件: utils.py 项目: jvalinas/fuel-qa
def update_ostf():
    logger.info("Uploading new package from {0}".format(
        settings.UPDATE_FUEL_PATH))
    ssh = SSHManager()
    pack_path = '/var/www/nailgun/fuel-ostf/'
    full_pack_path = os.path.join(pack_path, 'fuel-ostf*.noarch.rpm')
    ssh.upload_to_remote(ssh.admin_ip,
                         source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                         target=pack_path)

    # Check old fuel-ostf package
    cmd = "rpm -q fuel-ostf"

    old_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info('Current package version of '
                'fuel-ostf: {0}'.format(old_package))

    cmd = "rpm -qp {0}".format(full_pack_path)
    new_package = ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info('Package from review {0}'.format(new_package))

    if old_package == new_package:
        logger.info('Package {0} is installed'.format(new_package))
        return

    cmd = "service ostf stop"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "service ostf status"
    helpers.wait(lambda: "dead" in ssh.execute_on_remote(
        ssh.admin_ip, cmd=cmd, raise_on_assert=False, assert_ec_equal=[3])[
            'stdout_str'],
                 timeout=60)
    logger.info("OSTF status: inactive")
    cmd = "rpm -e fuel-ostf"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "rpm -q fuel-ostf"
    installed_package = ssh.execute_on_remote(ssh.admin_ip,
                                              cmd=cmd)['stdout_str']

    assert_equal(
        installed_package, new_package,
        "The new package {0} was not installed. Actual {1}".format(
            new_package, installed_package))
    cmd = "service ostf start"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
    cmd = "service ostf status"
    helpers.wait(lambda: "running" in ssh.execute_on_remote(
        ssh.admin_ip, cmd=cmd)['stdout_str'],
                 timeout=60)
    cmd = "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8777"
    helpers.wait(lambda: "401" in ssh.execute_on_remote(
        ssh.admin_ip, cmd=cmd, raise_on_assert=False)['stdout_str'],
                 timeout=60)
    logger.info("OSTF status: RUNNING")
示例#6
0
    def centos_setup_fuel(self, hostname):
        logger.info("upload fuel-release packet")
        if not settings.FUEL_RELEASE_PATH:
            raise exceptions.FuelQAVariableNotSet('FUEL_RELEASE_PATH', '/path')
        try:
            ssh = SSHManager()
            pack_path = '/tmp/'
            full_pack_path = os.path.join(pack_path,
                                          'fuel-release*.noarch.rpm')
            ssh.upload_to_remote(ip=ssh.admin_ip,
                                 source=settings.FUEL_RELEASE_PATH.rstrip('/'),
                                 target=pack_path)

        except Exception:
            logger.exception("Could not upload package")

        logger.debug("Update host information")
        cmd = "echo HOSTNAME={} >> /etc/sysconfig/network".format(hostname)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "echo {0} {1} {2} >> /etc/hosts".format(
            ssh.admin_ip, hostname, settings.FUEL_MASTER_HOSTNAME)

        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "hostname {}".format(hostname)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        logger.debug("setup MOS repositories")
        cmd = "rpm -ivh {}".format(full_pack_path)
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "yum install -y fuel-setup"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        cmd = "yum install -y screen"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        logger.info("Install Fuel services")

        cmd = "screen -dm bash -c 'showmenu=no wait_for_external_config=yes " \
              "bootstrap_admin_node.sh'"
        ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

        self.env.wait_for_external_config()
        self.env.admin_actions.modify_configs(self.env.d_env.router())
        self.env.kill_wait_for_external_config()

        self.env.wait_bootstrap()

        logger.debug("Check Fuel services")
        self.env.admin_actions.wait_for_fuel_ready()

        logger.debug("post-installation configuration of Fuel services")
        self.fuel_post_install_actions()
示例#7
0
文件: utils.py 项目: SergK/fuel-qa
def patch_and_assemble_ubuntu_bootstrap(environment):
    """Replaced initramfs.img in /var/www/nailgun/
    with newly_builded from review
    environment - Environment Model object - self.env
    """
    logger.info("Update fuel-agent code and assemble new ubuntu bootstrap")
    ssh = SSHManager()
    if not settings.UPDATE_FUEL:
        raise Exception("{} variable don't exist"
                        .format(settings.UPDATE_FUEL))
    try:
        pack_path = '/var/www/nailgun/fuel-agent-review/'
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.FUEL_AGENT_REPO_PATH.rstrip('/'),
            target=pack_path)
        # renew code in bootstrap

        # Step 1 - install squashfs-tools
        cmd = "yum install -y squashfs-tools"
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 2 - unpack bootstrap
        bootstrap = "/var/www/nailgun/bootstraps/active_bootstrap"
        bootstrap_var = "/var/root.squashfs"

        cmd = "unsquashfs -d /var/root.squashfs {}/root.squashfs".format(
            bootstrap)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 3 - replace fuel-agent code in unpacked bootstrap
        agent_path = "/usr/lib/python2.7/dist-packages/fuel_agent"
        bootstrap_file = bootstrap + "/root.squashfs"
        cmd = ("rsync -r {2}fuel_agent/* {0}{1}/;"
               "mv {3} /var/root.squashfs.old;"
               ).format(bootstrap_var, agent_path, pack_path, bootstrap_file)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 4 - assemble new bootstrap
        compression = "-comp xz"
        no_progress_bar = "-no-progress"
        no_append = "-noappend"
        image_rebuild = "mksquashfs {0} {1} {2} {3} {4}".format(
            bootstrap_var,
            bootstrap_file,
            compression,
            no_progress_bar,
            no_append)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=image_rebuild)
        with environment.d_env.get_admin_remote() as remote:
            checkers.check_file_exists(remote, '{0}'.format(bootstrap_file))
    except Exception as e:
        logger.error("Could not upload package {e}".format(e=e))
        raise
示例#8
0
文件: utils.py 项目: jvalinas/fuel-qa
def check_package_version_injected_in_bootstraps(package,
                                                 cluster_id=None,
                                                 ironic=None):

    ssh = SSHManager()
    try:
        pack_path = '/var/www/nailgun/{}/'.format(package)
        ssh.upload_to_remote(ip=ssh.admin_ip,
                             source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                             target=pack_path)
    except Exception:
        logger.exception("Could not upload package")
        raise

    # Step 1 - unpack active bootstrap
    logger.info("unpack active bootstrap")

    if ironic:
        bootstrap = "/var/www/nailgun/bootstrap/ironic/{}".format(cluster_id)
    else:
        bootstrap = "/var/www/nailgun/bootstraps/active_bootstrap"
    bootstrap_var = "/var/root.squashfs"

    cmd = "unsquashfs -d {} {}/root.squashfs".format(bootstrap_var, bootstrap)
    ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

    # Step 2 - check package version
    logger.info("check package {} version injected in ubuntu bootstrap".format(
        package))

    cmd = "ls {}|grep {} |grep deb |cut -f 2 -d '_'".format(pack_path, package)

    package_from_review = ssh.execute_on_remote(ip=ssh.admin_ip,
                                                cmd=cmd)['stdout_str']

    logger.info("package from review is {}".format(package_from_review))

    awk_pattern = "awk '{print $2}'"
    cmd = "chroot {}/ /bin/bash -c \"dpkg -s {}\"|grep Version|{}".format(
        bootstrap_var, package, awk_pattern)
    installed_package = ssh.execute_on_remote(ip=ssh.admin_ip,
                                              cmd=cmd)['stdout_str']
    logger.info("injected package is {}".format(installed_package))

    assert_equal(
        installed_package, package_from_review,
        "The new package {0} wasn't injected in bootstrap".format(
            package_from_review))

    # Step 3 - remove unpacked bootstrap
    cmd = "rm -rf {}".format(bootstrap_var)
    ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)
示例#9
0
文件: utils.py 项目: jvalinas/fuel-qa
def upload_nailgun_agent_rpm():
    """Upload nailgun_agent.rpm on master node
    """
    ssh = SSHManager()
    logger.info("Upload nailgun-agent")
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    pack_path = '/var/www/nailgun/nailgun-agent-review/'
    ssh.upload_to_remote(ip=ssh.admin_ip,
                         source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                         target=pack_path)
    # Extract rpm context
    cmd = 'cd {0}; rpm2cpio {1} | cpio -idmv'.format(
        pack_path, 'nailgun-agent-*.noarch.rpm ')
    ssh.execute_on_remote(ssh.admin_ip, cmd)
示例#10
0
def patch_and_assemble_ubuntu_bootstrap(environment):
    """Replaced initramfs.img in /var/www/nailgun/
    with newly_builded from review
    environment - Environment Model object - self.env
    """
    logger.info("Update fuel-agent code and assemble new ubuntu bootstrap")
    ssh = SSHManager()
    if not settings.UPDATE_FUEL:
        raise Exception("{} variable don't exist".format(settings.UPDATE_FUEL))
    try:
        pack_path = '/var/www/nailgun/fuel-agent-review/'
        ssh.upload_to_remote(ip=ssh.admin_ip,
                             source=settings.FUEL_AGENT_REPO_PATH.rstrip('/'),
                             target=pack_path)
        # renew code in bootstrap

        # Step 1 - install squashfs-tools
        cmd = "yum install -y squashfs-tools"
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 2 - unpack bootstrap
        bootstrap = "/var/www/nailgun/bootstraps/active_bootstrap"
        bootstrap_var = "/var/root.squashfs"

        cmd = "unsquashfs -d /var/root.squashfs {}/root.squashfs".format(
            bootstrap)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 3 - replace fuel-agent code in unpacked bootstrap
        agent_path = "/usr/lib/python2.7/dist-packages/fuel_agent"
        bootstrap_file = bootstrap + "/root.squashfs"
        cmd = ("rsync -r {2}fuel_agent/* {0}{1}/;"
               "mv {3} /var/root.squashfs.old;").format(
                   bootstrap_var, agent_path, pack_path, bootstrap_file)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)

        # Step 4 - assemble new bootstrap
        compression = "-comp xz"
        no_progress_bar = "-no-progress"
        no_append = "-noappend"
        image_rebuild = "mksquashfs {0} {1} {2} {3} {4}".format(
            bootstrap_var, bootstrap_file, compression, no_progress_bar,
            no_append)
        ssh.execute_on_remote(ip=ssh.admin_ip, cmd=image_rebuild)
        checkers.check_file_exists(ssh.admin_ip, '{0}'.format(bootstrap_file))
    except Exception as e:
        logger.error("Could not upload package {e}".format(e=e))
        raise
示例#11
0
文件: utils.py 项目: glluk/fuel-qa
def upload_nailgun_agent_rpm():
    """Upload nailgun_agent.rpm on master node
    """
    ssh = SSHManager()
    logger.info("Upload nailgun-agent")
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    pack_path = '/var/www/nailgun/nailgun-agent-review/'
    ssh.upload_to_remote(
        ip=ssh.admin_ip,
        source=settings.UPDATE_FUEL_PATH.rstrip('/'),
        target=pack_path)
    # Extract rpm context
    cmd = 'cd {0}; rpm2cpio {1} | cpio -idmv'.format(
        pack_path, 'nailgun-agent-*.noarch.rpm ')
    ssh.execute_on_remote(ssh.admin_ip, cmd)
示例#12
0
文件: utils.py 项目: SergK/fuel-qa
def patch_centos_bootstrap():
    """Replaced initramfs.img in /var/www/nailgun/
    with newly_builded from review
    environment - Environment Model object - self.env
    """
    logger.info("Update fuel-agent code and assemble new bootstrap")
    ssh = SSHManager()
    if not settings.UPDATE_FUEL:
        raise Exception("{} variable don't exist"
                        .format(settings.UPDATE_FUEL))
    try:
        pack_path = '/var/www/nailgun/fuel-agent-review/'
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.FUEL_AGENT_REPO_PATH.rstrip('/'),
            target=pack_path)
        # Step 1 - unpack bootstrap
        bootstrap_var = "/var/initramfs"
        bootstrap = "/var/www/nailgun/bootstrap"
        cmd = ("mkdir {0}; cp /{1}/initramfs.img {0}/; cd {0}; "
               "cat initramfs.img | gunzip | cpio -imudv;").format(
            bootstrap_var, bootstrap)
        result = ssh.execute_on_remote(
            ip=ssh.admin_ip, cmd=cmd)['stdout_str']
        logger.debug("Patching bootsrap finishes with {0}".format(result))

        # Step 2 - replace fuel-agent code in unpacked bootstrap
        agent_path = "/usr/lib/python2.7/site-packages/fuel_agent"
        image_rebuild = "{} | {} | {}".format(
            "find . -xdev",
            "cpio --create --format='newc'",
            "gzip -9 > /var/initramfs.img.updated")

        cmd = ("rm -rf {0}/initramfs.img; "
               "rsync -r {2}fuel_agent/* {0}{1}/;"
               "cd {0}/;"
               "{3};").format(bootstrap_var, agent_path, pack_path,
                              image_rebuild)
        result = ssh.execute_on_remote(
            ip=ssh.admin_ip, cmd=cmd)['stdout_str']
        logger.debug("Failed to rebuild image with {0}".format(result))

    except Exception as e:
        logger.error("Could not upload package {e}".format(e=e))
        raise
示例#13
0
def install_mos_repos():
    """
    Upload and install fuel-release packet with mos-repo description
    and install necessary packets for packetary Fuel installation
    :return: nothing
    """
    logger.info("upload fuel-release packet")
    if not settings.FUEL_RELEASE_PATH:
        raise exceptions.FuelQAVariableNotSet('FUEL_RELEASE_PATH', '/path')
    try:
        ssh = SSHManager()
        pack_path = '/tmp/'
        full_pack_path = os.path.join(pack_path,
                                      'fuel-release*.noarch.rpm')
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.FUEL_RELEASE_PATH.rstrip('/'),
            target=pack_path)

        if settings.RPM_REPOS_YAML:
            with ssh.open_on_remote(
                    ip=ssh.admin_ip,
                    path='/etc/yum.repos.d/custom.repo',
                    mode="w") as f:
                f.write(generate_yum_repos_config(settings.RPM_REPOS_YAML))

        if settings.DEB_REPOS_YAML:
            ssh = SSHManager()
            pack_path = "/root/default_deb_repos.yaml"
            ssh.upload_to_remote(
                ip=ssh.admin_ip,
                source=settings.DEB_REPOS_YAML,
                target=pack_path)

    except Exception:
        logger.exception("Could not upload package")
        raise

    logger.debug("setup MOS repositories")
    cmd = "rpm -ivh {}".format(full_pack_path)
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)

    cmd = "yum install -y fuel-setup"
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd)
示例#14
0
文件: utils.py 项目: glluk/fuel-qa
def replace_fuel_agent_rpm():
    """Replaced fuel_agent.rpm on master node with fuel_agent.rpm
    from review
    """
    ssh = SSHManager()
    logger.info("Patching fuel-agent")
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    try:
        pack_path = '/var/www/nailgun/fuel-agent/'
        full_pack_path = os.path.join(pack_path, 'fuel-agent*.noarch.rpm')
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.UPDATE_FUEL_PATH.rstrip('/'),
            target=pack_path)

        # Update fuel-agent on master node
        cmd = "rpm -q fuel-agent"
        old_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']
        cmd = "rpm -qp {0}".format(full_pack_path)
        new_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']
        logger.info("Updating package {0} with {1}"
                    .format(old_package, new_package))

        if old_package != new_package:
            logger.info("Updating fuel-agent package on master node")
            logger.info('Try to install package {0}'.format(
                new_package))
            cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
            ssh.execute_on_remote(ssh.admin_ip, cmd)

            cmd = "rpm -q fuel-agent"
            installed_package = ssh.execute_on_remote(
                ssh.admin_ip, cmd)['stdout_str']

            assert_equal(installed_package, new_package,
                         "The new package {0} was not installed".
                         format(new_package))

    except Exception as e:
        logger.error("Could not upload package {e}".format(e=e))
        raise
示例#15
0
def replace_fuel_agent_rpm():
    """Replaced fuel_agent.rpm on master node with fuel_agent.rpm
    from review
    """
    ssh = SSHManager()
    logger.info("Patching fuel-agent")
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    try:
        pack_path = '/var/www/nailgun/fuel-agent/'
        full_pack_path = os.path.join(pack_path, 'fuel-agent*.noarch.rpm')
        ssh.upload_to_remote(ip=ssh.admin_ip,
                             source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                             target=pack_path)

        # Update fuel-agent on master node
        cmd = "rpm -q fuel-agent"
        old_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']
        cmd = "rpm -qp {0}".format(full_pack_path)
        new_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']
        logger.info("Updating package {0} with {1}".format(
            old_package, new_package))

        if old_package != new_package:
            logger.info("Updating fuel-agent package on master node")
            logger.info('Try to install package {0}'.format(new_package))
            cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)
            ssh.execute_on_remote(ssh.admin_ip, cmd)

            cmd = "rpm -q fuel-agent"
            installed_package = ssh.execute_on_remote(ssh.admin_ip,
                                                      cmd)['stdout_str']

            assert_equal(
                installed_package, new_package,
                "The new package {0} was not installed".format(new_package))

    except Exception as e:
        logger.error("Could not upload package {e}".format(e=e))
        raise
示例#16
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        return "[{klass}({obj_id})]".format(klass=klass, obj_id=obj_id)

    def restart_service(self, service):
        result = self.ssh_manager.execute(
            ip=self.admin_ip, cmd="systemctl restart {0}".format(service))
        return result['exit_code'] == 0

    @staticmethod
    def put_value_to_local_yaml(old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml,
                      f_new,
                      default_flow_style=False,
                      default_style='"')

    @staticmethod
    def get_value_from_local_yaml(yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError(
                    "Element {0} not found in the file {1}".format(
                        element[:i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}".format(
                    element[:i + 1], f_old))
        return yaml_dict

    def change_remote_yaml(self, path_to_file, element, value):
        """Changes values in the yaml file stored
        There is no need to copy file manually
        :param path_to_file: absolute path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :return: Nothing
        """
        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=old_file)
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=new_file,
                                          target=path_to_file)
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_remote_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element
        :return obj: value
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=host_tmp_file)
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_remote_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=host_tmp_file)
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element,
                                     value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=host_tmp_file,
                                          target=path_to_file)
        os.remove(host_tmp_file)
示例#17
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        return "[{klass}({obj_id})]".format(klass=klass, obj_id=obj_id)

    # TODO(kozhukalov): This method seems not needed and
    # can easily be replaced by using execute_on_remote
    # available in SSHManager (up to the type of return value)
    def execute(self, cmd, exit_code=None, stdin=None):
        if stdin is not None:
            cmd = 'echo "{0}" | {1}'.format(stdin, cmd)

        result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd)
        if exit_code is not None:
            assert_equal(exit_code, result['exit_code'],
                         ('Command {cmd} returned exit code "{e}", but '
                          'expected "{c}". Output: {out}; {err} ').format(
                              cmd=cmd,
                              e=result['exit_code'],
                              c=exit_code,
                              out=result['stdout'],
                              err=result['stderr']))
        return ''.join(result['stdout']).strip()

    def restart_service(self, service):
        result = self.ssh_manager(ip=self.admin_ip,
                                  cmd="systemctl restart {0}".format(service))
        return result['exit_code'] == 0

    def put_value_to_local_yaml(self, old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml,
                      f_new,
                      default_flow_style=False,
                      default_style='"')

    def get_value_from_local_yaml(self, yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError(
                    "Element {0} not found in the file {1}".format(
                        element[:i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}".format(
                    element[:i + 1], f_old))
        return yaml_dict

    def change_remote_yaml(self, path_to_file, element, value):
        """Changes values in the yaml file stored
        There is no need to copy file manually
        :param path_to_file: absolute path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :return: Nothing
        """
        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=old_file)
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=new_file,
                                          target=path_to_file)
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_remote_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element
        :return obj: value
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=host_tmp_file)
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_remote_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=path_to_file,
                                              target=host_tmp_file)
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element,
                                     value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=host_tmp_file,
                                          target=path_to_file)
        os.remove(host_tmp_file)
示例#18
0
class CustomRepo(object):
    """CustomRepo."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.ip = self.ssh_manager.admin_ip
        self.path_scripts = ('{0}/fuelweb_test/helpers/'
                             .format(os.environ.get("WORKSPACE", "./")))
        self.remote_path_scripts = '/tmp/'
        self.ubuntu_script = 'regenerate_ubuntu_repo'
        self.centos_script = 'regenerate_centos_repo'
        self.local_mirror_ubuntu = settings.LOCAL_MIRROR_UBUNTU
        self.local_mirror_centos = settings.LOCAL_MIRROR_CENTOS
        self.ubuntu_release = settings.UBUNTU_RELEASE
        self.centos_supported_archs = ['noarch', 'x86_64']
        self.pkgs_list = []

        self.custom_pkgs_mirror_path = ''
        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            # Trying to determine the root of Ubuntu repository
            pkgs_path = settings.CUSTOM_PKGS_MIRROR.split('/dists/')
            if len(pkgs_path) == 2:
                self.custom_pkgs_mirror = pkgs_path[0]
                self.custom_pkgs_mirror_path = '/dists/{}'.format(pkgs_path[1])
            else:
                self.custom_pkgs_mirror = settings.CUSTOM_PKGS_MIRROR
        else:
            self.custom_pkgs_mirror = settings.CUSTOM_PKGS_MIRROR

    def prepare_repository(self):
        """Prepare admin node to packages testing

        Scenario:
            1. Temporary set nameserver to local router on admin node
            2. Install tools to manage rpm/deb repository
            3. Retrieve list of packages from custom repository
            4. Download packages to local rpm/deb repository
            5. Update .yaml file with new packages version
            6. Re-generate repo using shell scripts on admin node

        """
        # Check necessary settings and revert a snapshot
        if not self.custom_pkgs_mirror:
            return
        logger.info("Custom mirror with new packages: {0}"
                    .format(settings.CUSTOM_PKGS_MIRROR))

        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            # Ubuntu
            master_tools = ['dpkg', 'dpkg-devel', 'dpkg-dev']
            self.install_tools(master_tools)
            self.get_pkgs_list_ubuntu()
            pkgs_local_path = ('{0}/pool/'
                               .format(self.local_mirror_ubuntu))
            self.download_pkgs(pkgs_local_path)
            self.regenerate_repo(self.ubuntu_script, self.local_mirror_ubuntu)
        else:
            # CentOS
            master_tools = ['createrepo']
            self.install_tools(master_tools)
            self.get_pkgs_list_centos()
            pkgs_local_path = '{0}/Packages/'.format(self.local_mirror_centos)
            self.download_pkgs(pkgs_local_path)
            self.regenerate_repo(self.centos_script, self.local_mirror_centos)

    # Install tools to masternode
    def install_tools(self, master_tools=None):
        if master_tools is None:
            master_tools = []
        logger.info("Installing necessary tools for {0}"
                    .format(settings.OPENSTACK_RELEASE))
        for master_tool in master_tools:
            exit_code = install_pkg_2(
                ip=self.ip,
                pkg_name=master_tool
            )
            assert_equal(0, exit_code, 'Cannot install package {0} '
                         'on admin node.'.format(master_tool))

    # Ubuntu: Creating list of packages from the additional mirror
    def get_pkgs_list_ubuntu(self):
        url = "{0}/{1}/Packages".format(self.custom_pkgs_mirror,
                                        self.custom_pkgs_mirror_path)
        logger.info("Retrieving additional packages from the custom mirror:"
                    " {0}".format(url))
        try:
            pkgs_release = urllib2.urlopen(url).read()
        except (urllib2.HTTPError, urllib2.URLError):
            logger.error(traceback.format_exc())
            url_gz = '{0}.gz'.format(url)
            logger.info(
                "Retrieving additional packages from the custom mirror:"
                " {0}".format(url_gz))
            try:
                pkgs_release_gz = urllib2.urlopen(url_gz).read()
            except (urllib2.HTTPError, urllib2.URLError):
                logger.error(traceback.format_exc())
                raise
            try:
                d = zlib.decompressobj(zlib.MAX_WBITS | 32)
                pkgs_release = d.decompress(pkgs_release_gz)
            except Exception:
                logger.error('Ubuntu mirror error: Could not decompress {0}\n'
                             '{1}'.format(url_gz, traceback.format_exc()))
                raise

        packages = (pkg for pkg in pkgs_release.split("\n\n") if pkg)
        for package in packages:
            upkg = {pstr.split()[0].lower(): ''.join(pstr.split()[1:])
                    for pstr in package.split("\n") if pstr[0].strip()}

            upkg_keys = ["package:", "version:", "filename:"]
            assert_equal(True, all(x in upkg for x in upkg_keys),
                         'Missing one of the statements ["Package:", '
                         '"Version:", "Filename:"] in {0}'.format(url))
            # TODO: add dependencies list to upkg
            self.pkgs_list.append(upkg)

    # Centos: Creating list of packages from the additional mirror
    def get_pkgs_list_centos(self):
        logger.info("Retrieving additional packages from the custom mirror:"
                    " {0}".format(self.custom_pkgs_mirror))
        url = "{0}/repodata/repomd.xml".format(self.custom_pkgs_mirror)
        try:
            repomd_data = urllib2.urlopen(url).read()
        except (urllib2.HTTPError, urllib2.URLError):
            logger.error(traceback.format_exc())
            raise
        # Remove namespace attribute before parsing XML
        repomd_data = re.sub(' xmlns="[^"]+"', '', repomd_data, count=1)
        tree_repomd_data = ElementTree.fromstring(repomd_data)
        lists_location = ''
        for repomd in tree_repomd_data.findall('data'):
            if repomd.get('type') == 'primary':
                repomd_location = repomd.find('location')
                lists_location = repomd_location.get('href')

        assert_equal(True, lists_location is not '', 'CentOS mirror error:'
                     ' Could not parse {0}\nlists_location = "{1}"\n{2}'
                     .format(url, lists_location, traceback.format_exc()))
        url = "{0}/{1}".format(self.custom_pkgs_mirror, lists_location)
        try:
            lists_data = urllib2.urlopen(url).read()
        except (urllib2.HTTPError, urllib2.URLError):
            logger.error(traceback.format_exc())
            raise
        if '.xml.gz' in lists_location:
            try:
                d = zlib.decompressobj(zlib.MAX_WBITS | 32)
                lists_data = d.decompress(lists_data)
            except Exception:
                logger.error('CentOS mirror error: Could not decompress {0}\n'
                             '{1}'.format(url, traceback.format_exc()))
                raise

        # Remove namespace attribute before parsing XML
        lists_data = re.sub(' xmlns="[^"]+"', '', lists_data, count=1)

        tree_lists_data = ElementTree.fromstring(lists_data)

        for flist in tree_lists_data.findall('package'):
            if flist.get('type') == 'rpm':
                flist_arch = flist.find('arch').text
                if flist_arch in self.centos_supported_archs:
                    flist_name = flist.find('name').text
                    flist_location = flist.find('location')
                    flist_file = flist_location.get('href')
                    flist_version = flist.find('version')
                    flist_ver = '{0}-{1}'.format(flist_version.get('ver'),
                                                 flist_version.get('rel'))
                    cpkg = {'package:': flist_name,
                            'version:': flist_ver,
                            'filename:': flist_file}
                    # TODO: add dependencies list to cpkg
                    self.pkgs_list.append(cpkg)

    # Download packages (local_folder)
    def download_pkgs(self, pkgs_local_path):
        # Process the packages list:
        total_pkgs = len(self.pkgs_list)
        logger.info('Found {0} custom package(s)'.format(total_pkgs))

        for npkg, pkg in enumerate(self.pkgs_list):
            # TODO: Previous versions of the updating packages must be removed
            # to avoid unwanted packet manager dependencies resolution
            # (when some package still depends on other package which
            # is not going to be installed)

            logger.info('({0}/{1}) Downloading package: {2}/{3}'
                        .format(npkg + 1, total_pkgs,
                                self.custom_pkgs_mirror,
                                pkg["filename:"]))

            pkg_ext = pkg["filename:"].split('.')[-1]
            if pkg_ext == 'deb':
                path_suff = 'main/'
            elif pkg_ext == 'udeb':
                path_suff = 'debian-installer/'
            else:
                path_suff = ''

            wget_cmd = "wget --no-verbose --directory-prefix {0} {1}/{2}"\
                       .format(pkgs_local_path + path_suff,
                               self.custom_pkgs_mirror,
                               pkg["filename:"])
            wget_result = self.ssh_manager.execute(
                ip=self.ip,
                cmd=wget_cmd
            )
            assert_equal(0, wget_result['exit_code'],
                         self.assert_msg(wget_cmd, wget_result['stderr']))

    # Upload regenerate* script to masternode (script name)
    def regenerate_repo(self, regenerate_script, local_mirror_path):
        # Uploading scripts that prepare local repositories:
        # 'regenerate_centos_repo' and 'regenerate_ubuntu_repo'
        try:
            self.ssh_manager.upload_to_remote(
                ip=self.ip,
                source='{0}/{1}'.format(self.path_scripts, regenerate_script),
                target=self.remote_path_scripts
            )
            self.ssh_manager.execute_on_remote(
                ip=self.ip,
                cmd='chmod 755 {0}/{1}'.format(self.remote_path_scripts,
                                               regenerate_script)
            )
        except Exception:
            logger.error('Could not upload scripts for updating repositories.'
                         '\n{0}'.format(traceback.format_exc()))
            raise

        # Update the local repository using previously uploaded script.
        script_cmd = '{0}/{1} {2} {3}'.format(self.remote_path_scripts,
                                              regenerate_script,
                                              local_mirror_path,
                                              self.ubuntu_release)
        script_result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=script_cmd
        )
        assert_equal(0, script_result['exit_code'],
                     self.assert_msg(script_cmd, script_result['stderr']))

        logger.info('Local repository {0} has been updated successfully.'
                    .format(local_mirror_path))

    def assert_msg(self, cmd, err):
        return 'Executing \'{0}\' on the admin node has failed with: {1}'\
               .format(cmd, err)

    def check_puppet_logs(self):
        logger.info("Check puppet logs for packages with unmet dependencies.")
        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            err_deps = self.check_puppet_logs_ubuntu()
        else:
            err_deps = self.check_puppet_logs_centos()

        for err_deps_key in err_deps.keys():
            logger.info('Error: Package: {0} has unmet dependencies:'
                        .format(err_deps_key))
            for dep in err_deps[err_deps_key]:
                logger.info('        {0}'.format(dep.strip()))
        logger.info("Check puppet logs completed.")

    def check_puppet_logs_ubuntu(self):
        """ Check puppet-agent.log files on all nodes for package
            dependency errors during a cluster deployment (ubuntu)"""

        err_start = 'The following packages have unmet dependencies:'
        err_end = ('Unable to correct problems,'
                   ' you have held broken packages.')
        cmd = ('fgrep -h -e " Depends: " -e "{0}" -e "{1}" '
               '/var/log/docker-logs/remote/node-*/'
               'puppet*.log'.format(err_start, err_end))
        result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=cmd
        )['stdout']

        err_deps = {}
        err_deps_key = ''
        err_deps_flag = False

        # Forming a dictionary of package names
        # with sets of required packages.
        for res_str in result:
            if err_deps_flag:
                if err_end in res_str:
                    err_deps_flag = False
                elif ": Depends:" in res_str:
                    str0, str1, str2 = res_str.partition(': Depends:')
                    err_deps_key = ''.join(str0.split()[-1:])
                    if err_deps_key not in err_deps:
                        err_deps[err_deps_key] = set()
                    if 'but it is not' in str2 or 'is to be installed' in str2:
                        err_deps[err_deps_key].add('Depends:{0}'
                                                   .format(str2))
                elif 'Depends:' in res_str and err_deps_key:
                    str0, str1, str2 = res_str.partition('Depends:')
                    if 'but it is not' in str2 or 'is to be installed' in str2:
                        err_deps[err_deps_key].add(str1 + str2)
                else:
                    err_deps_key = ''
            elif err_start in res_str:
                err_deps_flag = True

        return err_deps

    def check_puppet_logs_centos(self):
        """ Check puppet-agent.log files on all nodes for package
            dependency errors during a cluster deployment (centos)"""

        cmd = ('fgrep -h -e "Error: Package: " -e " Requires: " /var/log/'
               'docker-logs/remote/node-*/puppet*.log')
        result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=cmd
        )['stdout']

        err_deps = {}
        err_deps_key = ''

        # Forming a dictionary of package names
        # with sets of required packages.
        for res_str in result:
            if 'Error: Package:' in res_str:
                err_deps_key = res_str.partition('Error: Package: ')[2]
                if err_deps_key not in err_deps:
                    err_deps[err_deps_key] = set()
            elif ' Requires: ' in res_str and err_deps_key:
                str0, str1, str2 = res_str.partition(' Requires: ')
                err_deps[err_deps_key].add(str1 + str2)
            else:
                err_deps_key = ''

        return err_deps
示例#19
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        return "[{klass}({obj_id})]".format(
            klass=klass,
            obj_id=obj_id)

    def restart_service(self, service):
        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd="systemctl restart {0}".format(service))
        return result['exit_code'] == 0

    @staticmethod
    def put_value_to_local_yaml(old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml, f_new, default_flow_style=False,
                      default_style='"')

    @staticmethod
    def get_value_from_local_yaml(yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError("Element {0} not found in the file {1}"
                                 .format(element[: i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}"
                               .format(element[: i + 1], f_old))
        return yaml_dict

    def change_remote_yaml(self, path_to_file, element, value):
        """Changes values in the yaml file stored
        There is no need to copy file manually
        :param path_to_file: absolute path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :return: Nothing
        """
        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=old_file
        )
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=new_file,
            target=path_to_file
        )
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_remote_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element
        :return obj: value
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=host_tmp_file
        )
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_remote_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=host_tmp_file
        )
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file,
                                     element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=host_tmp_file,
            target=path_to_file
        )
        os.remove(host_tmp_file)
示例#20
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip
        self.container = None

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        container = getattr(self, 'container', None)
        return "[{klass}({obj_id}), container:{container}]".format(
            klass=klass,
            obj_id=obj_id,
            container=container)

    def execute_in_container(self, command, container=None, exit_code=None,
                             stdin=None):
        if not container:
            container = self.container
        cmd = 'dockerctl shell {0} {1}'.format(container, command)
        if stdin is not None:
            cmd = 'echo "{0}" | {1}'.format(stdin, cmd)

        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd=cmd
        )
        if exit_code is not None:
            assert_equal(exit_code,
                         result['exit_code'],
                         ('Command {cmd} returned exit code "{e}", but '
                          'expected "{c}". Output: {out}; {err} ').format(
                             cmd=cmd,
                             e=result['exit_code'],
                             c=exit_code,
                             out=result['stdout'],
                             err=result['stderr']
                         ))
        return ''.join(result['stdout']).strip()

    def copy_between_node_and_container(self, copy_from, copy_to):
        """ Copy files from/to container.
        :param copy_from: path to copy file from
        :param copy_to: path to copy file to
        For ex.:

            - to copy from container to master node use:
                 copy_from = container:path_from
                 copy_to = path_to
            - to copy from master node to container use:
                 copy_from = path_from
                 copy_to = container:path_to

        :return:
            Standard output from console
        """
        cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to)
        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd=cmd
        )
        assert_equal(0, result['exit_code'],
                     ('Command copy returned exit code "{e}", but '
                      'expected "0". Output: {out}; {err} ').format(
                         cmd=cmd,
                         e=result['exit_code'],
                         out=result['stdout'],
                         err=result['stderr']))
        return ''.join(result['stdout']).strip()

    @property
    def is_container_ready(self):
        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd="timeout 5 dockerctl check {0}".format(self.container)
        )
        return result['exit_code'] == 0

    def wait_for_ready_container(self, timeout=300):
        wait(lambda: self.is_container_ready, timeout=timeout)

    def put_value_to_local_yaml(self, old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml, f_new, default_flow_style=False,
                      default_style='"')

    def get_value_from_local_yaml(self, yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError("Element {0} not found in the file {1}"
                                 .format(element[: i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}"
                               .format(element[: i + 1], f_old))
        return yaml_dict

    def change_yaml_file_in_container(
            self, path_to_file, element, value, container=None):
        """Changes values in the yaml file stored at container
        There is no need to copy file manually
        :param path_to_file: absolutely path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :param container: Container with file. By default it is nailgun
        :return: Nothing
        """
        if not container:
            container = self.container

        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.copy_between_node_and_container(
            '{0}:{1}'.format(container, path_to_file), old_file)
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=old_file,
            target=old_file
        )
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=new_file,
            target=new_file
        )
        self.copy_between_node_and_container(
            new_file, '{0}:{1}'.format(container, path_to_file))
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored in container
           or on master node if self.container is None

        :param str path_to_file: absolutely path to the file
        :param list element: list with path to the element be changed
        :return obj: value
        """

        if self.container:
            admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
            self.copy_between_node_and_container(
                '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file)
        else:
            admin_tmp_file = path_to_file

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=admin_tmp_file,
            target=host_tmp_file
        )
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored in container
           or on master node if self.container is None

        :param str path_to_file: absolutely path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        if self.container:
            admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
            self.copy_between_node_and_container(
                '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file)
        else:
            admin_tmp_file = path_to_file

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=admin_tmp_file,
            target=host_tmp_file
        )
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file,
                                     element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=host_tmp_file,
            target=admin_tmp_file
        )
        if self.container:
            self.copy_between_node_and_container(
                admin_tmp_file, '{0}:{1}'.format(self.container, path_to_file))
        os.remove(host_tmp_file)
示例#21
0
class CustomRepo(object):
    """CustomRepo."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.ip = self.ssh_manager.admin_ip
        self.path_scripts = ('{0}/fuelweb_test/helpers/'
                             .format(os.environ.get("WORKSPACE", "./")))
        self.remote_path_scripts = '/tmp/'
        self.ubuntu_script = 'regenerate_ubuntu_repo'
        self.centos_script = 'regenerate_centos_repo'
        self.local_mirror_ubuntu = settings.LOCAL_MIRROR_UBUNTU
        self.local_mirror_centos = settings.LOCAL_MIRROR_CENTOS
        self.ubuntu_release = settings.UBUNTU_RELEASE
        self.centos_supported_archs = ['noarch', 'x86_64']
        self.pkgs_list = []

        self.custom_pkgs_mirror_path = ''
        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            # Trying to determine the root of Ubuntu repository
            pkgs_path = settings.CUSTOM_PKGS_MIRROR.split('/dists/')
            if len(pkgs_path) == 2:
                self.custom_pkgs_mirror = pkgs_path[0]
                self.custom_pkgs_mirror_path = '/dists/{}'.format(pkgs_path[1])
            else:
                self.custom_pkgs_mirror = settings.CUSTOM_PKGS_MIRROR
        else:
            self.custom_pkgs_mirror = settings.CUSTOM_PKGS_MIRROR

    def prepare_repository(self):
        """Prepare admin node to packages testing

        Scenario:
            1. Temporary set nameserver to local router on admin node
            2. Install tools to manage rpm/deb repository
            3. Retrieve list of packages from custom repository
            4. Download packages to local rpm/deb repository
            5. Update .yaml file with new packages version
            6. Re-generate repo using shell scripts on admin node

        """
        # Check necessary settings and revert a snapshot
        if not self.custom_pkgs_mirror:
            return
        logger.info("Custom mirror with new packages: {0}"
                    .format(settings.CUSTOM_PKGS_MIRROR))

        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            # Ubuntu
            master_tools = ['dpkg', 'dpkg-devel', 'dpkg-dev']
            self.install_tools(master_tools)
            self.get_pkgs_list_ubuntu()
            pkgs_local_path = ('{0}/pool/'
                               .format(self.local_mirror_ubuntu))
            self.download_pkgs(pkgs_local_path)
            self.regenerate_repo(self.ubuntu_script, self.local_mirror_ubuntu)
        else:
            # CentOS
            master_tools = ['createrepo']
            self.install_tools(master_tools)
            self.get_pkgs_list_centos()
            pkgs_local_path = '{0}/Packages/'.format(self.local_mirror_centos)
            self.download_pkgs(pkgs_local_path)
            self.regenerate_repo(self.centos_script, self.local_mirror_centos)

    # Install tools to masternode
    def install_tools(self, master_tools=None):
        if master_tools is None:
            master_tools = []
        logger.info("Installing necessary tools for {0}"
                    .format(settings.OPENSTACK_RELEASE))
        for master_tool in master_tools:
            exit_code = install_pkg_2(
                ip=self.ip,
                pkg_name=master_tool
            )
            assert_equal(0, exit_code, 'Cannot install package {0} '
                         'on admin node.'.format(master_tool))

    # Ubuntu: Creating list of packages from the additional mirror
    def get_pkgs_list_ubuntu(self):
        url = "{0}/{1}/Packages".format(self.custom_pkgs_mirror,
                                        self.custom_pkgs_mirror_path)
        logger.info("Retrieving additional packages from the custom mirror:"
                    " {0}".format(url))
        try:
            pkgs_release = urlopen(url).read()
        except (HTTPError, URLError):
            logger.error(traceback.format_exc())
            url_gz = '{0}.gz'.format(url)
            logger.info(
                "Retrieving additional packages from the custom mirror:"
                " {0}".format(url_gz))
            try:
                pkgs_release_gz = urlopen(url_gz).read()
            except (HTTPError, URLError):
                logger.error(traceback.format_exc())
                raise
            try:
                d = zlib.decompressobj(zlib.MAX_WBITS | 32)
                pkgs_release = d.decompress(pkgs_release_gz)
            except Exception:
                logger.error('Ubuntu mirror error: Could not decompress {0}\n'
                             '{1}'.format(url_gz, traceback.format_exc()))
                raise

        packages = (pkg for pkg in pkgs_release.split("\n\n") if pkg)
        for package in packages:
            upkg = {pstr.split()[0].lower(): ''.join(pstr.split()[1:])
                    for pstr in package.split("\n") if pstr[0].strip()}

            upkg_keys = ["package:", "version:", "filename:"]
            assert_equal(True, all(x in upkg for x in upkg_keys),
                         'Missing one of the statements ["Package:", '
                         '"Version:", "Filename:"] in {0}'.format(url))
            # TODO: add dependencies list to upkg
            self.pkgs_list.append(upkg)

    # Centos: Creating list of packages from the additional mirror
    def get_pkgs_list_centos(self):
        logger.info("Retrieving additional packages from the custom mirror:"
                    " {0}".format(self.custom_pkgs_mirror))
        url = "{0}/repodata/repomd.xml".format(self.custom_pkgs_mirror)
        try:
            repomd_data = urlopen(url).read()
        except (HTTPError, URLError):
            logger.error(traceback.format_exc())
            raise
        # Remove namespace attribute before parsing XML
        repomd_data = re.sub(' xmlns="[^"]+"', '', repomd_data, count=1)
        tree_repomd_data = ElementTree.fromstring(repomd_data)
        lists_location = ''
        for repomd in tree_repomd_data.findall('data'):
            if repomd.get('type') == 'primary':
                repomd_location = repomd.find('location')
                lists_location = repomd_location.get('href')

        assert_equal(True, lists_location is not '', 'CentOS mirror error:'
                     ' Could not parse {0}\nlists_location = "{1}"\n{2}'
                     .format(url, lists_location, traceback.format_exc()))
        url = "{0}/{1}".format(self.custom_pkgs_mirror, lists_location)
        try:
            lists_data = urlopen(url).read()
        except (HTTPError, URLError):
            logger.error(traceback.format_exc())
            raise
        if '.xml.gz' in lists_location:
            try:
                d = zlib.decompressobj(zlib.MAX_WBITS | 32)
                lists_data = d.decompress(lists_data)
            except Exception:
                logger.error('CentOS mirror error: Could not decompress {0}\n'
                             '{1}'.format(url, traceback.format_exc()))
                raise

        # Remove namespace attribute before parsing XML
        lists_data = re.sub(' xmlns="[^"]+"', '', lists_data, count=1)

        tree_lists_data = ElementTree.fromstring(lists_data)

        for flist in tree_lists_data.findall('package'):
            if flist.get('type') == 'rpm':
                flist_arch = flist.find('arch').text
                if flist_arch in self.centos_supported_archs:
                    flist_name = flist.find('name').text
                    flist_location = flist.find('location')
                    flist_file = flist_location.get('href')
                    flist_version = flist.find('version')
                    flist_ver = '{0}-{1}'.format(flist_version.get('ver'),
                                                 flist_version.get('rel'))
                    cpkg = {'package:': flist_name,
                            'version:': flist_ver,
                            'filename:': flist_file}
                    # TODO: add dependencies list to cpkg
                    self.pkgs_list.append(cpkg)

    # Download packages (local_folder)
    def download_pkgs(self, pkgs_local_path):
        # Process the packages list:
        total_pkgs = len(self.pkgs_list)
        logger.info('Found {0} custom package(s)'.format(total_pkgs))

        for npkg, pkg in enumerate(self.pkgs_list):
            # TODO: Previous versions of the updating packages must be removed
            # to avoid unwanted packet manager dependencies resolution
            # (when some package still depends on other package which
            # is not going to be installed)

            logger.info('({0}/{1}) Downloading package: {2}/{3}'
                        .format(npkg + 1, total_pkgs,
                                self.custom_pkgs_mirror,
                                pkg["filename:"]))

            pkg_ext = pkg["filename:"].split('.')[-1]
            if pkg_ext == 'deb':
                path_suff = 'main/'
            elif pkg_ext == 'udeb':
                path_suff = 'debian-installer/'
            else:
                path_suff = ''

            wget_cmd = "wget --no-verbose --directory-prefix {0} {1}/{2}"\
                       .format(pkgs_local_path + path_suff,
                               self.custom_pkgs_mirror,
                               pkg["filename:"])
            wget_result = self.ssh_manager.execute(
                ip=self.ip,
                cmd=wget_cmd
            )
            assert_equal(0, wget_result['exit_code'],
                         self.assert_msg(wget_cmd, wget_result['stderr']))

    # Upload regenerate* script to masternode (script name)
    def regenerate_repo(self, regenerate_script, local_mirror_path):
        # Uploading scripts that prepare local repositories:
        # 'regenerate_centos_repo' and 'regenerate_ubuntu_repo'
        try:
            self.ssh_manager.upload_to_remote(
                ip=self.ip,
                source='{0}/{1}'.format(self.path_scripts, regenerate_script),
                target=self.remote_path_scripts
            )
            self.ssh_manager.execute_on_remote(
                ip=self.ip,
                cmd='chmod 755 {0}/{1}'.format(self.remote_path_scripts,
                                               regenerate_script)
            )
        except Exception:
            logger.error('Could not upload scripts for updating repositories.'
                         '\n{0}'.format(traceback.format_exc()))
            raise

        # Update the local repository using previously uploaded script.
        script_cmd = '{0}/{1} {2} {3}'.format(self.remote_path_scripts,
                                              regenerate_script,
                                              local_mirror_path,
                                              self.ubuntu_release)
        script_result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=script_cmd
        )
        assert_equal(0, script_result['exit_code'],
                     self.assert_msg(script_cmd, script_result['stderr']))

        logger.info('Local repository {0} has been updated successfully.'
                    .format(local_mirror_path))

    @staticmethod
    def assert_msg(cmd, err):
        return 'Executing \'{0}\' on the admin node has failed with: {1}'\
               .format(cmd, err)

    def check_puppet_logs(self):
        logger.info("Check puppet logs for packages with unmet dependencies.")
        if settings.OPENSTACK_RELEASE_UBUNTU in settings.OPENSTACK_RELEASE:
            err_deps = self.check_puppet_logs_ubuntu()
        else:
            err_deps = self.check_puppet_logs_centos()

        for err_deps_key in err_deps.keys():
            logger.info('Error: Package: {0} has unmet dependencies:'
                        .format(err_deps_key))
            for dep in err_deps[err_deps_key]:
                logger.info('        {0}'.format(dep.strip()))
        logger.info("Check puppet logs completed.")

    def check_puppet_logs_ubuntu(self):
        """ Check puppet-agent.log files on all nodes for package
            dependency errors during a cluster deployment (ubuntu)"""

        err_start = 'The following packages have unmet dependencies:'
        err_end = ('Unable to correct problems,'
                   ' you have held broken packages.')
        cmd = ('fgrep -h -e " Depends: " -e "{0}" -e "{1}" '
               '/var/log/remote/node-*/'
               'puppet*.log'.format(err_start, err_end))
        result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=cmd
        )['stdout']

        err_deps = {}
        err_deps_key = ''
        err_deps_flag = False

        # Forming a dictionary of package names
        # with sets of required packages.
        for res_str in result:
            if err_deps_flag:
                if err_end in res_str:
                    err_deps_flag = False
                elif ": Depends:" in res_str:
                    str0, str1, str2 = res_str.partition(': Depends:')
                    err_deps_key = ''.join(str0.split()[-1:])
                    if err_deps_key not in err_deps:
                        err_deps[err_deps_key] = set()
                    if 'but it is not' in str2 or 'is to be installed' in str2:
                        err_deps[err_deps_key].add('Depends:{0}'
                                                   .format(str2))
                elif 'Depends:' in res_str and err_deps_key:
                    str0, str1, str2 = res_str.partition('Depends:')
                    if 'but it is not' in str2 or 'is to be installed' in str2:
                        err_deps[err_deps_key].add(str1 + str2)
                else:
                    err_deps_key = ''
            elif err_start in res_str:
                err_deps_flag = True

        return err_deps

    def check_puppet_logs_centos(self):
        """ Check puppet-agent.log files on all nodes for package
            dependency errors during a cluster deployment (centos)"""

        cmd = ('fgrep -h -e "Error: Package: " -e " Requires: " /var/log/'
               'remote/node-*/puppet*.log')
        result = self.ssh_manager.execute(
            ip=self.ip,
            cmd=cmd
        )['stdout']

        err_deps = {}
        err_deps_key = ''

        # Forming a dictionary of package names
        # with sets of required packages.
        for res_str in result:
            if 'Error: Package:' in res_str:
                err_deps_key = res_str.partition('Error: Package: ')[2]
                if err_deps_key not in err_deps:
                    err_deps[err_deps_key] = set()
            elif ' Requires: ' in res_str and err_deps_key:
                _, str1, str2 = res_str.partition(' Requires: ')
                err_deps[err_deps_key].add(str1 + str2)
            else:
                err_deps_key = ''

        return err_deps
示例#22
0
def replace_fuel_nailgun_rpm():
    """
    Replace fuel_nailgun*.rpm from review
    """
    logger.info("Patching fuel-nailgun")
    ssh = SSHManager()
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    pack_path = '/var/www/nailgun/fuel-nailgun/'

    full_pack_path = os.path.join(pack_path,
                                  'fuel-nailgun*.noarch.rpm')
    logger.info('Package path {0}'.format(full_pack_path))
    ssh.upload_to_remote(
        ip=ssh.admin_ip,
        source=settings.UPDATE_FUEL_PATH.rstrip('/'), target=pack_path)

    # Check old fuel-nailgun package
    cmd = "rpm -q fuel-nailgun"

    old_package = ssh.execute_on_remote(
        ip=ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info(
        'Current package version of '
        'fuel-nailgun: {0}'.format(old_package))

    cmd = "rpm -qp {0}".format(full_pack_path)
    new_package = ssh.execute_on_remote(
        ip=ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info("Updating package {0} with {1}".format(
        old_package, new_package))

    if old_package == new_package:
        logger.debug('Looks like package from review '
                     'was installed during setups of master node')
        return

    # stop services
    service_list = ['assassind', 'receiverd', 'nailgun', 'statsenderd']
    for service in service_list:
        ssh.execute_on_remote(
            ip=ssh.admin_ip, cmd='systemctl stop {0}'.format(service))
    logger.info('statistic services {0}'.format(get_oswl_services_names()))
    # stop statistic services
    for service in get_oswl_services_names():
        ssh.execute_on_remote(
            ip=ssh.admin_ip, cmd='systemctl stop {0}'.format(service))

    # Drop nailgun db manage.py dropdb
    cmd = 'manage.py dropdb'
    ssh.execute_on_remote(ssh.admin_ip, cmd)

    # Delete package
    logger.info("Delete package {0}".format(old_package))
    cmd = "rpm -e fuel-nailgun"
    ssh.execute_on_remote(ssh.admin_ip, cmd)

    logger.info("Install package {0}".format(new_package))

    cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)

    ssh.execute_on_remote(ssh.admin_ip, cmd)

    cmd = "rpm -q fuel-nailgun"
    installed_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']

    assert_equal(installed_package, new_package,
                 "The new package {0} was not installed".format(new_package))

    cmd = ('puppet apply --debug '
           '/etc/puppet/modules/fuel/examples/nailgun.pp')
    ssh.execute_on_remote(ssh.admin_ip, cmd)
    cmd_sync = 'fuel release --sync-deployment-tasks --dir /etc/puppet/'
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd_sync)
示例#23
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        return "[{klass}({obj_id})]".format(
            klass=klass,
            obj_id=obj_id)

    # TODO(kozhukalov): This method seems not needed and
    # can easily be replaced by using execute_on_remote
    # available in SSHManager (up to the type of return value)
    def execute(self, cmd, exit_code=None, stdin=None):
        if stdin is not None:
            cmd = 'echo "{0}" | {1}'.format(stdin, cmd)

        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd=cmd
        )
        if exit_code is not None:
            assert_equal(exit_code,
                         result['exit_code'],
                         ('Command {cmd} returned exit code "{e}", but '
                          'expected "{c}". Output: {out}; {err} ').format(
                             cmd=cmd,
                             e=result['exit_code'],
                             c=exit_code,
                             out=result['stdout'],
                             err=result['stderr']
                         ))
        return ''.join(result['stdout']).strip()

    def restart_service(self, service):
        result = self.ssh_manager(
            ip=self.admin_ip,
            cmd="systemctl restart {0}".format(service))
        return result['exit_code'] == 0

    def put_value_to_local_yaml(self, old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml, f_new, default_flow_style=False,
                      default_style='"')

    def get_value_from_local_yaml(self, yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError("Element {0} not found in the file {1}"
                                 .format(element[: i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}"
                               .format(element[: i + 1], f_old))
        return yaml_dict

    def change_remote_yaml(self, path_to_file, element, value):
        """Changes values in the yaml file stored
        There is no need to copy file manually
        :param path_to_file: absolute path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :return: Nothing
        """
        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=old_file
        )
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=new_file,
            target=path_to_file
        )
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_remote_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element
        :return obj: value
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=host_tmp_file
        )
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_remote_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored
           on the master node

        :param str path_to_file: absolute path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(
            ip=self.admin_ip,
            destination=path_to_file,
            target=host_tmp_file
        )
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file,
                                     element, value)
        self.ssh_manager.upload_to_remote(
            ip=self.admin_ip,
            source=host_tmp_file,
            target=path_to_file
        )
        os.remove(host_tmp_file)
示例#24
0
def check_package_version_injected_in_bootstraps(
        package,
        cluster_id=None,
        ironic=None):

    ssh = SSHManager()
    try:
        pack_path = '/var/www/nailgun/{}/'.format(package)
        ssh.upload_to_remote(
            ip=ssh.admin_ip,
            source=settings.UPDATE_FUEL_PATH.rstrip('/'),
            target=pack_path)
    except Exception:
        logger.exception("Could not upload package")
        raise

    # Step 1 - unpack active bootstrap
    logger.info("unpack active bootstrap")

    if ironic:
        bootstrap = "/var/www/nailgun/bootstrap/ironic/{}".format(cluster_id)
    else:
        bootstrap = "/var/www/nailgun/bootstraps/active_bootstrap"
    bootstrap_var = "/var/root.squashfs"

    cmd = "unsquashfs -d {} {}/root.squashfs".format(
        bootstrap_var, bootstrap)
    ssh.execute_on_remote(
        ip=ssh.admin_ip,
        cmd=cmd)

    # Step 2 - check package version
    logger.info(
        "check package {} version injected in ubuntu bootstrap".format(
            package))

    cmd = "ls {}|grep {} |grep deb |cut -f 2 -d '_'".format(
        pack_path, package)

    package_from_review = ssh.execute_on_remote(
        ip=ssh.admin_ip,
        cmd=cmd)['stdout_str']

    logger.info("package from review is {}".format(package_from_review))

    awk_pattern = "awk '{print $2}'"
    cmd = "chroot {}/ /bin/bash -c \"dpkg -s {}\"|grep Version|{}".format(
        bootstrap_var, package, awk_pattern)
    installed_package = ssh.execute_on_remote(
        ip=ssh.admin_ip,
        cmd=cmd)['stdout_str']
    logger.info("injected package is {}".format(installed_package))

    assert_equal(installed_package, package_from_review,
                 "The new package {0} wasn't injected in bootstrap".format(
                     package_from_review))

    # Step 3 - remove unpacked bootstrap
    cmd = "rm -rf {}".format(bootstrap_var)
    ssh.execute_on_remote(
        ip=ssh.admin_ip,
        cmd=cmd)
示例#25
0
class BaseActions(object):
    """BaseActions."""  # TODO documentation

    def __init__(self):
        self.ssh_manager = SSHManager()
        self.admin_ip = self.ssh_manager.admin_ip
        self.container = None

    def __repr__(self):
        klass, obj_id = type(self), hex(id(self))
        container = getattr(self, 'container', None)
        return "[{klass}({obj_id}), container:{container}]".format(
            klass=klass, obj_id=obj_id, container=container)

    def execute_in_container(self,
                             command,
                             container=None,
                             exit_code=None,
                             stdin=None):
        if not container:
            container = self.container
        cmd = 'dockerctl shell {0} {1}'.format(container, command)
        if stdin is not None:
            cmd = 'echo "{0}" | {1}'.format(stdin, cmd)

        result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd)
        if exit_code is not None:
            assert_equal(exit_code, result['exit_code'],
                         ('Command {cmd} returned exit code "{e}", but '
                          'expected "{c}". Output: {out}; {err} ').format(
                              cmd=cmd,
                              e=result['exit_code'],
                              c=exit_code,
                              out=result['stdout'],
                              err=result['stderr']))
        return ''.join(result['stdout']).strip()

    def copy_between_node_and_container(self, copy_from, copy_to):
        """ Copy files from/to container.
        :param copy_from: path to copy file from
        :param copy_to: path to copy file to
        For ex.:

            - to copy from container to master node use:
                 copy_from = container:path_from
                 copy_to = path_to
            - to copy from master node to container use:
                 copy_from = path_from
                 copy_to = container:path_to

        :return:
            Standard output from console
        """
        cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to)
        result = self.ssh_manager.execute(ip=self.admin_ip, cmd=cmd)
        assert_equal(0, result['exit_code'],
                     ('Command copy returned exit code "{e}", but '
                      'expected "0". Output: {out}; {err} ').format(
                          cmd=cmd,
                          e=result['exit_code'],
                          out=result['stdout'],
                          err=result['stderr']))
        return ''.join(result['stdout']).strip()

    @property
    def is_container_ready(self):
        result = self.ssh_manager.execute(
            ip=self.admin_ip,
            cmd="timeout 5 dockerctl check {0}".format(self.container))
        return result['exit_code'] == 0

    def wait_for_ready_container(self, timeout=300):
        wait(lambda: self.is_container_ready, timeout=timeout)

    def put_value_to_local_yaml(self, old_file, new_file, element, value):
        """Changes content in old_file at element is given to the new value
        and creates new file with changed content
        :param old_file: a path to the file content from to be changed
        :param new_file: a path to the new file to ve created with new content
        :param element: tuple with path to element to be changed
        for example: ['root_elem', 'first_elem', 'target_elem']
        if there are a few elements with equal names use integer
        to identify which element should be used
        :return: nothing
        """

        with open(old_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        origin_yaml = yaml_dict
        for k in element[:-1]:
            yaml_dict = yaml_dict[k]
        yaml_dict[element[-1]] = value

        with open(new_file, 'w') as f_new:
            yaml.dump(origin_yaml,
                      f_new,
                      default_flow_style=False,
                      default_style='"')

    def get_value_from_local_yaml(self, yaml_file, element):
        """Get a value of the element from the local yaml file

           :param str yaml_file: a path to the yaml file
           :param list element:
               list with path to element to be read
               for example: ['root_elem', 'first_elem', 'target_elem']
               if there are a few elements with equal names use integer
               to identify which element should be used
           :return obj: value
        """
        with open(yaml_file, 'r') as f_old:
            yaml_dict = yaml.load(f_old)

        for i, k in enumerate(element):
            try:
                yaml_dict = yaml_dict[k]
            except IndexError:
                raise IndexError(
                    "Element {0} not found in the file {1}".format(
                        element[:i + 1], f_old))
            except KeyError:
                raise KeyError("Element {0} not found in the file {1}".format(
                    element[:i + 1], f_old))
        return yaml_dict

    def change_yaml_file_in_container(self,
                                      path_to_file,
                                      element,
                                      value,
                                      container=None):
        """Changes values in the yaml file stored at container
        There is no need to copy file manually
        :param path_to_file: absolutely path to the file
        :param element: list with path to the element be changed
        :param value: new value for element
        :param container: Container with file. By default it is nailgun
        :return: Nothing
        """
        if not container:
            container = self.container

        old_file = '/tmp/temp_file_{0}.old.yaml'.format(str(os.getpid()))
        new_file = '/tmp/temp_file_{0}.new.yaml'.format(str(os.getpid()))

        self.copy_between_node_and_container(
            '{0}:{1}'.format(container, path_to_file), old_file)
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=old_file,
                                              target=old_file)
        self.put_value_to_local_yaml(old_file, new_file, element, value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=new_file,
                                          target=new_file)
        self.copy_between_node_and_container(
            new_file, '{0}:{1}'.format(container, path_to_file))
        os.remove(old_file)
        os.remove(new_file)

    def get_value_from_yaml(self, path_to_file, element):
        """Get a value from the yaml file stored in container
           or on master node if self.container is None

        :param str path_to_file: absolutely path to the file
        :param list element: list with path to the element be changed
        :return obj: value
        """

        if self.container:
            admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
            self.copy_between_node_and_container(
                '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file)
        else:
            admin_tmp_file = path_to_file

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=admin_tmp_file,
                                              target=host_tmp_file)
        value = self.get_value_from_local_yaml(host_tmp_file, element)
        os.remove(host_tmp_file)
        return value

    def put_value_to_yaml(self, path_to_file, element, value):
        """Put a value to the yaml file stored in container
           or on master node if self.container is None

        :param str path_to_file: absolutely path to the file
        :param list element: list with path to the element be changed
        :param value: new value for element
        :return: None
        """

        if self.container:
            admin_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
            self.copy_between_node_and_container(
                '{0}:{1}'.format(self.container, path_to_file), admin_tmp_file)
        else:
            admin_tmp_file = path_to_file

        host_tmp_file = '/tmp/temp_file_{0}.yaml'.format(str(os.getpid()))
        self.ssh_manager.download_from_remote(ip=self.admin_ip,
                                              destination=admin_tmp_file,
                                              target=host_tmp_file)
        self.put_value_to_local_yaml(host_tmp_file, host_tmp_file, element,
                                     value)
        self.ssh_manager.upload_to_remote(ip=self.admin_ip,
                                          source=host_tmp_file,
                                          target=admin_tmp_file)
        if self.container:
            self.copy_between_node_and_container(
                admin_tmp_file, '{0}:{1}'.format(self.container, path_to_file))
        os.remove(host_tmp_file)
示例#26
0
文件: utils.py 项目: jvalinas/fuel-qa
def replace_fuel_nailgun_rpm():
    """
    Replace fuel_nailgun*.rpm from review
    """
    logger.info("Patching fuel-nailgun")
    ssh = SSHManager()
    if not settings.UPDATE_FUEL:
        raise exceptions.FuelQAVariableNotSet('UPDATE_FUEL', 'True')
    pack_path = '/var/www/nailgun/fuel-nailgun/'

    full_pack_path = os.path.join(pack_path, 'fuel-nailgun*.noarch.rpm')
    logger.info('Package path {0}'.format(full_pack_path))
    ssh.upload_to_remote(ip=ssh.admin_ip,
                         source=settings.UPDATE_FUEL_PATH.rstrip('/'),
                         target=pack_path)

    # Check old fuel-nailgun package
    cmd = "rpm -q fuel-nailgun"

    old_package = ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info('Current package version of '
                'fuel-nailgun: {0}'.format(old_package))

    cmd = "rpm -qp {0}".format(full_pack_path)
    new_package = ssh.execute_on_remote(ip=ssh.admin_ip, cmd=cmd)['stdout_str']
    logger.info("Updating package {0} with {1}".format(old_package,
                                                       new_package))

    if old_package == new_package:
        logger.debug('Looks like package from review '
                     'was installed during setups of master node')
        return

    # stop services
    service_list = ['assassind', 'receiverd', 'nailgun', 'statsenderd']
    for service in service_list:
        ssh.execute_on_remote(ip=ssh.admin_ip,
                              cmd='systemctl stop {0}'.format(service))
    logger.info('statistic services {0}'.format(get_oswl_services_names()))
    # stop statistic services
    for service in get_oswl_services_names():
        ssh.execute_on_remote(ip=ssh.admin_ip,
                              cmd='systemctl stop {0}'.format(service))

    # Drop nailgun db manage.py dropdb
    cmd = 'manage.py dropdb'
    ssh.execute_on_remote(ssh.admin_ip, cmd)

    # Delete package
    logger.info("Delete package {0}".format(old_package))
    cmd = "rpm -e fuel-nailgun"
    ssh.execute_on_remote(ssh.admin_ip, cmd)

    logger.info("Install package {0}".format(new_package))

    cmd = "rpm -Uvh --oldpackage {0}".format(full_pack_path)

    ssh.execute_on_remote(ssh.admin_ip, cmd)

    cmd = "rpm -q fuel-nailgun"
    installed_package = ssh.execute_on_remote(ssh.admin_ip, cmd)['stdout_str']

    assert_equal(installed_package, new_package,
                 "The new package {0} was not installed".format(new_package))

    cmd = ('puppet apply --debug '
           '/etc/puppet/modules/fuel/examples/nailgun.pp')
    ssh.execute_on_remote(ssh.admin_ip, cmd)
    cmd_sync = 'fuel release --sync-deployment-tasks --dir /etc/puppet/'
    ssh.execute_on_remote(ssh.admin_ip, cmd=cmd_sync)