def add_standard_cmdline_options(parser, uses_pw_file=True,
                                 running_deployment=True,
                                 default_log_level="INFO"):
    """These are the command line options used by 
    """
    log_setup.add_log_option(parser, default=default_log_level)
    parser.add_option("--deployment-home", "-d", dest="deployment_home",
                      default=None,
                      help="Location of deployed application - can figure this out automatically unless installing from source")
    if uses_pw_file:
        if running_deployment:
            parser.add_option("-p", "--master-password-file", default=None,
                              help="File containing master password (if not specified, will prompt from console if needed). If --suppress-master-password-file is not set, and the master password file is not already at <deployment_home>/config/master.pw, a master password file will be generated at that location. Permissions will be set to 0600.")
            parser.add_option("--generate-random-passwords", "-g",
                              default=False, action="store_true",
                              help="If passwords are needed for individual components to be installed, generate random passwords rather than prompting for them")
            parser.add_option("--suppress-master-password-file", default=False,
                              action="store_true",
                              help="If specified, do not create a file containing the master password at <deployment_home>/config/master.pw.")
        else:
            parser.add_option("-p", "--master-password-file", default=None,
                              help="File containing master password. If not specified, will look for file at <deployment_home>/config/master.pw. If that file is not present, prompt from console if needed)")
        ## parser.add_option("--generate-password-file", "-g",
        ##                   dest="generate_password_file",
        ##                   default=False, action="store_true",
        ##                   help="If specified, generate a password file and exit")
        parser.add_option("-s", "--subproc", action="store_true", dest="subproc",
                          default=False, help="Run in subprocess mode, getting master password from standard input")
    if running_deployment:
        parser.add_option("--mgt-backends", dest="mgt_backends", default=None,
                          help="If specified, a list of management backend plugin(s)")
        parser.add_option("--force-stop-on-error", dest="force_stop_on_error",
                          default=False, action="store_true",
                          help="If specified, force stop any running daemons if the install fails. Default is to leave things running (helpful for debugging).")
        parser.add_option("-n", "--dry-run", action="store_true",
                          default=False,
                          help="If specified, just do a dry run and exit")
Exemple #2
0
    def process_args(self, argv):
        usage = "usage: %prog [options] deployment_home"
        parser = OptionParser(usage=usage)
        add_log_option(parser)
        parser.add_option("--application-archive", "-a", dest="application_archive", action="store",
                          default=None,
                          help="If specified, override the application_archive property in config choices file with this value")        
        parser.add_option("-s", "--subproc", action="store_true", dest="subproc",
                          default=False, help="Run in subprocess mode, getting master password from standard input")
        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("-p", "--master-password-file", default=None,
                          help="File containing master password (if not specified, will prompt from console if needed)")

        (self.options, args) = parser.parse_args(args=argv)
        if len(args) != 1:
            parser.error("Expecting exactly one argument, the deployment's home directory")
        self.deployment_home = os.path.abspath(os.path.expanduser(args[0]))
        if not os.path.exists(self.deployment_home):
            parser.error("Deployment home %s not found" % self.deployment_home)

        self.config_dir = os.path.join(self.deployment_home, "config")
        if not os.path.exists(self.config_dir):
            parser.error("Configuration directory %s does not exist" % self.config_dir)
        log_directory_file = os.path.join(self.config_dir, "log_directory.txt")
        if not os.path.exists(log_directory_file):
            parser.error("Log directory pointer file %s does not exit" % log_directory_file)
        with open(log_directory_file, "r") as f:
            self.log_directory = f.read().rstrip()
        parse_log_options(self.options, self.log_directory)
        if self.options.python_exe:
            if not os.path.exists(self.options.python_exe):
                parser.error("Python executable %s does not exist" % self.options.python_exe)
        if self.options.master_password_file:
            if not os.path.exists(self.options.master_password_file):
                parser.error("Master password file %s not found" %
                             self.options.master_password_file)

        self.engage_home = os.path.join(self.deployment_home, "engage")
        if not os.path.isdir(self.engage_home):
            parser.error("Engage home %s does not exist" % self.engage_home)
        self.engage_bin_dir = os.path.join(self.engage_home, "bin")
        if not os.path.isdir(self.engage_bin_dir):
            parser.error("Engage binary directory %s does not exist" % self.engage_bin_dir)

        if self.options.application_archive:
            self.application_archive = os.path.abspath(os.path.expanduser(self.options.application_archive))
            if not os.path.exists(self.application_archive):
                parser.error("Application archive file %s does not exist" % self.application_archive)

        if os.path.exists(os.path.join(self.config_dir, "pw_repository")):
            if self.options.master_password_file:
                with open(self.options.master_password_file, "rb") as f:
                    self.master_pw = f.read().rstrip()
            elif self.options.subproc:
                self.master_pw = sys.stdin.read().rstrip()
            else:
                while True:
                    self.master_pw = getpass.getpass("Master password:"******"Re-enter Master password:"******"Passwords do not match, try again."                
Exemple #3
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