Exemple #1
0
def vm_reaper():
    """ Iterates through each task in the db which has not yet been cleaned and runs the reaper

    This function iterates through each task. If the task is either failed or passed, ie, the
    task has completed, then the VM is cleaned up and then the docker container. If both of
    these operations occur, then the cleanup is set to True.
    """
    tasks = tapi.task().get(cleanup=False)['objects']
    for task in tasks:
        if task['result'] in ["failed", "passed", "invalid"]:
            vm_cleanup = False
            docker_cleanup = False

            if task['provider'] == "Sprout" and task['vm_name'] == "Sprout":
                vm_cleanup = True
            else:
                if task['provider'] and task['vm_name']:
                    logger.info('Cleaning up {} on {}'.format(
                        task['vm_name'], task['provider']))
                    if task['vm_name'] == "None":
                        vm_cleanup = True
                    else:
                        appliance = Appliance(task['provider'],
                                              task['vm_name'])
                        try:
                            if appliance.does_vm_exist():
                                logger.info("Destroying {}".format(
                                    appliance.vm_name))
                                appliance.destroy()
                            vm_cleanup = True
                        except Exception:
                            logger.info('Exception occured cleaning up')

            containers = dockerbot.dc.containers(all=True)
            for container in containers:
                if task['tid'] in container['Names'][0]:
                    logger.info('Cleaning up docker container {}'.format(
                        container['Id']))
                    dockerbot.dc.remove_container(container['Id'], force=True)
                    docker_cleanup = True
                    break
            else:
                docker_cleanup = True

            if docker_cleanup and vm_cleanup:
                tapi.task(task['tid']).put({'cleanup': True})
Exemple #2
0
def vm_reaper():
    """ Iterates through each task in the db which has not yet been cleaned and runs the reaper

    This function iterates through each task. If the task is either failed or passed, ie, the
    task has completed, then the VM is cleaned up and then the docker container. If both of
    these operations occur, then the cleanup is set to True.
    """
    tasks = tapi.task().get(cleanup=False)['objects']
    for task in tasks:
        if task['result'] in ["failed", "passed", "invalid"]:
            vm_cleanup = False
            docker_cleanup = False

            if task['provider'] == "Sprout" and task['vm_name'] == "Sprout":
                vm_cleanup = True
            else:
                if task['provider'] and task['vm_name']:
                    logger.info('Cleaning up {} on {}'.format(task['vm_name'], task['provider']))
                    if task['vm_name'] == "None":
                        vm_cleanup = True
                    else:
                        appliance = Appliance(task['provider'], task['vm_name'])
                        try:
                            if appliance.does_vm_exist():
                                logger.info("Destroying {}".format(appliance.vm_name))
                                appliance.destroy()
                            vm_cleanup = True
                        except Exception:
                            logger.info('Exception occured cleaning up')

            containers = dockerbot.dc.containers(all=True)
            for container in containers:
                if task['tid'] in container['Names'][0]:
                    logger.info('Cleaning up docker container {}'.format(container['Id']))
                    dockerbot.dc.remove_container(container['Id'], force=True)
                    docker_cleanup = True
                    break
            else:
                docker_cleanup = True

            if docker_cleanup and vm_cleanup:
                tapi.task(task['tid']).put({'cleanup': True})
def compliance_vm(request, provider_key, provider_crud):
    try:
        ip_addr = re.findall(r'[0-9]+(?:\.[0-9]+){3}', store.base_url)[0]
        appl_name = provider_crud.get_mgmt_system().get_vm_name_from_ip(ip_addr)
        appliance = Appliance(provider_key, appl_name)
        logger.info(
            "The tested appliance ({}) is already on this provider ({}) so reusing it.".format(
                appl_name, provider_key))
        appliance.configure_fleecing()
        vm = Vm(appl_name, provider_crud)
    except VmNotFoundViaIP:
        logger.info("Provisioning a new appliance on provider {}.".format(provider_key))
        appliance = provision_appliance(
            vm_name_prefix=PREFIX + "host_",
            version=str(version.current_version()),
            provider_name=provider_key)
        request.addfinalizer(lambda: diaper(appliance.destroy))
        appliance.configure(setup_fleece=True)
        vm = Vm(appliance.vm_name, provider_crud)
    # Do the final touches
    with appliance.ipapp(browser_steal=True) as appl:
        appl.set_session_timeout(86400)
        provider_crud.refresh_provider_relationships()
        vm.wait_to_appear()
        vm.load_details()
        wait_for_ssa_enabled()
        yield vm
def call_appliance(provider_name, vm_name, action, *args):
    # Given a provider class, find the named method and call it with
    # *args. This could possibly be generalized for other CLI tools.
    appliance = Appliance(provider_name, vm_name)

    try:
        call = getattr(appliance, action)
    except AttributeError:
        raise Exception('Action "%s" not found' % action)
    if isinstance(getattr(type(appliance), action), property):
        return call
    else:
        return call(*args)
def get_appliance(provider):
    '''Fixture to provision appliance to the provider being tested if necessary'''
    global appliance_list, main_provider
    appliance_vm_prefix = "long-test_ssa-appl_"

    if provider.key not in appliance_list:
        try:
            # see if the current appliance is on the needed provider
            ip_addr = urlparse(store.base_url).hostname
            appl_name = provider.mgmt.get_vm_name_from_ip(ip_addr)
            logger.info(
                "re-using already provisioned appliance on {}...".format(
                    provider.key))
            main_provider = provider.key
            appliance = Appliance(provider.key, appl_name)
            appliance.configure_fleecing()
            appliance_list[provider.key] = appliance
        except Exception as e:
            logger.exception(e)
            # provision appliance and configure
            ver_to_prov = str(version.current_version())
            logger.info("provisioning {} appliance on {}...".format(
                ver_to_prov, provider.key))
            appliance = None
            try:
                appliance = provision_appliance(
                    vm_name_prefix=appliance_vm_prefix,
                    version=ver_to_prov,
                    provider_name=provider.key)
                logger.info("appliance IP address: " + str(appliance.address))
                appliance.configure(setup_fleece=True)
            except Exception as e:
                logger.exception(e)
                if appliance is not None:
                    appliance.destroy()
                raise CFMEException(
                    'Appliance encountered error during initial setup: {}'.
                    format(str(e)))
            appliance_list[provider.key] = appliance
    return appliance_list[provider.key]
Exemple #6
0
def compliance_vm(request, provider):
    try:
        ip_addr = urlparse(store.base_url).hostname
        appl_name = provider.mgmt.get_vm_name_from_ip(ip_addr)
        appliance = Appliance(provider.key, appl_name)
        logger.info(
            "The tested appliance ({}) is already on this provider ({}) so reusing it."
            .format(appl_name, provider.key))
        try:
            appliance.configure_fleecing()
        except (EOFError, ApplianceException) as e:
            # If something was happening, restart and wait for the UI to reappear to prevent errors
            appliance.ipapp.reboot()
            pytest.skip(
                "Error during appliance configuration. Skipping:\n{}: {}".
                format(type(e).__name__, str(e)))
        vm = Vm(appl_name, provider)
    except VmNotFoundViaIP:
        logger.info("Provisioning a new appliance on provider {}.".format(
            provider.key))
        appliance = provision_appliance(vm_name_prefix=PREFIX + "host_",
                                        version=str(version.current_version()),
                                        provider_name=provider.key)
        request.addfinalizer(lambda: diaper(appliance.destroy))
        try:
            appliance.configure(setup_fleece=True)
        except (EOFError,
                ApplianceException) as e:  # Add known exceptions as needed.
            pytest.skip(
                "Error during appliance configuration. Skipping:\n{}: {}".
                format(type(e).__name__, str(e)))
        vm = Vm(appliance.vm_name, provider)
    if provider.type in {"rhevm"}:
        request.addfinalizer(appliance.remove_rhev_direct_lun_disk)
    # Do the final touches
    with appliance.ipapp(browser_steal=True) as appl:
        appl.set_session_timeout(86400)
        provider.refresh_provider_relationships()
        vm.wait_to_appear()
        vm.load_details()
        wait_for_ssa_enabled()
        yield vm
Exemple #7
0
def compliance_vm(request, provider):
    try:
        ip_addr = urlparse(store.base_url).hostname
        appl_name = provider.mgmt.get_vm_name_from_ip(ip_addr)
        appliance = Appliance(provider.key, appl_name)
        logger.info(
            "The tested appliance (%s) is already on this provider (%s) so reusing it.",
            appl_name, provider.key)
        try:
            appliance.configure_fleecing()
        except (EOFError, ApplianceException) as e:
            # If something was happening, restart and wait for the UI to reappear to prevent errors
            appliance.ipapp.reboot()
            pytest.skip(
                "Error during appliance configuration. Skipping:\n{}: {}".format(
                    type(e).__name__, str(e)))
        vm = VM.factory(appl_name, provider)
    except exceptions.VMNotFoundViaIP:
        logger.info("Provisioning a new appliance on provider %s.", provider.key)
        appliance = provision_appliance(
            vm_name_prefix=PREFIX + "host_",
            version=str(version.current_version()),
            provider_name=provider.key)
        request.addfinalizer(lambda: diaper(appliance.destroy))
        try:
            appliance.configure(setup_fleece=True)
        except (EOFError, ApplianceException) as e:   # Add known exceptions as needed.
            pytest.skip(
                "Error during appliance configuration. Skipping:\n{}: {}".format(
                    type(e).__name__, str(e)))
        vm = VM.factory(appliance.vm_name, provider)
    if provider.type in {"rhevm"}:
        request.addfinalizer(appliance.remove_rhev_direct_lun_disk)
    # Do the final touches
    with appliance.ipapp(browser_steal=True) as appl:
        appl.set_session_timeout(86400)
        provider.refresh_provider_relationships()
        vm.wait_to_appear()
        vm.load_details()
        wait_for_ssa_enabled()
        yield vm
def get_appliance(provider_crud):
    '''Fixture to provision appliance to the provider being tested if necessary'''
    global appliance_list, main_provider
    appliance_vm_prefix = "test_vm_analysis"

    if provider_crud.key not in appliance_list:
        try:
            # see if the current appliance is on the needed provider
            ip_addr = re.findall(r'[0-9]+(?:\.[0-9]+){3}', conf.env['base_url'])[0]
            appl_name = provider_crud.get_mgmt_system().get_vm_name_from_ip(ip_addr)
            logger.info("re-using already provisioned appliance on {}...".format(provider_crud.key))
            main_provider = provider_crud.key
            appliance = Appliance(provider_crud.key, appl_name)
            appliance.configure_fleecing()
            appliance_list[provider_crud.key] = appliance
        except Exception as e:
            logger.error("Exception: %s" % str(e))
            # provision appliance and configure
            ver_to_prov = str(version.current_version())
            logger.info("provisioning {} appliance on {}...".format(ver_to_prov, provider_crud.key))
            appliance = None
            try:
                appliance = provision_appliance(
                    vm_name_prefix=appliance_vm_prefix,
                    version=ver_to_prov,
                    provider_name=provider_crud.key)
                logger.info("appliance IP address: " + str(appliance.address))
                appliance.configure(setup_fleece=True)
            except Exception as e:
                logger.error("Exception: %s" % str(e))
                if appliance is not None:
                    appliance.destroy()
                raise CFMEException(
                    'Appliance encountered error during initial setup: {}'.format(str(e)))
            appliance_list[provider_crud.key] = appliance
    return appliance_list[provider_crud.key]
def get_appliance(provider):
    '''Fixture to provision appliance to the provider being tested if necessary'''
    global appliance_list, main_provider
    appliance_vm_prefix = "long-test_ssa-appl_"

    if provider.key not in appliance_list:
        try:
            # see if the current appliance is on the needed provider
            ip_addr = urlparse(store.base_url).hostname
            appl_name = provider.mgmt.get_vm_name_from_ip(ip_addr)
            logger.info("re-using already provisioned appliance on {}...".format(provider.key))
            main_provider = provider.key
            appliance = Appliance(provider.key, appl_name)
            appliance.configure_fleecing()
            appliance_list[provider.key] = appliance
        except Exception as e:
            logger.exception(e)
            # provision appliance and configure
            ver_to_prov = str(version.current_version())
            logger.info("provisioning {} appliance on {}...".format(ver_to_prov, provider.key))
            appliance = None
            try:
                appliance = provision_appliance(
                    vm_name_prefix=appliance_vm_prefix,
                    version=ver_to_prov,
                    provider_name=provider.key)
                logger.info("appliance IP address: " + str(appliance.address))
                appliance.configure(setup_fleece=True)
            except Exception as e:
                logger.exception(e)
                if appliance is not None:
                    appliance.destroy()
                raise CFMEException(
                    'Appliance encountered error during initial setup: {}'.format(str(e)))
            appliance_list[provider.key] = appliance
    return appliance_list[provider.key]
def main():
    parser = argparse.ArgumentParser(description=__doc__,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)

    # required options (heh)
    parser.add_argument('--provider', help='provider key in cfme_data')
    parser.add_argument('--template', help='the name of the template to clone')
    parser.add_argument('--vm_name', help='the name of the VM to create')

    # generic options
    parser.add_argument('--destroy', dest='destroy', action='store_true',
                        help='Destroy the destination VM')
    parser.add_argument('--configure', default=False, action='store_true',
                        help='configure the VM after provisioning')
    parser.add_argument('--no-cleanup', default=True, action='store_false',
                        dest='cleanup', help="don't clean up the vm on clone failure")
    parser.add_argument('--log', dest='loglevel', default='WARNING',
                        help='Set the log level')
    parser.add_argument('--outfile', dest='outfile',
                        help='Write provisioning details to the named file', default='')

    # sub options organized for provider types
    rhev_parser = parser.add_argument_group('rhev')
    rhev_parser.add_argument('--cluster', default=None,
                             help='the name of the VM on which to act')
    rhev_parser.add_argument('--place_policy_host', default=None,
                             help='the host for the vm to start on')
    rhev_parser.add_argument('--place_policy_aff', default=None,
                             help='the affinity of the vm on a host')

    cloud_parser = parser.add_argument_group('cloud')
    cloud_parser.add_argument('--flavor', default=None, help='ec2/rhos flavor')

    openstack_parser = parser.add_argument_group('openstack')
    openstack_parser.add_argument('--floating-ip-pool', default=None,
                                  help='openstack floating ip pool to use')

    args = parser.parse_args()

    # get_mgmt validates, since it will explode without an existing key or type
    provider = get_mgmt(args.provider)
    provider_dict = cfme_data['management_systems'][args.provider]
    provider_type = provider_dict['type']

    # Used by the cloud provs
    flavors = cfme_data['appliance_provisioning']['default_flavors'].get(provider_type, [])

    logger.info('Connecting to {}'.format(args.provider))

    if args.destroy:
        # TODO: destroy should be its own script
        # but it's easy enough to just hijack the parser here
        # This returns True if destroy fails to give POSIXy exit codes (0 is good, False is 0, etc)
        return not destroy_vm(provider, args.vm_name)

    deploy_args = {
        'vm_name': args.vm_name,
        'template': args.template,
    }

    # Try to snag defaults from cfme_data here for each provider type
    if provider_type == 'rhevm':
        cluster = provider_dict.get('default_cluster', args.cluster)
        if cluster is None:
            raise Exception('--cluster is required for rhev instances and default is not set')
        deploy_args['cluster'] = cluster

        if args.place_policy_host and args.place_policy_aff:
            deploy_args['placement_policy_host'] = args.place_policy_host
            deploy_args['placement_policy_affinity'] = args.rhev_place_policy_aff
    elif provider_type == 'ec2':
        # ec2 doesn't have an api to list available flavors, so the first flavor is the default
        try:
            flavor = args.flavor or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for EC2 instances and default is not set')
        deploy_args['instance_type'] = flavor
    elif provider_type == 'openstack':
        # filter openstack flavors based on what's available
        available_flavors = provider.list_flavor()
        flavors = filter(lambda f: f in available_flavors, flavors)
        try:
            flavor = args.flavor or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for RHOS instances and '
                            'default is not set or unavailable on provider')
        # flavour? Thanks, psav...
        deploy_args['flavour_name'] = flavor

        if 'network' in provider_dict:
            # support rhos4 network names
            deploy_args['network_name'] = provider_dict['network']

        provider_pools = [p.name for p in provider.api.floating_ip_pools.list()]
        try:
            # TODO: If there are multiple pools, have a provider default in cfme_data
            floating_ip_pool = args.floating_ip_pool or provider_pools[0]
        except IndexError:
            raise Exception('No floating IP pools available on provider')

        if floating_ip_pool is not None:
            deploy_args['floating_ip_pool'] = floating_ip_pool
    elif provider_type == "virtualcenter":
        if "allowed_datastores" in provider_dict:
            deploy_args["allowed_datastores"] = provider_dict["allowed_datastores"]
    elif provider_type == 'scvmm':
        deploy_args["host_group"] = provider_dict["provisioning"]['host_group']

    # Do it!
    try:
        logger.info('Cloning {} to {} on {}'.format(args.template, args.vm_name, args.provider))
        provider.deploy_template(**deploy_args)
    except Exception as e:
        logger.exception(e)
        logger.error('Clone failed')
        if args.cleanup:
            logger.info('attempting to destroy {}'.format(args.vm_name))
            destroy_vm(provider, args.vm_name)
            return 12

    if provider.is_vm_running(args.vm_name):
        logger.info("VM {} is running".format(args.vm_name))
    else:
        logger.error("VM is not running")
        return 10

    ip, time_taken = wait_for(provider.get_ip_address, [args.vm_name], num_sec=1200,
                              fail_condition=None)
    logger.info('IP Address returned is {}'.format(ip))

    if args.configure:
        logger.info('Configuring appliance, this can take a while.')
        app = Appliance(args.provider, args.vm_name)
        app.configure()

    if args.outfile:
        with open(args.outfile, 'w') as outfile:
            outfile.write("appliance_ip_address={}\n".format(ip))

    # In addition to the outfile, drop the ip address on stdout for easy parsing
    print(ip)
Exemple #11
0
def main():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)

    # required options (heh)
    parser.add_argument('--provider', help='provider key in cfme_data')
    parser.add_argument('--template', help='the name of the template to clone')
    parser.add_argument('--vm_name', help='the name of the VM to create')

    # generic options
    parser.add_argument('--destroy',
                        dest='destroy',
                        action='store_true',
                        help='Destroy the destination VM')
    parser.add_argument('--configure',
                        default=False,
                        action='store_true',
                        help='configure the VM after provisioning')
    parser.add_argument('--no-cleanup',
                        default=True,
                        action='store_false',
                        dest='cleanup',
                        help="don't clean up the vm on clone failure")
    parser.add_argument('--log',
                        dest='loglevel',
                        default='WARNING',
                        help='Set the log level')
    parser.add_argument('--outfile',
                        dest='outfile',
                        help='Write provisioning details to the named file',
                        default='')

    # sub options organized for provider types
    rhev_parser = parser.add_argument_group('rhev')
    rhev_parser.add_argument('--cluster',
                             default=None,
                             help='the name of the VM on which to act')
    rhev_parser.add_argument('--place_policy_host',
                             default=None,
                             help='the host for the vm to start on')
    rhev_parser.add_argument('--place_policy_aff',
                             default=None,
                             help='the affinity of the vm on a host')

    cloud_parser = parser.add_argument_group('cloud')
    cloud_parser.add_argument('--flavor', default=None, help='ec2/rhos flavor')

    openstack_parser = parser.add_argument_group('openstack')
    openstack_parser.add_argument('--floating-ip-pool',
                                  default=None,
                                  help='openstack floating ip pool to use')

    args = parser.parse_args()

    # get_mgmt validates, since it will explode without an existing key or type
    provider = get_mgmt(args.provider)
    provider_dict = cfme_data['management_systems'][args.provider]
    provider_type = provider_dict['type']

    # Used by the cloud provs
    flavors = cfme_data['appliance_provisioning']['default_flavors'].get(
        provider_type, [])

    logger.info('Connecting to {}'.format(args.provider))

    if args.destroy:
        # TODO: destroy should be its own script
        # but it's easy enough to just hijack the parser here
        # This returns True if destroy fails to give POSIXy exit codes (0 is good, False is 0, etc)
        return not destroy_vm(provider, args.vm_name)

    deploy_args = {
        'vm_name': args.vm_name,
        'template': args.template,
    }

    # Try to snag defaults from cfme_data here for each provider type
    if provider_type == 'rhevm':
        cluster = provider_dict.get('default_cluster', args.cluster)
        if cluster is None:
            raise Exception(
                '--cluster is required for rhev instances and default is not set'
            )
        deploy_args['cluster'] = cluster

        if args.place_policy_host and args.place_policy_aff:
            deploy_args['placement_policy_host'] = args.place_policy_host
            deploy_args[
                'placement_policy_affinity'] = args.rhev_place_policy_aff
    elif provider_type == 'ec2':
        # ec2 doesn't have an api to list available flavors, so the first flavor is the default
        try:
            flavor = args.flavor or flavors[0]
        except IndexError:
            raise Exception(
                '--flavor is required for EC2 instances and default is not set'
            )
        deploy_args['instance_type'] = flavor
    elif provider_type == 'openstack':
        # filter openstack flavors based on what's available
        available_flavors = provider.list_flavor()
        flavors = filter(lambda f: f in available_flavors, flavors)
        try:
            flavor = args.flavor or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for RHOS instances and '
                            'default is not set or unavailable on provider')
        # flavour? Thanks, psav...
        deploy_args['flavour_name'] = flavor

        if 'network' in provider_dict:
            # support rhos4 network names
            deploy_args['network_name'] = provider_dict['network']

        provider_pools = [
            p.name for p in provider.api.floating_ip_pools.list()
        ]
        try:
            # TODO: If there are multiple pools, have a provider default in cfme_data
            floating_ip_pool = args.floating_ip_pool or provider_pools[0]
        except IndexError:
            raise Exception('No floating IP pools available on provider')

        if floating_ip_pool is not None:
            deploy_args['floating_ip_pool'] = floating_ip_pool
    elif provider_type == "virtualcenter":
        if "allowed_datastores" in provider_dict:
            deploy_args["allowed_datastores"] = provider_dict[
                "allowed_datastores"]
    elif provider_type == 'scvmm':
        deploy_args["host_group"] = provider_dict["provisioning"]['host_group']

    # Do it!
    try:
        logger.info('Cloning {} to {} on {}'.format(args.template,
                                                    args.vm_name,
                                                    args.provider))
        provider.deploy_template(**deploy_args)
    except Exception as e:
        logger.exception(e)
        logger.error('Clone failed')
        if args.cleanup:
            logger.info('attempting to destroy {}'.format(args.vm_name))
            destroy_vm(provider, args.vm_name)
            return 12

    if provider.is_vm_running(args.vm_name):
        logger.info("VM {} is running".format(args.vm_name))
    else:
        logger.error("VM is not running")
        return 10

    ip, time_taken = wait_for(provider.get_ip_address, [args.vm_name],
                              num_sec=1200,
                              fail_condition=None)
    logger.info('IP Address returned is {}'.format(ip))

    if args.configure:
        logger.info('Configuring appliance, this can take a while.')
        app = Appliance(args.provider, args.vm_name)
        app.configure()

    if args.outfile:
        with open(args.outfile, 'w') as outfile:
            outfile.write("appliance_ip_address={}\n".format(ip))

    # In addition to the outfile, drop the ip address on stdout for easy parsing
    print(ip)
def main(**kwargs):
    # get_mgmt validates, since it will explode without an existing key or type
    if kwargs.get('deploy', None):
        kwargs['configure'] = True
        kwargs['outfile'] = 'appliance_ip_address_1'
        provider_data = utils.conf.provider_data
        providers = provider_data['management_systems']
        provider_dict = provider_data['management_systems'][kwargs['provider']]
        credentials =\
            {'username': provider_dict['username'],
             'password': provider_dict['password'],
             'tenant': provider_dict['template_upload'].get('tenant_admin', 'admin'),
             'auth_url': provider_dict.get('auth_url', None),
             }
        provider = get_mgmt(kwargs['provider'], providers=providers, credentials=credentials)
        flavors = provider_dict['template_upload'].get('flavors', ['m1.medium'])
        provider_type = provider_data['management_systems'][kwargs['provider']]['type']
        deploy_args = {
            'vm_name': kwargs['vm_name'],
            'template': kwargs['template'],
        }
    else:
        provider = get_mgmt(kwargs['provider'])
        provider_dict = cfme_data['management_systems'][kwargs['provider']]
        provider_type = provider_dict['type']
        flavors = cfme_data['appliance_provisioning']['default_flavors'].get(provider_type, [])
        deploy_args = {
            'vm_name': kwargs['vm_name'],
            'template': kwargs['template'],
        }

    logger.info('Connecting to {}'.format(kwargs['provider']))

    if kwargs.get('destroy', None):
        # TODO: destroy should be its own script
        # but it's easy enough to just hijack the parser here
        # This returns True if destroy fails to give POSIXy exit codes (0 is good, False is 0, etc)
        return not destroy_vm(provider, deploy_args['vm_name'])

    # Try to snag defaults from cfme_data here for each provider type
    if provider_type == 'rhevm':
        cluster = provider_dict.get('default_cluster', kwargs.get('cluster', None))
        if cluster is None:
            raise Exception('--cluster is required for rhev instances and default is not set')
        deploy_args['cluster'] = cluster

        if kwargs.get('place_policy_host', None) and kwargs.get('place_policy_aff', None):
            deploy_args['placement_policy_host'] = kwargs['place_policy_host']
            deploy_args['placement_policy_affinity'] = kwargs['place_policy_aff']
    elif provider_type == 'ec2':
        # ec2 doesn't have an api to list available flavors, so the first flavor is the default
        try:
            flavor = kwargs.get('flavor', None) or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for EC2 instances and default is not set')
        deploy_args['instance_type'] = flavor
    elif provider_type == 'openstack':
        # filter openstack flavors based on what's available
        available_flavors = provider.list_flavor()
        flavors = filter(lambda f: f in available_flavors, flavors)
        try:
            flavor = kwargs.get('flavor', None) or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for RHOS instances and '
                            'default is not set or unavailable on provider')
        # flavour? Thanks, psav...
        deploy_args['flavour_name'] = flavor

        if 'network' in provider_dict:
            # support rhos4 network names
            deploy_args['network_name'] = provider_dict['network']

        provider_pools = [p.name for p in provider.api.floating_ip_pools.list()]
        try:
            # TODO: If there are multiple pools, have a provider default in cfme_data
            floating_ip_pool = kwargs.get('floating_ip_pool', None) or provider_pools[0]
        except IndexError:
            raise Exception('No floating IP pools available on provider')

        if floating_ip_pool is not None:
            deploy_args['floating_ip_pool'] = floating_ip_pool
    elif provider_type == "virtualcenter":
        if "allowed_datastores" in provider_dict:
            deploy_args["allowed_datastores"] = provider_dict["allowed_datastores"]
    elif provider_type == 'scvmm':
        deploy_args["host_group"] = provider_dict["provisioning"]['host_group']
    elif provider_type == 'gce':
        deploy_args['ssh_key'] = '{user_name}:{public_key}'.format(
            user_name=cred['ssh']['ssh-user'],
            public_key=cred['ssh']['public_key'])
    # Do it!
    try:
        logger.info('Cloning {} to {} on {}'.format(deploy_args['template'], deploy_args['vm_name'],
                                                    kwargs['provider']))
        provider.deploy_template(**deploy_args)
    except Exception as e:
        logger.exception(e)
        logger.error('Clone failed')
        if kwargs.get('cleanup', None):
            logger.info('attempting to destroy {}'.format(deploy_args['vm_name']))
            destroy_vm(provider, deploy_args['vm_name'])
            return 12

    if provider.is_vm_running(deploy_args['vm_name']):
        logger.info("VM {} is running".format(deploy_args['vm_name']))
    else:
        logger.error("VM is not running")
        return 10

    try:
        ip, time_taken = wait_for(provider.get_ip_address, [deploy_args['vm_name']], num_sec=1200,
                                  fail_condition=None)
        logger.info('IP Address returned is {}'.format(ip))
    except Exception as e:
        logger.exception(e)
        logger.error('IP address not returned')
        return 10

    try:
        if kwargs.get('configure', None):
            logger.info('Configuring appliance, this can take a while.')
            if kwargs.get('deploy', None):
                app = IPAppliance(address=ip)
            else:
                app = Appliance(kwargs['provider'], deploy_args['vm_name'])
            if provider_type == 'gce':
                with app as ipapp:
                    ipapp.configure_gce()
            else:
                app.configure()
            logger.info('Successfully Configured the appliance.')
    except Exception as e:
        logger.exception(e)
        logger.error('Appliance Configuration Failed')
        if not kwargs.get('deploy', None):
            app = Appliance(kwargs['provider'], deploy_args['vm_name'])
            ssh_client = app.ssh_client()
            status, output = ssh_client.run_command('find /root/anaconda-post.log')
            if status == 0:
                ssh_client.get_file('/root/anaconda-post.log',
                                    log_path.join('anaconda-post.log').strpath)
            ssh_client.close()
        return 10

    if kwargs.get('outfile', None) or kwargs.get('deploy', None):
        with open(kwargs['outfile'], 'w') as outfile:
            outfile.write("appliance_ip_address={}\n".format(ip))

    # In addition to the outfile, drop the ip address on stdout for easy parsing
    print(ip)
def main(**kwargs):
    # get_mgmt validates, since it will explode without an existing key or type
    if kwargs.get('deploy', None):
        kwargs['configure'] = True
        provider_data = utils.conf.provider_data
        providers = provider_data['management_systems']
        provider_dict = provider_data['management_systems'][kwargs['provider']]
        credentials =\
            {'username': provider_dict['username'],
             'password': provider_dict['password'],
             'tenant': provider_dict['template_upload'].get('tenant_admin', None),
             'auth_url': provider_dict.get('auth_url', None),
             }
        provider = get_mgmt(kwargs['provider'], providers=providers, credentials=credentials)
        flavors = provider_dict['template_upload'].get('flavors', [])
        provider_type = provider_data['management_systems'][kwargs['provider']]['type']
        deploy_args = {
            'vm_name': kwargs['vm_name'],
            'template': kwargs['template'],
        }
    else:
        provider = get_mgmt(kwargs['provider'])
        provider_dict = cfme_data['management_systems'][kwargs['provider']]
        provider_type = provider_dict['type']
        flavors = cfme_data['appliance_provisioning']['default_flavors'].get(provider_type, [])
        deploy_args = {
            'vm_name': kwargs['vm_name'],
            'template': kwargs['template'],
        }

    logger.info('Connecting to {}'.format(kwargs['provider']))

    if kwargs.get('destroy', None):
        # TODO: destroy should be its own script
        # but it's easy enough to just hijack the parser here
        # This returns True if destroy fails to give POSIXy exit codes (0 is good, False is 0, etc)
        return not destroy_vm(provider, deploy_args['vm_name'])

    # Try to snag defaults from cfme_data here for each provider type
    if provider_type == 'rhevm':
        cluster = provider_dict.get('default_cluster', kwargs.get('cluster', None))
        if cluster is None:
            raise Exception('--cluster is required for rhev instances and default is not set')
        deploy_args['cluster'] = cluster

        if kwargs.get('place_policy_host', None) and kwargs.get('place_policy_aff', None):
            deploy_args['placement_policy_host'] = kwargs['place_policy_host']
            deploy_args['placement_policy_affinity'] = kwargs['place_policy_aff']
    elif provider_type == 'ec2':
        # ec2 doesn't have an api to list available flavors, so the first flavor is the default
        try:
            flavor = kwargs.get('flavor', None) or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for EC2 instances and default is not set')
        deploy_args['instance_type'] = flavor
    elif provider_type == 'openstack':
        # filter openstack flavors based on what's available
        available_flavors = provider.list_flavor()
        flavors = filter(lambda f: f in available_flavors, flavors)
        try:
            flavor = kwargs.get('flavor', None) or flavors[0]
        except IndexError:
            raise Exception('--flavor is required for RHOS instances and '
                            'default is not set or unavailable on provider')
        # flavour? Thanks, psav...
        deploy_args['flavour_name'] = flavor

        if 'network' in provider_dict:
            # support rhos4 network names
            deploy_args['network_name'] = provider_dict['network']

        provider_pools = [p.name for p in provider.api.floating_ip_pools.list()]
        try:
            # TODO: If there are multiple pools, have a provider default in cfme_data
            floating_ip_pool = kwargs.get('floating_ip_pool', None) or provider_pools[0]
        except IndexError:
            raise Exception('No floating IP pools available on provider')

        if floating_ip_pool is not None:
            deploy_args['floating_ip_pool'] = floating_ip_pool
    elif provider_type == "virtualcenter":
        if "allowed_datastores" in provider_dict:
            deploy_args["allowed_datastores"] = provider_dict["allowed_datastores"]
    elif provider_type == 'scvmm':
        deploy_args["host_group"] = provider_dict["provisioning"]['host_group']

    # Do it!
    try:
        logger.info('Cloning {} to {} on {}'.format(deploy_args['template'], deploy_args['vm_name'],
                                                    kwargs['provider']))
        provider.deploy_template(**deploy_args)
    except Exception as e:
        logger.exception(e)
        logger.error('Clone failed')
        if kwargs.get('cleanup', None):
            logger.info('attempting to destroy {}'.format(deploy_args['vm_name']))
            destroy_vm(provider, deploy_args['vm_name'])
            return 12

    if provider.is_vm_running(deploy_args['vm_name']):
        logger.info("VM {} is running".format(deploy_args['vm_name']))
    else:
        logger.error("VM is not running")
        return 10

    ip, time_taken = wait_for(provider.get_ip_address, [deploy_args['vm_name']], num_sec=1200,
                              fail_condition=None)
    logger.info('IP Address returned is {}'.format(ip))

    if kwargs.get('configure', None):
        logger.info('Configuring appliance, this can take a while.')
        app = Appliance(kwargs['provider'], deploy_args['vm_name'])
        app.configure()

    if kwargs.get('outfile', None):
        with open(kwargs['outfile'], 'w') as outfile:
            outfile.write("appliance_ip_address={}\n".format(ip))

    # In addition to the outfile, drop the ip address on stdout for easy parsing
    print(ip)