Example #1
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)
Example #2
0
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":
                app.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)
Example #3
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
        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']

    # 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'])
            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):
        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)
Example #5
0
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

    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.')
            app = Appliance(kwargs['provider'], deploy_args['vm_name'])
            app.configure()
            logger.info('Successfully Configured the appliance.')
    except Exception as e:
        logger.exception(e)
        logger.error('Appliance Configuration Failed')
        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):
        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)