Esempio n. 1
0
def do_run(args, env):
    """The "ravello run" command."""
    login.default_login()
    keypair.default_keypair()
    manif = manifest.default_manifest()

    appname = args.application
    for appdef in manif.get('applications', []):
        if appdef['name'] == appname:
            break
    else:
        error.raise_error("Unknown application `{0}`.", appname)

    vms = set((vm['name'] for vm in appdef.get('vms', [])))
    if args.vms:
        only = set((name for name in args.vms.split(',')))
        if not only <= vms:
            unknown = [name for name in only if name not in vms]
            what = inflect.plural_noun('virtual machine', len(unknown))
            error.raise_error("Unknown {0}: {1}", ', '.join(unknown), what)
        vms = [name for name in vms if name in only]
    if not vms:
        error.raise_error('No virtual machines in application.')

    app = application.create_or_reuse_application(appdef, args.new)
    app = application.wait_for_application(app, vms)

    if args.command:
        for vm in appdef['vms']:
            for task in vm['tasks']:
                if task['name'] == 'execute':
                    task['commands'] = [args.command]
    elif args.dry_run:
        for vm in appdef['vms']:
            vm['tasks'] = []

    ret = tasks.run_all_tasks(app, vms)

    console.info('\n== The following services will be available for {0} '
                 'minutes:\n', appdef['keepalive'])

    for vm in app['vms']:
        if vm['name'] not in vms:
            continue
        svcs = vm.get('suppliedServices')
        if not svcs:
            continue
        console.info('On virtual machine `{0}`:', vm['name'])
        for svc in svcs:
            svc = svc['baseService']
            addr = util.format_service(vm, svc)
            console.info('    * {0}: {1}', svc['name'], addr)
        console.info('')

    return error.EX_OK if ret == 0 else error.EX_SOFTWARE
Esempio n. 2
0
def _setup_testmill():
    """Set up or re-sync a TestMill "env" from a Fabric "env". Also set some
    useful defaults in the Fabric environment for using TestMill.

    In essense this is a bridge between Fabric and the TestMill package.
    """
    env.quiet = False
    env.verbose = fab.output.debug
    env.manifest = None
    env.debug = fab.output.debug
    env.always_confirm = False
    if not hasattr(fab.env, 'ravello_user'):
        fab.env.ravello_user = '******'
    if not hasattr(fab.env, 'ravello_api_user'):
        fab.env.ravello_api_user = None
    if not hasattr(fab.env, 'ravello_api_password'):
        fab.env.ravello_api_password = None
    if not hasattr(fab.env, 'ravello_api_url'):
        fab.env.ravello_api_url = None
    if not hasattr(env, 'api'):
        main.setup_logging()
        env.service_url = fab.env.ravello_api_url
        env.api = ravello.RavelloClient(service_url=env.service_url)
        try:
            login.token_login()
        except error.ProgramError:
            if not fab.env.ravello_api_user:
                msg = 'Please enter your Ravello username: '******'Please enter your Ravello password: '******'public_key'):
        keypair.default_keypair()
        key_filename = env.private_key_file
        if fab.env.key_filename is None:
            fab.env.key_filename = key_filename
        elif isinstance(fab.env, compat.str):
            fab.env.key_filename = [fab.env.key_filename, key_filename]
        elif isinstance(fab.env, list):
            fab.env.key_filename.append(key_filename)
Esempio n. 3
0
def do_save(args, env):
    """The "ravello save" command."""

    with env.let(quiet=True):
        login.default_login()
        keypair.default_keypair()
        manif = manifest.default_manifest(required=False)

    app = application.default_application(args.application)
    appname = app["name"]
    project, defname, instance = appname.split(":")

    state = application.get_application_state(app)
    if state not in ("STOPPED", "STARTED"):
        error.raise_error(
            "Application `{0}:{1}` is currently in state {2}.\n" "Can only create blueprint when STOPPED or STARTED.",
            defname,
            instance,
            state,
        )

    if state == "STARTED" and not env.always_confirm:
        console.info("Application `{0}:{1}` is currently running.", defname, instance)
        result = console.confirm("Do you want to continue with a live snapshot")
        if not result:
            console.info("Not confirmed.")
            return error.EX_OK

    template = "{0}:{1}".format(project, defname)
    bpname = util.get_unused_name(template, cache.get_blueprints())
    parts = bpname.split(":")

    console.info("Saving blueprint as `{0}:{1}`.", parts[1], parts[2])

    blueprint = env.api.create_blueprint(bpname, app)
    env.blueprint = blueprint  # for tests

    console.info("Blueprint creation process started.")
    console.info("Use 'ravtest ps -b' to monitor progress.")

    return error.EX_OK
Esempio n. 4
0
def do_ps(args, env):
    """The "ravello ps" command."""
    with env.let(quiet=True):
        login.default_login()
        pubkey = keypair.default_keypair()
        manif = manifest.default_manifest(required=False)

    if manif is None and not args.all:
        error.raise_error('Project manifest ({0}) not found.\n'
                          "Use 'ravtest ps -a' to list all applications.",
                          manifest.manifest_name())
    if args.all:
        project = None
    else:
        project = manif['project']['name']
        console.info('Project name is `{0}`.', project)
    
    if args.blueprint:
        apps = cache.find_blueprints(project)
        what = 'blueprint'
    else:
        apps = cache.find_applications(project)
        what = 'application'

    apps = sorted(apps, key=lambda app: app['name'])
    objs = inflect.plural_noun(what)
    console.writeln('Currently available {0}:\n', objs)

    current_project = None
    for app in apps:
        parts = app['name'].split(':')
        if parts[0] != project and not args.all:
            continue
        if args.all and current_project != parts[0]:
            console.writeln("== Project: `{0}`", parts[0])
            current_project = parts[0]
        if args.full and not args.blueprint:
            app = cache.get_application(app['id'])

        cloud = app.get('cloud')
        region = app.get('regionName')
        started = app.get('totalStartedVms')
        publish_time = app.get('publishStartTime')
        creation_time = app.get('creationTime')
        created = publish_time or creation_time
        if created:
            now = time.time()
            created = util.format_timedelta(now - created/1000)
            created = '{0} ago'.format(created)
        else:
            created = ''
        if args.full and not args.blueprint:
            vms = [ vm['name'] for vm in application.get_vms(app) ]
            vms = '`{0}`'.format('`, `'.join(vms))
            state = application.get_application_state(app)
        else:
            state = app.get('state') or ''

        console.writeln('=== {0}: `{1}:{2}`', what.title(), parts[1], parts[2])
        what2 = inflect.plural_noun('VM', started)
        if state:
            console.writeln('    state: {0}', state)
        if started is not None:
            console.writeln('    {0} {1} running', started, what2)
        if cloud is not None:
            console.writeln('    published to {0}/{1}', cloud, region)
        if created:
            console.writeln('    created: {0}', created)
        if args.full and not args.blueprint:
            console.writeln('    VMs: {0}', vms)
        console.writeln()

    return error.EX_OK
Esempio n. 5
0
def do_ssh(args, env):
    """The "ravello ssh" command."""

    with env.let(quiet=True):
        login.default_login()
        keypair.default_keypair()

    if manifest.manifest_exists():
        with env.let(quiet=True):
            manif = manifest.default_manifest()
    else:
        manif = None

    parts = args.application.split(':')
    if len(parts) in (1, 2) and manif is None:
        error.raise_error('No manifest found ({0}).\n'
                          'Please specify the fully qualified app name.\n'
                          'Use `ravtest ps --all` for a list.',
                          manifest.manifest_name())
    if len(parts) in (1, 2):
        project = manif['project']['name']
        console.info('Project name is `{0}`.', project)
        defname = parts[0]
        instance = parts[1] if len(parts) == 2 else None
    elif len(parts) == 3:
        project, defname, instance = parts
    else:
        error.raise_error('Illegal application name: `{0}`.', appname)

    apps = cache.find_applications(project, defname, instance)
    if len(apps) == 0:
        error.raise_error('No instances of application `{0}` exist.',
                          defname)
    elif len(apps) > 1:
        error.raise_error('Multiple instances of `{0}` exist.\n'
                          'Use `ravtest ps` to list the instances and then\n'
                          'specify the application with its instance id.',
                          defname)
    app = cache.get_application(apps[0]['id'])
    appname = app['name']
    _, _, instance = appname.split(':')

    vmname = args.vm
    vm = application.get_vm(app, vmname)
    if vm is None:
        error.raise_error('Application `{0}:{1}` has no VM named `{2}`.\n'
                          'Use `ravtest ps --full` to see a list of VMs.',
                          defname, instance, vmname)
    console.info("Connecting to VM `{0}` of application `{1}:{2}`...",
                 vmname, defname, instance)

    # Start up the application and wait for it if we need to.

    state = application.get_application_state(app)
    if state not in ('PUBLISHING', 'STARTING', 'STOPPED', 'STARTED'):
        error.raise_error("VM `{0}` is in an unknown state.", vmname)

    userdata = vm.get('customVmConfigurationData', {})
    vmkey = userdata.get('keypair', {})

    if vmkey.get('id') != env.public_key['id']:
        error.raise_error("VM uses unknown public key `{0}`.",
                          vmkey.get('name'))

    application.start_application(app)
    application.wait_for_application(app, [vmname])

    # Now run ssh. Prefer openssh but fall back to using Fabric/Paramiko.

    host = 'ravello@{0}'.format(vm['dynamicMetadata']['externalIp'])
    command = '~/bin/run {0}'.format(args.testid)

    openssh = util.find_openssh()
    interactive = os.isatty(sys.stdin.fileno())

    if interactive and openssh:
        if not sys.platform.startswith('win'):
            # On Unix use execve(). This is the most efficient.
            argv = ['ssh', '-i', env.private_key_file,
                    '-o', 'UserKnownHostsFile=/dev/null',
                    '-o', 'StrictHostKeyChecking=no',
                    '-o', 'LogLevel=quiet',
                    '-t',  host, command]
            console.debug('Starting {0}', ' '.join(argv))
            os.execve(openssh, argv, os.environ)
        else:
            # Windows has execve() but for some reason it does not work
            # well with arguments with spaces in it. So use subprocess
            # instead.
            command = [openssh, '-i', env.private_key_file,
                       '-o', 'UserKnownHostsFile=NUL',
                       '-o', 'StrictHostKeyChecking=no',
                       '-o', 'LogLevel=quiet',
                       '-t', host, command]
            ssh = subprocess.Popen(command)
            ret = ssh.wait()
            error.exit(ret)

    # TODO: should also support PuTTY on Windows

    console.info(textwrap.dedent("""\
            Warning: no local openssh installation found.
            Falling back to Fabric/Paramiko for an interactive shell.
            However, please note:

            * CTRL-C and terminal resize signals may not work.
            * Output of programs that repaint the screen may
              be garbled (e.g. progress bars).
            """))

    fab.env.host_string = host
    fab.env.key_filename = env.private_key_file
    fab.env.disable_known_hosts = True
    fab.env.remote_interrupt = True
    fab.env.output_prefix = None
    fabric.state.output.running = None
    fabric.state.output.status = None

    ret = fab.run(command, warn_only=True)
    return ret.return_code