Ejemplo n.º 1
0
def run_install(engage_bin_dir, sw_packages_dir, package_file_list,
                logger, alternative_package_name=None,
                never_download=False):
    """Does an install into the engage virtualenv. See if there is a
    matching package in the sw_packages_dir from the package file list. If so,
    install it. Otherwise, use the alternative package name (if one was provided).
    """
    install_exe = os.path.join(engage_bin_dir, "pip")
    assert os.path.exists(install_exe), "Cound not find pip executable at %s" % install_exe
    package_file_or_name = alternative_package_name
    is_local_file = False
    for package_file in package_file_list:
        package_path = os.path.join(sw_packages_dir, package_file)
        if os.path.exists(package_path):
            package_file_or_name = package_path
            is_local_file = True
            break
    if not package_file_or_name:
        raise Exception("Unable to find required python package %s" % package_path)
    elif never_download and (not is_local_file):
        raise Exception("Unable to find local copy of package and --never-download was specified. Package list was %s" % package_file_list)
                
    logger.info("Installing bootstrap python package: %s install %s" % (
            install_exe, package_file_or_name))
    rc = system("%s install %s" % (install_exe, package_file_or_name), logger)
    if rc != 0:
        raise Exception("pip install for %s failed" % package_file_or_name)
    logger.info("pip install successful")
Ejemplo n.º 2
0
def is_package_installed(engage_bin_dir, package_name, logger):
    rc = system('%s -c "import %s"' %
                (os.path.join(engage_bin_dir, "python"),
                 package_name), logger)
    if rc == 0:
        logger.debug("Package '%s' already installed" %
                     package_name)
        return True
    else:
        logger.debug("Package '%s' not already installed" %
                     package_name)
        return False
Ejemplo n.º 3
0
def create_virtualenv(desired_python_dir, logger, package_dir,
                      base_python_exe=None,
                      never_download=False):
    virtualenv_search_dirs = get_python_search_paths()
    python_exe = find_python_executable(logger, explicit_path=base_python_exe)
    # we start our virtualenv executable search at the same place as where we have
    # the python executable. Then, we check a bunch of well-known places to stick
    # virtualenv
    virtualenv_search_dirs = [os.path.dirname(python_exe)] + get_python_search_paths()
    virtualenv = find_executable("virtualenv", virtualenv_search_dirs, logger)
    version = get_virtualenv_version(virtualenv)
    if compare_versions("1.6.1", version)>=0:
        # --never-download and --extra-search-dir were added in 1.6.1
        has_options = True
    else:
        has_options = False
    if compare_versions("1.7", version)>=0:
        site_packages_opt = True
    else:
        site_packages_opt = False
        
    if not os.path.exists(desired_python_dir):
        os.makedirs(desired_python_dir)
    opts = ["--python=%s" % python_exe,]
    if site_packages_opt:
        opts.append("--system-site-packages")
    if has_options:
        opts.append("--extra-search-dir=%s" % package_dir)
        if never_download:
            opts.append("--never-download")
    elif never_download:
        raise Exception("--never-download option requires virtualenv 1.6.1 or later")
    # JF 6/7/2011: removed --no-site-packages command line option, as it makes
    # it hard to use pre-built packages installed by the package manager,
    # like py-mysql
    cmd = "%s %s %s" % (virtualenv, ' '.join(opts), desired_python_dir)
    logger.info('create virtualenv running command: %s' % cmd)
    rc = system(cmd, logger, cwd=desired_python_dir)
    if rc != 0:
        raise Exception("Execution of '%s' failed, rc was %d" % (cmd, rc))
Ejemplo n.º 4
0
def main(argv):
    usage = "usage: %prog [options] deployment_home"
    parser = OptionParser(usage=usage)
    add_log_option(parser)
    parser.add_option("-d", "--logdir", action="store",
                      type="string",
                      help="master log directory for deployment (defaults to <deployment_home>/log)",
                      dest="logdir", default=None)
    parser.add_option("-c", "--create-dist-archive",
                      action="store_true",
                      help="create a distribution archive",
                      dest="create_dist_archive", default=False)
    parser.add_option("-x", "--python",
                      default=None,
                      help="Use the specified python executable as basis for Python virtual environments",
                      dest="python_exe")
    parser.add_option("--never-download",
                      default=False,
                      action="store_true",
                      help="If specified, never try to download packages during bootstrap. If a package is required, exit with an error.",
                      dest="never_download")
    parser.add_option("--include-test-data",
                      default=False,
                      action="store_true",
                      help="If specified, copy test data into the deployment home. Otherwise, tests requiring data will be skipped.")
    (options, args) = parser.parse_args(args=argv)
    if len(args) != 1:
        parser.error("Expecting exactly one argument, the deployment's home directory")
        
    logger = setup_logger("Bootstrap", __name__)

    if options.python_exe:
        options.python_exe = os.path.abspath(os.path.expanduser(options.python_exe))
        if not os.path.exists(options.python_exe):
            parser.error("Python executable %s does not exist" %
                         options.python_exe)
        if not os.access(options.python_exe, os.X_OK):
            parser.error("Python executable file %s is not an executable" %
                         options.python_exe)

    test_data_src = os.path.join(base_src_dir, "test_data")
    if options.include_test_data and not os.path.isdir(test_data_src):
        parser.error("--include-test-data specified, but test data directory %s does not exist" % test_data_src)
        
    deployment_home = os.path.abspath(os.path.expanduser(args[0]))
    if os.path.exists(deployment_home):
        sentry_file = os.path.join(deployment_home, "config/installed_resources.json")
        if os.path.exists(sentry_file):
            raise Exception("Deployment home directory %s exists and contains the file %s. Cannot overwrite an existing install." %
                            (deployment_home, sentry_file))
    else:
        os.makedirs(deployment_home)

    if options.logdir:
        log_dir = os.path.abspath(os.path.expanduser(options.logdir))
    else:
        log_dir = os.path.join(deployment_home, "log")
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    parse_log_options(options, log_dir)
    logger.info("Running bootstrap under Python executable %s" % sys.executable)

    # the engage home is just a python virtual environment
    engage_home = os.path.join(deployment_home, "engage")

    sw_packages_src_loc = os.path.join(base_src_dir, "sw_packages")
    sw_packages_dst_loc = os.path.join(engage_home, "sw_packages")

    create_virtualenv(engage_home, logger,
                      sw_packages_src_loc,
                      base_python_exe=options.python_exe,
                      never_download=options.never_download)
    logger.info("Created python virtualenv for engage")

    # copy this bootstrap script and the upgrade script
    bootstrap_py_dst = os.path.join(engage_home, "bootstrap.py")
    shutil.copyfile(os.path.join(base_src_dir, "bootstrap.py"), bootstrap_py_dst)
    os.chmod(bootstrap_py_dst, 0755)
    upgrade_py_src = os.path.join(base_src_dir, "upgrade.py")
    upgrade_py_dst = os.path.join(engage_home, "upgrade.py")
    shutil.copyfile(upgrade_py_src, upgrade_py_dst)
    os.chmod(upgrade_py_dst, 0755)
               
    # we also copy the python_pkg directory to the distribution home for use in creating
    # future distributions
    python_pkg_dst_dir = os.path.join(engage_home, "python_pkg")
    copy_tree(python_pkg_dir, python_pkg_dst_dir, logger)

    # we need to run the setup.py script for the python_pkg
    engage_bin_dir = os.path.join(engage_home, "bin")
    engage_python_exe = os.path.join(engage_bin_dir, "python")
    assert os.path.exists(engage_python_exe), "Python executable at %s missing" % engage_python_exe
    setup_py_file = os.path.join(python_pkg_dir, "setup.py")
    assert os.path.exists(setup_py_file), "Missing %s" % setup_py_file
    cmd = "%s %s install" % (engage_python_exe, setup_py_file)
    rc = system(cmd, logger, cwd=python_pkg_dir)
    if rc != 0:
        raise Exception("Install of engage python packages failed: '%s' failed, rc was %d" % (cmd, rc))
    logger.info("Installed python packages")

    platform = get_platform()

    # copy the configurator binary
    config_exe_src_loc = os.path.join(base_src_dir, "bin/configurator-%s" % platform)
    assert os.path.exists(config_exe_src_loc), "Configurator executable missing at %s" % config_exe_src_loc
    config_exe_dst_loc = os.path.join(engage_bin_dir, "configurator-%s" % platform)
    logger.action("cp %s %s" % (config_exe_src_loc, config_exe_dst_loc))
    shutil.copyfile(config_exe_src_loc, config_exe_dst_loc)
    os.chmod(config_exe_dst_loc, 0755)
    symlink_loc = os.path.join(engage_bin_dir, "configurator")
    logger.action("ln -s %s %s" % (config_exe_dst_loc, symlink_loc))
    os.symlink(config_exe_dst_loc, symlink_loc)

    # copy the metadata files
    metadata_files_src_loc = os.path.join(base_src_dir, "metadata")
    metadata_files_dst_loc = os.path.join(engage_home, "metadata")
    copy_tree(metadata_files_src_loc, metadata_files_dst_loc, logger)

    # copy the sw_packages directory
    copy_tree(sw_packages_src_loc, sw_packages_dst_loc, logger)

    if not is_package_installed(engage_bin_dir, "Crypto.Cipher.AES", logger):
        if get_platform()=="linux64" and (not options.never_download):
            run_apt_install("python-crypto", logger)
        else:
            # Pycrypto may be preinstalled on the machine.
            # If so, we don't install our local copy, as installation
            # can be expensive (involves a g++ compile).
            run_install(engage_bin_dir, sw_packages_src_loc,
                        ["pycrypto-2.3-%s.tar.gz" % platform, "pycrypto-2.3.tar.gz"],
                        logger, "pycrypto",
                        never_download=options.never_download)

    bootstrap_packages = [# JF 2012-05-11: Don't install provision and its
                          # dependencies - moving down to DJM level.
                          #(["paramiko-1.7.6.zip"], "paramiko"),
                          #(["apache-libcloud-0.6.2.tar.bz2"], None),
                          #(["argparse-1.2.1.tar.gz"], "argparse"),
                          #(["provision-0.9.3-dev.tar.gz"], None),
                          (["nose-1.0.0.tar.gz"], "nose"),
                          (["engage_utils-1.0.tar.gz"], "git+git://github.com/genforma/engage-utils.git")]
    # run install for all of the bootstrap packages
    for (package_file_list, alternate) in bootstrap_packages:
        run_install(engage_bin_dir, sw_packages_src_loc,
                    package_file_list,
                    logger, alternate,
                    never_download=options.never_download)
    
    # create a virtualenv for the deployed apps
    deployed_virtualenv = os.path.join(deployment_home, "python")
    create_virtualenv(deployed_virtualenv, logger,
                      sw_packages_src_loc,
                      base_python_exe=options.python_exe,
                      never_download=options.never_download)
    logger.info("Created a virtualenv for deployed apps")

    deployed_config_dir = os.path.join(deployment_home, "config")
    os.makedirs(deployed_config_dir)
    # don't use "with" as this should be python 2.5 compatible
    f = open(os.path.join(deployed_config_dir, "log_directory.txt"), "wb")
    try:
        f.write(log_dir)
    finally:
        f.close()

    # copy the test data if requested
    if options.include_test_data:
        test_data_dest = os.path.join(engage_home, "test_data")
        copy_tree(test_data_src, test_data_dest, logger)

    if options.create_dist_archive:
        logger.info("Creating a distribution")
        import engage.engine.create_distribution
        engage.engine.create_distribution.create_distribution_from_deployment_home(deployment_home, include_test_data=options.include_test_data)
        
    logger.info("Engage environment bootstrapped successfully")
    return 0
Ejemplo n.º 5
0
def run_apt_install(package_name, logger):
    rc = system("/usr/bin/sudo /usr/bin/apt-get install -y -q %s", logger)
    if rc != 0:
        raise Exception("apt-get install for %s failed" % package_name)
    logger.info("apt-get install for %s successful" % package_name)