Ejemplo 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
Ejemplo n.º 2
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
Ejemplo n.º 3
0
def wait_until_application_accepts_ssh(app, vms, timeout=None,
                                       poll_timeout=None):
    """Wait until an application is reachable by ssh.

    An application is reachable by SSH if all the VMs that have a public key in
    their userdata are connect()able on port 22. 
    """
    if timeout is None:
        timeout = 300
    if poll_timeout is None:
        poll_timeout = 5
    waitaddrs = set((vm['dynamicMetadata']['externalIp']
                     for vm in app['vms'] if vm['name'] in vms))
    aliveaddrs = set()
    end_time = time.time() + timeout
    # For the intricate details on non-blocking connect()'s, see Stevens,
    # UNIX network programming, volume 1, chapter 16.3 and following.
    while True:
        if time.time() > end_time:
            break
        waitfds = {}
        for addr in waitaddrs:
            sock = socket.socket()
            sock.setblocking(False)
            try:
                sock.connect((addr, 22))
            except socket.error as e:
                if e.errno not in nb_connect_errors:
                    console.debug('connect(): errno {.errno}'.format(e))
                    continue
            waitfds[sock.fileno()] = (sock, addr)
        poll_end_time = time.time() + poll_timeout
        while True:
            timeout = poll_end_time - time.time()
            if timeout < 0:
                for fd in waitfds:
                    sock, _ = waitfds[fd]
                    sock.close()
                break
            try:
                wfds = list(waitfds)
                _, wfds, _ = select.select([], wfds, [], timeout)
            except select.error as e:
                if e.args[0] == errno.EINTR:
                    continue
                console.debug('select(): errno {.errno}'.format(e))
                raise
            for fd in wfds:
                assert fd in waitfds
                sock, addr = waitfds[fd]
                try:
                    err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
                except socket.error as e:
                    err = e.errno
                sock.close()
                if not err:
                    aliveaddrs.add(addr)
                    waitaddrs.remove(addr)
                del waitfds[fd]
            if not waitfds:
                break
        if not waitaddrs:
            return
        console.show_progress('C')  # 'C' = Connecting
        time.sleep(max(0, poll_end_time - time.time()))
    unreachable = set((vm['name'] for vm in app['vms']
                       if vm['dynamicMetadata']['externalIp'] in waitaddrs))
    noun = inflect.plural_noun('VM', len(unreachable))
    vmnames = '`{0}`'.format('`, `'.join(sorted(unreachable)))
    error.raise_error('{0} `{1}` did not become reachable within {2} seconds.',
                      noun, vmnames, timeout)
Ejemplo n.º 4
0
def run_all_tasks(app, vms):
    """Run the runbook for an application ``app``."""
    hosts = []
    host_info = {}
    appname = app['name'].split(':')[1]
    for appdef in env.manifest['applications']:
        if appdef['name'] == appname:
            break
    else:
        error.raise_error('Application definition not found?')

    for vm in app['vms']:
        if vm['name'] not in vms:
            continue
        ipaddr = vm['dynamicMetadata']['externalIp']
        hosts.append(ipaddr)
        host_info[ipaddr] = vm['name']

    env.test_id = os.urandom(16).encode('hex')
    console.info('Starting run `{0}`.', env.test_id)
    env.host_info = host_info
    env.start_time = int(time.time())
    env.lock = multiprocessing.Lock()
    manager = multiprocessing.Manager()
    env.shared_state = manager.dict()
    for vmname in vms:
        vmstate = {}
        vmstate['exited'] = False
        vmstate['completed_tasks'] = {}
        vmstate['shell_env_update'] = {}
        env.shared_state[vmname] = vmstate
    env.appdef = appdef
    env.application = app
    env.vms = vms

    fab.env.user = '******'
    fab.env.key_filename = env.private_key_file
    fab.env.disable_known_hosts = True
    fab.env.remote_interrupt = True
    fab.env.hosts = hosts
    fab.env.parallel = True
    fab.env.output_prefix = env.debug
    fabric.state.output.running = env.debug
    fabric.state.output.output = True
    fabric.state.output.status = env.debug

    # This is where it all happens...
    noun = inflect.plural_noun('virtual machine', len(vms))
    console.info('Executing tasks on {0} {1}...', len(vms), noun)

    fabric.tasks.execute(run_tasklist, env)

    errors = set()
    for vmname in vms:
        vmstate = env.shared_state[vmname]
        for taskname,status in vmstate['completed_tasks'].items():
            if status != 0:
                errors.add('`{0}` on `{1}`'.format(taskname, vmname))

    if not errors:
        console.info('All tasks were executed succesfully!')
    else:
        what = inflect.plural_noun('task', len(errors))
        errapps = ', '.join(errors)
        console.error('The following {0} failed: {1}', what, errapps)

    fabric.network.disconnect_all()
    return len(errors)