Spin up an instance using Salt Cloud

    CLI Example:

    .. code-block:: bash

        salt minionname cloud.profile my-gce-config myinstance
504349
def profile_(profile, names, vm_overrides=None, opts=None, **kwargs):
    '''
    
    '''
    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    info = client.profile(profile, names, vm_overrides=vm_overrides, **kwargs)
    return info
1265825
def create(vm_):
    '''
    
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'softlayer',
                                                           vm_['profile'],
                                                           vm_=vm_) is False:
            return False
    except AttributeError:
        pass

    name = vm_['name']
    hostname = name
    domain = config.get_cloud_config_value(
        'domain', vm_, __opts__, default=None
    )
    if domain is None:
        SaltCloudSystemExit(
            'A domain name is required for the SoftLayer driver.'
        )

    if vm_.get('use_fqdn'):
        name = '.'.join([name, domain])
        vm_['name'] = name

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(name),
        args=__utils__['cloud.filter_event']('creating', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    log.info('Creating Cloud VM %s', name)
    conn = get_conn()
    kwargs = {
        'hostname': hostname,
        'domain': domain,
        'startCpus': vm_['cpu_number'],
        'maxMemory': vm_['ram'],
        'hourlyBillingFlag': vm_['hourly_billing'],
    }

    local_disk_flag = config.get_cloud_config_value(
        'local_disk', vm_, __opts__, default=False
    )
    kwargs['localDiskFlag'] = local_disk_flag

    if 'image' in vm_:
        kwargs['operatingSystemReferenceCode'] = vm_['image']
        kwargs['blockDevices'] = []
        disks = vm_['disk_size']

        if isinstance(disks, int):
            disks = [six.text_type(disks)]
        elif isinstance(disks, six.string_types):
            disks = [size.strip() for size in disks.split(',')]

        count = 0
        for disk in disks:
            # device number '1' is reserved for the SWAP disk
            if count == 1:
                count += 1
            block_device = {'device': six.text_type(count),
                            'diskImage': {'capacity': six.text_type(disk)}}
            kwargs['blockDevices'].append(block_device)
            count += 1

            # Upper bound must be 5 as we're skipping '1' for the SWAP disk ID
            if count > 5:
                log.warning('More that 5 disks were specified for %s .'
                            'The first 5 disks will be applied to the VM, '
                            'but the remaining disks will be ignored.\n'
                            'Please adjust your cloud configuration to only '
                            'specify a maximum of 5 disks.', name)
                break

    elif 'global_identifier' in vm_:
        kwargs['blockDeviceTemplateGroup'] = {
            'globalIdentifier': vm_['global_identifier']
        }

    location = get_location(vm_)
    if location:
        kwargs['datacenter'] = {'name': location}

    private_vlan = config.get_cloud_config_value(
        'private_vlan', vm_, __opts__, default=False
    )
    if private_vlan:
        kwargs['primaryBackendNetworkComponent'] = {
            'networkVlan': {
                'id': private_vlan,
            }
        }

    private_network = config.get_cloud_config_value(
        'private_network', vm_, __opts__, default=False
    )
    if bool(private_network) is True:
        kwargs['privateNetworkOnlyFlag'] = 'True'

    public_vlan = config.get_cloud_config_value(
        'public_vlan', vm_, __opts__, default=False
    )
    if public_vlan:
        kwargs['primaryNetworkComponent'] = {
            'networkVlan': {
                'id': public_vlan,
            }
        }

    public_security_groups = config.get_cloud_config_value(
        'public_security_groups', vm_, __opts__, default=False
    )
    if public_security_groups:
        secgroups = [{'securityGroup': {'id': int(sg)}}
                     for sg in public_security_groups]
        pnc = kwargs.get('primaryNetworkComponent', {})
        pnc['securityGroupBindings'] = secgroups
        kwargs.update({'primaryNetworkComponent': pnc})

    private_security_groups = config.get_cloud_config_value(
        'private_security_groups', vm_, __opts__, default=False
    )

    if private_security_groups:
        secgroups = [{'securityGroup': {'id': int(sg)}}
                     for sg in private_security_groups]
        pbnc = kwargs.get('primaryBackendNetworkComponent', {})
        pbnc['securityGroupBindings'] = secgroups
        kwargs.update({'primaryBackendNetworkComponent': pbnc})

    max_net_speed = config.get_cloud_config_value(
        'max_net_speed', vm_, __opts__, default=10
    )
    if max_net_speed:
        kwargs['networkComponents'] = [{
            'maxSpeed': int(max_net_speed)
        }]

    post_uri = config.get_cloud_config_value(
        'post_uri', vm_, __opts__, default=None
    )
    if post_uri:
        kwargs['postInstallScriptUri'] = post_uri

    dedicated_host_id = config.get_cloud_config_value(
        'dedicated_host_id', vm_, __opts__, default=None
    )
    if dedicated_host_id:
        kwargs['dedicatedHost'] = {'id': dedicated_host_id}

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(name),
        args={
            'kwargs': __utils__['cloud.filter_event']('requesting', kwargs, list(kwargs)),
        },
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    try:
        response = conn.createObject(kwargs)
    except Exception as exc:
        log.error(
            'Error creating %s on SoftLayer\n\n'
            'The following exception was thrown when trying to '
            'run the initial deployment: \n%s', name, exc,
            # Show the traceback if the debug logging level is enabled
            exc_info_on_loglevel=logging.DEBUG
        )
        return False

    ip_type = 'primaryIpAddress'
    private_ssh = config.get_cloud_config_value(
        'private_ssh', vm_, __opts__, default=False
    )
    private_wds = config.get_cloud_config_value(
        'private_windows', vm_, __opts__, default=False
    )
    if private_ssh or private_wds or public_vlan is None:
        ip_type = 'primaryBackendIpAddress'

    def wait_for_ip():
        '''
        Wait for the IP address to become available
        '''
        nodes = list_nodes_full()
        if ip_type in nodes[hostname]:
            return nodes[hostname][ip_type]
        time.sleep(1)
        return False

    ip_address = salt.utils.cloud.wait_for_fun(
        wait_for_ip,
        timeout=config.get_cloud_config_value(
            'wait_for_fun_timeout', vm_, __opts__, default=15 * 60),
    )
    if config.get_cloud_config_value('deploy', vm_, __opts__) is not True:
        return show_instance(hostname, call='action')

    SSH_PORT = 22
    WINDOWS_DS_PORT = 445
    managing_port = SSH_PORT
    if config.get_cloud_config_value('windows', vm_, __opts__) or \
            config.get_cloud_config_value('win_installer', vm_, __opts__):
        managing_port = WINDOWS_DS_PORT

    ssh_connect_timeout = config.get_cloud_config_value(
        'ssh_connect_timeout', vm_, __opts__, 15 * 60
    )
    connect_timeout = config.get_cloud_config_value(
        'connect_timeout', vm_, __opts__, ssh_connect_timeout
    )
    if not salt.utils.cloud.wait_for_port(ip_address,
                                          port=managing_port,
                                          timeout=connect_timeout):
        raise SaltCloudSystemExit(
            'Failed to authenticate against remote ssh'
        )

    pass_conn = get_conn(service='SoftLayer_Account')
    mask = {
        'virtualGuests': {
            'powerState': '',
            'operatingSystem': {
                'passwords': ''
            },
        },
    }

    def get_credentials():
        '''
        Wait for the password to become available
        '''
        node_info = pass_conn.getVirtualGuests(id=response['id'], mask=mask)
        for node in node_info:
            if node['id'] == response['id'] and \
                            'passwords' in node['operatingSystem'] and \
                            node['operatingSystem']['passwords']:
                return node['operatingSystem']['passwords'][0]['username'], node['operatingSystem']['passwords'][0]['password']
        time.sleep(5)
        return False

    username, passwd = salt.utils.cloud.wait_for_fun(  # pylint: disable=W0633
        get_credentials,
        timeout=config.get_cloud_config_value(
            'wait_for_fun_timeout', vm_, __opts__, default=15 * 60),
    )
    response['username'] = username
    response['password'] = passwd
    response['public_ip'] = ip_address

    ssh_username = config.get_cloud_config_value(
        'ssh_username', vm_, __opts__, default=username
    )

    vm_['ssh_host'] = ip_address
    vm_['password'] = passwd
    ret = __utils__['cloud.bootstrap'](vm_, __opts__)

    ret.update(response)

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(name),
        args=__utils__['cloud.filter_event']('created', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return ret
424397
def start(vm_name, call=None):
    '''
    
    '''
    if call != 'action':
        raise SaltCloudSystemExit(
            'The start action must be called with -a or --action.'
        )

    conn = get_conn()

    __utils__['cloud.fire_event'](
        'event',
        'start instance',
        'salt/cloud/{0}/starting'.format(vm_name),
        args={'name': vm_name},
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    result = conn.ex_start_node(
        conn.ex_get_node(vm_name)
    )

    __utils__['cloud.fire_event'](
        'event',
        'start instance',
        'salt/cloud/{0}/started'.format(vm_name),
        args={'name': vm_name},
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return result
640791
def show_instance(name, call=None):
    '''
    
    '''
    local = salt.client.LocalClient()
    ret = local.cmd(name, 'grains.items')
    ret.update(_build_required_items(ret))
    return ret
979988
def show_instance(name, call=None):
    '''
    
    '''
    if call != 'action':
        raise SaltCloudSystemExit(
            'The show_instance action must be called with -a or --action.'
        )

    items = query(action='ve', command=name)

    ret = {}
    for item in items:
        if 'text' in item.__dict__:
            ret[item.tag] = item.text
        else:
            ret[item.tag] = item.attrib

        if item._children:
            ret[item.tag] = {}
            children = item._children
            for child in children:
                ret[item.tag][child.tag] = child.attrib

    __utils__['cloud.cache_node'](ret, __active_provider_name__, __opts__)
    return ret
1317117
def reboot(name, call=None):
    '''
    
    '''
    if call != 'action':
        raise SaltCloudSystemExit(
            'The stop action must be called with -a or --action.'
        )

    log.info('Rebooting node %s', name)

    instance_id = _get_node(name)['InstanceId']

    params = {'Action': 'RebootInstance',
              'InstanceId': instance_id}
    result = query(params)

    return result
390878
def _run(name,
         cmd,
         output=None,
         no_start=False,
         preserve_state=True,
         stdin=None,
         python_shell=True,
         output_loglevel='debug',
         use_vt=False,
         path=None,
         ignore_retcode=False,
         chroot_fallback=None,
         keep_env='http_proxy,https_proxy,no_proxy'):
    '''
    

    '''
    orig_state = state(name, path=path)
    try:
        if attachable(name, path=path):
            ret = __salt__['container_resource.run'](
                name,
                cmd,
                path=path,
                container_type=__virtualname__,
                exec_driver=EXEC_DRIVER,
                output=output,
                no_start=no_start,
                stdin=stdin,
                python_shell=python_shell,
                output_loglevel=output_loglevel,
                ignore_retcode=ignore_retcode,
                use_vt=use_vt,
                keep_env=keep_env)
        else:
            if not chroot_fallback:
                raise CommandExecutionError(
                    '{0} is not attachable.'.format(name))
            rootfs = info(name, path=path).get('rootfs')
            # Set context var to make cmd.run_chroot run cmd.run instead of
            # cmd.run_all.
            __context__['cmd.run_chroot.func'] = __salt__['cmd.run']
            ret = __salt__['cmd.run_chroot'](rootfs,
                                             cmd,
                                             stdin=stdin,
                                             python_shell=python_shell,
                                             output_loglevel=output_loglevel,
                                             ignore_retcode=ignore_retcode)
    except Exception:
        raise
    finally:
        # Make sure we honor preserve_state, even if there was an exception
        new_state = state(name, path=path)
        if preserve_state:
            if orig_state == 'stopped' and new_state != 'stopped':
                stop(name, path=path)
            elif orig_state == 'frozen' and new_state != 'frozen':
                freeze(name, start=True, path=path)

    if output in (None, 'all'):
        return ret
    else:
        return ret[output]
486729
def _deploy_salt_minion(name, session, vm_):
    '''
    
    '''
    # Get bootstrap values
    vm_['ssh_host'] = get_vm_ip(name, session)
    vm_['user'] = vm_.get('user', 'root')
    vm_['password'] = vm_.get('password', 'p@ssw0rd!')
    vm_['provider'] = vm_.get('provider', 'xen')
    log.debug('%s has IP of %s', name, vm_['ssh_host'])
    # Bootstrap Salt minion!
    if vm_['ssh_host'] is not None:
        log.info('Installing Salt minion on %s', name)
        boot_ret = __utils__['cloud.bootstrap'](vm_, __opts__)
        log.debug('boot return: %s', boot_ret)
826646
def create(server_):
    '''
    
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if server_['profile'] and config.is_profile_configured(__opts__,
                                                               __active_provider_name__ or 'scaleway',
                                                               server_['profile'],
                                                               vm_=server_) is False:
            return False
    except AttributeError:
        pass

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(server_['name']),
        args=__utils__['cloud.filter_event']('creating', server_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    log.info('Creating a BareMetal server %s', server_['name'])

    access_key = config.get_cloud_config_value(
        'access_key', get_configured_provider(), __opts__, search_global=False
    )

    commercial_type = config.get_cloud_config_value(
        'commercial_type', server_, __opts__, default='C1'
    )

    key_filename = config.get_cloud_config_value(
        'ssh_key_file', server_, __opts__, search_global=False, default=None
    )

    if key_filename is not None and not os.path.isfile(key_filename):
        raise SaltCloudConfigError(
            'The defined key_filename \'{0}\' does not exist'.format(
                key_filename
            )
        )

    ssh_password = config.get_cloud_config_value(
        'ssh_password', server_, __opts__
    )

    kwargs = {
        'name': server_['name'],
        'organization': access_key,
        'image': get_image(server_),
        'commercial_type': commercial_type,
    }

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(server_['name']),
        args={
            'kwargs': __utils__['cloud.filter_event']('requesting', kwargs, list(kwargs)),
        },
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    try:
        ret = create_node(kwargs)
    except Exception as exc:
        log.error(
            'Error creating %s on Scaleway\n\n'
            'The following exception was thrown when trying to '
            'run the initial deployment: %s',
            server_['name'], exc,
            # Show the traceback if the debug logging level is enabled
            exc_info_on_loglevel=logging.DEBUG
        )
        return False

    def __query_node_data(server_name):
        ''' Called to check if the server has a public IP address.
        '''
        data = show_instance(server_name, 'action')
        if data and data.get('public_ip'):
            return data
        return False

    try:
        data = salt.utils.cloud.wait_for_ip(
            __query_node_data,
            update_args=(server_['name'],),
            timeout=config.get_cloud_config_value(
                'wait_for_ip_timeout', server_, __opts__, default=10 * 60),
            interval=config.get_cloud_config_value(
                'wait_for_ip_interval', server_, __opts__, default=10),
        )
    except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
        try:
            # It might be already up, let's destroy it!
            destroy(server_['name'])
        except SaltCloudSystemExit:
            pass
        finally:
            raise SaltCloudSystemExit(six.text_type(exc))

    server_['ssh_host'] = data['public_ip']['address']
    server_['ssh_password'] = ssh_password
    server_['key_filename'] = key_filename
    ret = __utils__['cloud.bootstrap'](server_, __opts__)

    ret.update(data)

    log.info('Created BareMetal server \'%s\'', server_['name'])
    log.debug(
        '\'%s\' BareMetal server creation details:\n%s',
        server_['name'], pprint.pformat(data)
    )

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(server_['name']),
        args=__utils__['cloud.filter_event']('created', server_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return ret
841647
def create(name, launch_config_name, availability_zones, min_size, max_size,
           desired_capacity=None, load_balancers=None, default_cooldown=None,
           health_check_type=None, health_check_period=None,
           placement_group=None, vpc_zone_identifier=None, tags=None,
           termination_policies=None, suspended_processes=None,
           scaling_policies=None, scheduled_actions=None, region=None,
           notification_arn=None, notification_types=None,
           key=None, keyid=None, profile=None):
    '''
    
    '''
    conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
    if isinstance(availability_zones, six.string_types):
        availability_zones = salt.utils.json.loads(availability_zones)
    if isinstance(load_balancers, six.string_types):
        load_balancers = salt.utils.json.loads(load_balancers)
    if isinstance(vpc_zone_identifier, six.string_types):
        vpc_zone_identifier = salt.utils.json.loads(vpc_zone_identifier)
    if isinstance(tags, six.string_types):
        tags = salt.utils.json.loads(tags)
    # Make a list of tag objects from the dict.
    _tags = []
    if tags:
        for tag in tags:
            try:
                key = tag.get('key')
            except KeyError:
                log.error('Tag missing key.')
                return False
            try:
                value = tag.get('value')
            except KeyError:
                log.error('Tag missing value.')
                return False
            propagate_at_launch = tag.get('propagate_at_launch', False)
            _tag = autoscale.Tag(key=key, value=value, resource_id=name,
                                 propagate_at_launch=propagate_at_launch)
            _tags.append(_tag)
    if isinstance(termination_policies, six.string_types):
        termination_policies = salt.utils.json.loads(termination_policies)
    if isinstance(suspended_processes, six.string_types):
        suspended_processes = salt.utils.json.loads(suspended_processes)
    if isinstance(scheduled_actions, six.string_types):
        scheduled_actions = salt.utils.json.loads(scheduled_actions)
    retries = 30
    while True:
        try:
            _asg = autoscale.AutoScalingGroup(
                name=name, launch_config=launch_config_name,
                availability_zones=availability_zones,
                min_size=min_size, max_size=max_size,
                desired_capacity=desired_capacity, load_balancers=load_balancers,
                default_cooldown=default_cooldown,
                health_check_type=health_check_type,
                health_check_period=health_check_period,
                placement_group=placement_group, tags=_tags,
                vpc_zone_identifier=vpc_zone_identifier,
                termination_policies=termination_policies,
                suspended_processes=suspended_processes)
            conn.create_auto_scaling_group(_asg)
            # create scaling policies
            _create_scaling_policies(conn, name, scaling_policies)
            # create scheduled actions
            _create_scheduled_actions(conn, name, scheduled_actions)
            # create notifications
            if notification_arn and notification_types:
                conn.put_notification_configuration(_asg, notification_arn, notification_types)
            log.info('Created ASG %s', name)
            return True
        except boto.exception.BotoServerError as e:
            if retries and e.code == 'Throttling':
                log.debug('Throttled by AWS API, retrying in 5 seconds...')
                time.sleep(5)
                retries -= 1
                continue
            log.error(e)
            msg = 'Failed to create ASG %s', name
            log.error(msg)
            return False
999945
def run_profile(self, profile, names, vm_overrides=None):
        '''
        
        '''
        if profile not in self.opts['profiles']:
            msg = 'Profile {0} is not defined'.format(profile)
            log.error(msg)
            return {'Error': msg}

        ret = {}
        if not vm_overrides:
            vm_overrides = {}

        try:
            with salt.utils.files.fopen(self.opts['conf_file'], 'r') as mcc:
                main_cloud_config = salt.utils.yaml.safe_load(mcc)
            if not main_cloud_config:
                main_cloud_config = {}
        except KeyError:
            main_cloud_config = {}
        except IOError:
            main_cloud_config = {}

        if main_cloud_config is None:
            main_cloud_config = {}

        mapped_providers = self.map_providers_parallel()
        profile_details = self.opts['profiles'][profile]
        vms = {}
        for prov, val in six.iteritems(mapped_providers):
            prov_name = next(iter(val))
            for node in mapped_providers[prov][prov_name]:
                vms[node] = mapped_providers[prov][prov_name][node]
                vms[node]['provider'] = prov
                vms[node]['driver'] = prov_name
        alias, driver = profile_details['provider'].split(':')

        provider_details = self.opts['providers'][alias][driver].copy()
        del provider_details['profiles']

        for name in names:
            if name in vms:
                prov = vms[name]['provider']
                driv = vms[name]['driver']
                msg = '{0} already exists under {1}:{2}'.format(
                    name, prov, driv
                )
                log.error(msg)
                ret[name] = {'Error': msg}
                continue

            vm_ = self.vm_config(
                name,
                main_cloud_config,
                provider_details,
                profile_details,
                vm_overrides,
            )
            if self.opts['parallel']:
                process = multiprocessing.Process(
                    target=self.create,
                    args=(vm_,)
                )
                process.start()
                ret[name] = {
                    'Provisioning': 'VM being provisioned in parallel. '
                                    'PID: {0}'.format(process.pid)
                }
                continue

            try:
                # No need to inject __active_provider_name__ into the context
                # here because self.create takes care of that
                ret[name] = self.create(vm_)
                if not ret[name]:
                    ret[name] = {'Error': 'Failed to deploy VM'}
                    if len(names) == 1:
                        raise SaltCloudSystemExit('Failed to deploy VM')
                    continue
                if self.opts.get('show_deploy_args', False) is False:
                    ret[name].pop('deploy_kwargs', None)
            except (SaltCloudSystemExit, SaltCloudConfigError) as exc:
                if len(names) == 1:
                    raise
                ret[name] = {'Error': str(exc)}

        return ret
1189385
def run(self):
        '''
        
        '''
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user')
        if salt_master_user is None:
            salt_master_user = salt.utils.user.get_user()

        if not check_user(salt_master_user):
            self.error(
                'If salt-cloud is running on a master machine, salt-cloud '
                'needs to run as the same user as the salt-master, \'{0}\'. '
                'If salt-cloud is not running on a salt-master, the '
                'appropriate write permissions must be granted to \'{1}\'. '
                'Please run salt-cloud as root, \'{0}\', or change '
                'permissions for \'{1}\'.'.format(
                    salt_master_user,
                    syspaths.CONFIG_DIR
                )
            )

        try:
            if self.config['verify_env']:
                verify_env(
                    [os.path.dirname(self.config['conf_file'])],
                    salt_master_user,
                    root_dir=self.config['root_dir'],
                )
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: %s', err)
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()
        verify_log(self.config)

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            salt.output.display_output(ret,
                                       self.options.output,
                                       opts=self.config)
            self.exit(salt.defaults.exitcodes.EX_OK)

        log.info('salt-cloud starting')
        try:
            mapper = salt.cloud.Map(self.config)
        except SaltCloudSystemExit as exc:
            self.handle_exception(exc.args, exc)
        except SaltCloudException as exc:
            msg = 'There was an error generating the mapper.'
            self.handle_exception(msg, exc)

        names = self.config.get('names', None)
        if names is not None:
            filtered_rendered_map = {}
            for map_profile in mapper.rendered_map:
                filtered_map_profile = {}
                for name in mapper.rendered_map[map_profile]:
                    if name in names:
                        filtered_map_profile[name] = mapper.rendered_map[map_profile][name]
                if filtered_map_profile:
                    filtered_rendered_map[map_profile] = filtered_map_profile
            mapper.rendered_map = filtered_rendered_map

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.selected_query_option == 'list_profiles':
                provider = self.options.list_profiles
                try:
                    ret = mapper.profile_list(provider)
                except(SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing profiles: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info('Applying map from \'%s\'.', self.config['map'])
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(
                    self.options.list_locations
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(
                    self.options.list_images
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(
                    self.options.list_sizes
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None) or
                                       self.config.get('map', None)):
            map_file = self.config.get('map', None)
            names = self.config.get('names', ())
            if map_file is not None:
                if names != ():
                    msg = 'Supplying a mapfile, \'{0}\', in addition to instance names {1} ' \
                          'with the \'--destroy\' or \'-d\' function is not supported. ' \
                          'Please choose to delete either the entire map file or individual ' \
                          'instances.'.format(map_file, names)
                    self.handle_exception(msg, SaltCloudSystemExit)

                log.info('Applying map from \'%s\'.', map_file)
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    names,
                    profile=self.options.profile
                )

            if not matching:
                print('No machines were found to be destroyed')
                self.exit(salt.defaults.exitcodes.EX_OK)

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in six.iteritems(matching):
                msg += '  {0}:\n'.format(alias)
                for driver, vms in six.iteritems(drivers):
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None) or
                                      self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from \'%s\'.', self.config['map'])
                try:
                    names = mapper.get_vmnames_by_action(self.options.action)
                except SaltCloudException as exc:
                    msg = 'There was an error actioning virtual machines.'
                    self.handle_exception(msg, exc)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(
                    self.options.action
                )
            )
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    key, value = name.split('=', 1)
                    kwargs[key] = value
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args)
                )
            try:
                ret = mapper.do_function(
                    self.function_provider, self.function_name, kwargs
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(
                    self.options.profile,
                    self.config.get('names')
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if not mapper.rendered_map:
                sys.stderr.write('No nodes defined in this map')
                self.exit(salt.defaults.exitcodes.EX_GENERIC)
            try:
                ret = {}
                run_map = True

                log.info('Applying map from \'%s\'.', self.config['map'])
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in six.iteritems(dmap['errors']):
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines already exist:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing']:
                        if 'ec2' in dmap['existing'][name]['provider']:
                            msg = 'Instance already exists, or is terminated and has the same name.'
                        else:
                            msg = 'Already running.'
                        ret[name] = {'Message': msg}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.bootstrap:
            host = self.options.bootstrap
            if self.args and '=' not in self.args[0]:
                minion_id = self.args.pop(0)
            else:
                minion_id = host

            vm_ = {
                'driver': '',
                'ssh_host': host,
                'name': minion_id,
            }
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    vm_[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --bootstrap need to be passed as '
                    'kwargs. Ex: ssh_username=larry. Remaining arguments: {0}'.format(args)
                )

            try:
                ret = salt.utils.cloud.bootstrap(vm_, self.config)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error bootstrapping the minion: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        salt.output.display_output(ret,
                                   self.options.output,
                                   opts=self.config)
        self.exit(salt.defaults.exitcodes.EX_OK)
1366299
def create(vm_):
    '''
    
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'cloudstack',
                                                           vm_['profile'],
                                                           vm_=vm_) is False:
            return False
    except AttributeError:
        pass

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        sock_dir=__opts__['sock_dir'],
        args=__utils__['cloud.filter_event']('creating', vm_, ['name', 'profile', 'provider', 'driver']),
        transport=__opts__['transport']
    )

    log.info('Creating Cloud VM %s', vm_['name'])
    conn = get_conn()
    # pylint: disable=not-callable
    kwargs = {
        'name': vm_['name'],
        'image': get_image(conn, vm_),
        'size': get_size(conn, vm_),
        'location': get_location(conn, vm_),
    }
    # pylint: enable=not-callable

    sg = get_security_groups(conn, vm_)
    if sg is not False:
        kwargs['ex_security_groups'] = sg

    if get_keypair(vm_) is not False:
        kwargs['ex_keyname'] = get_keypair(vm_)

    if get_networkid(vm_) is not False:
        kwargs['networkids'] = get_networkid(vm_)
        kwargs['networks'] = (   # The only attr that is used is 'id'.
                                 CloudStackNetwork(None, None, None,
                                                   kwargs['networkids'],
                                                   None, None),
                             )

    if get_project(conn, vm_) is not False:
        kwargs['project'] = get_project(conn, vm_)

    event_data = kwargs.copy()
    event_data['image'] = kwargs['image'].name
    event_data['size'] = kwargs['size'].name

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        sock_dir=__opts__['sock_dir'],
        args={
            'kwargs': __utils__['cloud.filter_event'](
                'requesting',
                event_data,
                ['name', 'profile', 'provider', 'driver', 'image', 'size'],
            ),
        },
        transport=__opts__['transport']
    )

    displayname = cloudstack_displayname(vm_)
    if displayname:
        kwargs['ex_displayname'] = displayname
    else:
        kwargs['ex_displayname'] = kwargs['name']

    volumes = {}
    ex_blockdevicemappings = block_device_mappings(vm_)
    if ex_blockdevicemappings:
        for ex_blockdevicemapping in ex_blockdevicemappings:
            if 'VirtualName' not in ex_blockdevicemapping:
                ex_blockdevicemapping['VirtualName'] = '{0}-{1}'.format(vm_['name'], len(volumes))
            __utils__['cloud.fire_event'](
                'event',
                'requesting volume',
                'salt/cloud/{0}/requesting'.format(ex_blockdevicemapping['VirtualName']),
                sock_dir=__opts__['sock_dir'],
                args={'kwargs': {'name': ex_blockdevicemapping['VirtualName'],
                                 'device': ex_blockdevicemapping['DeviceName'],
                                 'size': ex_blockdevicemapping['VolumeSize']}},
            )
            try:
                volumes[ex_blockdevicemapping['DeviceName']] = conn.create_volume(
                        ex_blockdevicemapping['VolumeSize'],
                        ex_blockdevicemapping['VirtualName']
                    )
            except Exception as exc:
                log.error(
                    'Error creating volume %s on CLOUDSTACK\n\n'
                    'The following exception was thrown by libcloud when trying to '
                    'requesting a volume: \n%s',
                    ex_blockdevicemapping['VirtualName'], exc,
                    # Show the traceback if the debug logging level is enabled
                    exc_info_on_loglevel=logging.DEBUG
                )
                return False
    else:
        ex_blockdevicemapping = {}
    try:
        data = conn.create_node(**kwargs)
    except Exception as exc:
        log.error(
            'Error creating %s on CLOUDSTACK\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: \n%s',
            vm_['name'], exc,
            # Show the traceback if the debug logging level is enabled
            exc_info_on_loglevel=logging.DEBUG
        )
        return False

    for device_name in six.iterkeys(volumes):
        try:
            conn.attach_volume(data, volumes[device_name], device_name)
        except Exception as exc:
            log.error(
                'Error attaching volume %s on CLOUDSTACK\n\n'
                'The following exception was thrown by libcloud when trying to '
                'attach a volume: \n%s',
                ex_blockdevicemapping.get('VirtualName', 'UNKNOWN'), exc,
                # Show the traceback if the debug logging level is enabled
                exc_info=log.isEnabledFor(logging.DEBUG)
            )
            return False

    ssh_username = config.get_cloud_config_value(
        'ssh_username', vm_, __opts__, default='root'
    )

    vm_['ssh_host'] = get_ip(data)
    vm_['password'] = data.extra['password']
    vm_['key_filename'] = get_key()
    ret = __utils__['cloud.bootstrap'](vm_, __opts__)

    ret.update(data.__dict__)

    if 'password' in data.extra:
        del data.extra['password']

    log.info('Created Cloud VM \'%s\'', vm_['name'])
    log.debug(
        '\'%s\' VM creation details:\n%s',
        vm_['name'], pprint.pformat(data.__dict__)
    )

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(vm_['name']),
        sock_dir=__opts__['sock_dir'],
        args=__utils__['cloud.filter_event']('created', vm_, ['name', 'profile', 'provider', 'driver']),
        transport=__opts__['transport']
    )

    return ret
1157868
def ls(ctx, name, list_instances):
    """"""
    session = create_session(ctx.obj['AWS_PROFILE_NAME'])

    client = session.client('elb')
    inst = {'LoadBalancerDescriptions': []}
    if name == '*':
        inst = client.describe_load_balancers()
    else:
        try:
            inst = client.describe_load_balancers(LoadBalancerNames=[name])
        except ClientError as e:
            click.echo(e, err=True)

    for i in inst['LoadBalancerDescriptions']:
        click.echo(i['LoadBalancerName'])
        if list_instances:
            for ec2 in i['Instances']:
                health = client.describe_instance_health(
                    LoadBalancerName=name,
                    Instances=[ec2]
                )
                click.echo('{0}\t{1}'.format(ec2['InstanceId'], health['InstanceStates'][0]['State']))
897870
def start(name):
    '''
    
    '''
    __salt__['file.remove']('{0}/down'.format(_service_path(name)))
    cmd = 'svc -u {0}'.format(_service_path(name))
    return not __salt__['cmd.retcode'](cmd, python_shell=False)
931128
def bootstrap(vm_, opts=None):
    '''
    
    '''
    if opts is None:
        opts = __opts__
    deploy_config = salt.config.get_cloud_config_value(
        'deploy',
        vm_, opts, default=False)
    inline_script_config = salt.config.get_cloud_config_value(
        'inline_script',
        vm_, opts, default=None)
    if deploy_config is False and inline_script_config is None:
        return {
            'Error': {
                'No Deploy': '\'deploy\' is not enabled. Not deploying.'
            }
        }

    if vm_.get('driver') == 'saltify':
        saltify_driver = True
    else:
        saltify_driver = False

    key_filename = salt.config.get_cloud_config_value(
        'key_filename', vm_, opts, search_global=False,
        default=salt.config.get_cloud_config_value(
            'ssh_keyfile', vm_, opts, search_global=False, default=None
        )
    )
    if key_filename is not None and not os.path.isfile(key_filename):
        raise SaltCloudConfigError(
            'The defined ssh_keyfile \'{0}\' does not exist'.format(
                key_filename
            )
        )
    has_ssh_agent = False
    if (opts.get('ssh_agent', False) and
            'SSH_AUTH_SOCK' in os.environ and
            stat.S_ISSOCK(os.stat(os.environ['SSH_AUTH_SOCK']).st_mode)):
        has_ssh_agent = True

    if (key_filename is None and
            salt.config.get_cloud_config_value(
                'password', vm_, opts, default=None
            ) is None and
            salt.config.get_cloud_config_value(
                'win_password', vm_, opts, default=None
            ) is None and
            has_ssh_agent is False):
        raise SaltCloudSystemExit(
            'Cannot deploy Salt in a VM if the \'key_filename\' setting '
            'is not set and there is no password set for the VM. '
            'Check the provider docs for \'change_password\' option if it '
            'is supported by your provider.'
        )

    ret = {}

    minion_conf = minion_config(opts, vm_)
    deploy_script_code = os_script(
        salt.config.get_cloud_config_value(
            'os', vm_, opts, default='bootstrap-salt'
        ),
        vm_, opts, minion_conf
    )

    ssh_username = salt.config.get_cloud_config_value(
        'ssh_username', vm_, opts, default='root'
    )

    if 'file_transport' not in opts:
        opts['file_transport'] = vm_.get('file_transport', 'sftp')

    # If we haven't generated any keys yet, do so now.
    if 'pub_key' not in vm_ and 'priv_key' not in vm_:
        log.debug('Generating keys for \'%s\'', vm_['name'])

        vm_['priv_key'], vm_['pub_key'] = gen_keys(
            salt.config.get_cloud_config_value(
                'keysize',
                vm_,
                opts
            )
        )

        key_id = vm_.get('name')
        if 'append_domain' in vm_:
            key_id = '.'.join([key_id, vm_['append_domain']])

        accept_key(
            opts['pki_dir'], vm_['pub_key'], key_id
        )

    if 'os' not in vm_:
        vm_['os'] = salt.config.get_cloud_config_value(
            'script',
            vm_,
            opts
        )

    # NOTE: deploy_kwargs is also used to pass inline_script variable content
    #       to run_inline_script function
    host = salt.config.get_cloud_config_value('ssh_host', vm_, opts)
    deploy_kwargs = {
        'opts': opts,
        'host': host,
        'port': salt.config.get_cloud_config_value(
            'ssh_port', vm_, opts, default=22
        ),
        'salt_host': vm_.get('salt_host', host),
        'username': ssh_username,
        'script': deploy_script_code,
        'inline_script': inline_script_config,
        'name': vm_['name'],
        'has_ssh_agent': has_ssh_agent,
        'tmp_dir': salt.config.get_cloud_config_value(
            'tmp_dir', vm_, opts, default='/tmp/.saltcloud'
        ),
        'vm_': vm_,
        'start_action': opts['start_action'],
        'parallel': opts['parallel'],
        'sock_dir': opts['sock_dir'],
        'conf_file': opts['conf_file'],
        'minion_pem': vm_['priv_key'],
        'minion_pub': vm_['pub_key'],
        'master_sign_pub_file': salt.config.get_cloud_config_value(
            'master_sign_pub_file', vm_, opts, default=None),
        'keep_tmp': opts['keep_tmp'],
        'sudo': salt.config.get_cloud_config_value(
            'sudo', vm_, opts, default=(ssh_username != 'root')
        ),
        'sudo_password': salt.config.get_cloud_config_value(
            'sudo_password', vm_, opts, default=None
        ),
        'tty': salt.config.get_cloud_config_value(
            'tty', vm_, opts, default=True
        ),
        'password': salt.config.get_cloud_config_value(
            'password', vm_, opts, search_global=False
        ),
        'key_filename': key_filename,
        'script_args': salt.config.get_cloud_config_value(
            'script_args', vm_, opts
        ),
        'script_env': salt.config.get_cloud_config_value(
            'script_env', vm_, opts
        ),
        'minion_conf': minion_conf,
        'force_minion_config': salt.config.get_cloud_config_value(
            'force_minion_config', vm_, opts, default=False
        ),
        'preseed_minion_keys': vm_.get('preseed_minion_keys', None),
        'display_ssh_output': salt.config.get_cloud_config_value(
            'display_ssh_output', vm_, opts, default=True
        ),
        'known_hosts_file': salt.config.get_cloud_config_value(
            'known_hosts_file', vm_, opts, default='/dev/null'
        ),
        'file_map': salt.config.get_cloud_config_value(
            'file_map', vm_, opts, default=None
        ),
        'maxtries': salt.config.get_cloud_config_value(
            'wait_for_passwd_maxtries', vm_, opts, default=15
        ),
        'preflight_cmds': salt.config.get_cloud_config_value(
            'preflight_cmds', vm_, opts, default=[]
        ),
        'cloud_grains': {'driver': vm_['driver'],
                         'provider': vm_['provider'],
                         'profile': vm_['profile']
                         }
    }

    inline_script_kwargs = deploy_kwargs.copy()  # make a copy at this point

    # forward any info about possible ssh gateway to deploy script
    # as some providers need also a 'gateway' configuration
    if 'gateway' in vm_:
        deploy_kwargs.update({'gateway': vm_['gateway']})

    # Deploy salt-master files, if necessary
    if salt.config.get_cloud_config_value('make_master', vm_, opts) is True:
        deploy_kwargs['make_master'] = True
        deploy_kwargs['master_pub'] = vm_['master_pub']
        deploy_kwargs['master_pem'] = vm_['master_pem']
        master_conf = master_config(opts, vm_)
        deploy_kwargs['master_conf'] = master_conf

        if master_conf.get('syndic_master', None):
            deploy_kwargs['make_syndic'] = True

    deploy_kwargs['make_minion'] = salt.config.get_cloud_config_value(
        'make_minion', vm_, opts, default=True
    )

    if saltify_driver:
        deploy_kwargs['wait_for_passwd_maxtries'] = 0  # No need to wait/retry with Saltify

    win_installer = salt.config.get_cloud_config_value(
        'win_installer', vm_, opts
    )
    if win_installer:
        deploy_kwargs['port'] = salt.config.get_cloud_config_value(
            'smb_port', vm_, opts, default=445
        )
        deploy_kwargs['win_installer'] = win_installer
        minion = minion_config(opts, vm_)
        deploy_kwargs['master'] = minion['master']
        deploy_kwargs['username'] = salt.config.get_cloud_config_value(
            'win_username', vm_, opts, default='Administrator'
        )
        win_pass = salt.config.get_cloud_config_value(
            'win_password', vm_, opts, default=''
        )
        if win_pass:
            deploy_kwargs['password'] = win_pass
        deploy_kwargs['use_winrm'] = salt.config.get_cloud_config_value(
            'use_winrm', vm_, opts, default=False
        )
        deploy_kwargs['winrm_port'] = salt.config.get_cloud_config_value(
            'winrm_port', vm_, opts, default=5986
        )
        deploy_kwargs['winrm_use_ssl'] = salt.config.get_cloud_config_value(
            'winrm_use_ssl', vm_, opts, default=True
        )
        deploy_kwargs['winrm_verify_ssl'] = salt.config.get_cloud_config_value(
            'winrm_verify_ssl', vm_, opts, default=True
        )
        if saltify_driver:
            deploy_kwargs['port_timeout'] = 1  # No need to wait/retry with Saltify

    # Store what was used to the deploy the VM
    event_kwargs = copy.deepcopy(deploy_kwargs)
    del event_kwargs['opts']
    del event_kwargs['minion_pem']
    del event_kwargs['minion_pub']
    del event_kwargs['sudo_password']
    if 'password' in event_kwargs:
        del event_kwargs['password']
    ret['deploy_kwargs'] = event_kwargs

    fire_event(
        'event',
        'executing deploy script',
        'salt/cloud/{0}/deploying'.format(vm_['name']),
        args={'kwargs': salt.utils.data.simple_types_filter(event_kwargs)},
        sock_dir=opts.get(
            'sock_dir',
            os.path.join(__opts__['sock_dir'], 'master')),
        transport=opts.get('transport', 'zeromq')
    )

    if inline_script_config and deploy_config is False:
        inline_script_deployed = run_inline_script(**inline_script_kwargs)
        if inline_script_deployed is not False:
            log.info('Inline script(s) ha(s|ve) run on %s', vm_['name'])
        ret['deployed'] = False
        return ret
    else:
        if win_installer:
            deployed = deploy_windows(**deploy_kwargs)
        else:
            deployed = deploy_script(**deploy_kwargs)

        if inline_script_config:
            inline_script_deployed = run_inline_script(**inline_script_kwargs)
            if inline_script_deployed is not False:
                log.info('Inline script(s) ha(s|ve) run on %s', vm_['name'])

        if deployed is not False:
            ret['deployed'] = True
            if deployed is not True:
                ret.update(deployed)
            log.info('Salt installed on %s', vm_['name'])
            return ret

    log.error('Failed to start Salt on host %s', vm_['name'])
    return {
        'Error': {
            'Not Deployed': 'Failed to start Salt on host {0}'.format(
                vm_['name']
            )
        }
    }
762887
def create(vm_):
    '''
    
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'azure',
                                                           vm_['profile'],
                                                           vm_=vm_) is False:
            return False
    except AttributeError:
        pass

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('creating', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    log.info('Creating Cloud VM %s', vm_['name'])
    conn = get_conn()

    label = vm_.get('label', vm_['name'])
    service_name = vm_.get('service_name', vm_['name'])
    service_kwargs = {
        'service_name': service_name,
        'label': label,
        'description': vm_.get('desc', vm_['name']),
    }

    loc_error = False
    if 'location' in vm_:
        if 'affinity_group' in vm_:
            loc_error = True
        else:
            service_kwargs['location'] = vm_['location']
    elif 'affinity_group' in vm_:
        service_kwargs['affinity_group'] = vm_['affinity_group']
    else:
        loc_error = True

    if loc_error:
        raise SaltCloudSystemExit(
            'Either a location or affinity group must be specified, but not both'
        )

    ssh_port = config.get_cloud_config_value('port', vm_, __opts__,
                                             default=22, search_global=True)

    ssh_endpoint = azure.servicemanagement.ConfigurationSetInputEndpoint(
        name='SSH',
        protocol='TCP',
        port=ssh_port,
        local_port=22,
    )

    network_config = azure.servicemanagement.ConfigurationSet()
    network_config.input_endpoints.input_endpoints.append(ssh_endpoint)
    network_config.configuration_set_type = 'NetworkConfiguration'

    if 'win_username' in vm_:
        system_config = azure.servicemanagement.WindowsConfigurationSet(
            computer_name=vm_['name'],
            admin_username=vm_['win_username'],
            admin_password=vm_['win_password'],
        )

        smb_port = '445'
        if 'smb_port' in vm_:
            smb_port = vm_['smb_port']

        smb_endpoint = azure.servicemanagement.ConfigurationSetInputEndpoint(
            name='SMB',
            protocol='TCP',
            port=smb_port,
            local_port=smb_port,
        )

        network_config.input_endpoints.input_endpoints.append(smb_endpoint)

        # Domain and WinRM configuration not yet supported by Salt Cloud
        system_config.domain_join = None
        system_config.win_rm = None

    else:
        system_config = azure.servicemanagement.LinuxConfigurationSet(
            host_name=vm_['name'],
            user_name=vm_['ssh_username'],
            user_password=vm_['ssh_password'],
            disable_ssh_password_authentication=False,
        )

    # TODO: Might need to create a storage account
    media_link = vm_['media_link']
    # TODO: Probably better to use more than just the name in the media_link
    media_link += '/{0}.vhd'.format(vm_['name'])
    os_hd = azure.servicemanagement.OSVirtualHardDisk(vm_['image'], media_link)

    vm_kwargs = {
        'service_name': service_name,
        'deployment_name': service_name,
        'deployment_slot': vm_['slot'],
        'label': label,
        'role_name': vm_['name'],
        'system_config': system_config,
        'os_virtual_hard_disk': os_hd,
        'role_size': vm_['size'],
        'network_config': network_config,
    }

    if 'virtual_network_name' in vm_:
        vm_kwargs['virtual_network_name'] = vm_['virtual_network_name']
        if 'subnet_name' in vm_:
            network_config.subnet_names.append(vm_['subnet_name'])

    log.debug('vm_kwargs: %s', vm_kwargs)

    event_kwargs = {'service_kwargs': service_kwargs.copy(),
                    'vm_kwargs': vm_kwargs.copy()}
    del event_kwargs['vm_kwargs']['system_config']
    del event_kwargs['vm_kwargs']['os_virtual_hard_disk']
    del event_kwargs['vm_kwargs']['network_config']
    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('requesting', event_kwargs, list(event_kwargs)),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )
    log.debug('vm_kwargs: %s', vm_kwargs)

    # Azure lets you open winrm on a new VM
    # Can open up specific ports in Azure; but not on Windows
    try:
        conn.create_hosted_service(**service_kwargs)
    except AzureConflictHttpError:
        log.debug('Cloud service already exists')
    except Exception as exc:
        error = 'The hosted service name is invalid.'
        if error in six.text_type(exc):
            log.error(
                'Error creating %s on Azure.\n\n'
                'The hosted service name is invalid. The name can contain '
                'only letters, numbers, and hyphens. The name must start with '
                'a letter and must end with a letter or a number.',
                vm_['name'],
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG
            )
        else:
            log.error(
                'Error creating %s on Azure\n\n'
                'The following exception was thrown when trying to '
                'run the initial deployment: \n%s',
                vm_['name'], exc,
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG
            )
        return False
    try:
        result = conn.create_virtual_machine_deployment(**vm_kwargs)
        log.debug('Request ID for machine: %s', result.request_id)
        _wait_for_async(conn, result.request_id)
    except AzureConflictHttpError:
        log.debug('Conflict error. The deployment may already exist, trying add_role')
        # Deleting two useless keywords
        del vm_kwargs['deployment_slot']
        del vm_kwargs['label']
        del vm_kwargs['virtual_network_name']
        result = conn.add_role(**vm_kwargs)
        _wait_for_async(conn, result.request_id)
    except Exception as exc:
        error = 'The hosted service name is invalid.'
        if error in six.text_type(exc):
            log.error(
                'Error creating %s on Azure.\n\n'
                'The VM name is invalid. The name can contain '
                'only letters, numbers, and hyphens. The name must start with '
                'a letter and must end with a letter or a number.',
                vm_['name'],
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG
            )
        else:
            log.error(
                'Error creating %s on Azure.\n\n'
                'The Virtual Machine could not be created. If you '
                'are using an already existing Cloud Service, '
                'make sure you set up the `port` variable corresponding '
                'to the SSH port exists and that the port number is not '
                'already in use.\nThe following exception was thrown when trying to '
                'run the initial deployment: \n%s',
                vm_['name'], exc,
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG
            )
        return False

    def wait_for_hostname():
        '''
        Wait for the IP address to become available
        '''
        try:
            conn.get_role(service_name, service_name, vm_['name'])
            data = show_instance(vm_['name'], call='action')
            if 'url' in data and data['url'] != six.text_type(''):
                return data['url']
        except AzureMissingResourceHttpError:
            pass
        time.sleep(1)
        return False

    hostname = salt.utils.cloud.wait_for_fun(
        wait_for_hostname,
        timeout=config.get_cloud_config_value(
            'wait_for_fun_timeout', vm_, __opts__, default=15 * 60),
    )

    if not hostname:
        log.error('Failed to get a value for the hostname.')
        return False

    vm_['ssh_host'] = hostname.replace('http://', '').replace('/', '')
    vm_['password'] = config.get_cloud_config_value(
        'ssh_password', vm_, __opts__
    )
    ret = __utils__['cloud.bootstrap'](vm_, __opts__)

    # Attaching volumes
    volumes = config.get_cloud_config_value(
        'volumes', vm_, __opts__, search_global=True
    )
    if volumes:
        __utils__['cloud.fire_event'](
            'event',
            'attaching volumes',
            'salt/cloud/{0}/attaching_volumes'.format(vm_['name']),
            args=__utils__['cloud.filter_event']('attaching_volumes', vm_, ['volumes']),
            sock_dir=__opts__['sock_dir'],
            transport=__opts__['transport']
        )

        log.info('Create and attach volumes to node %s', vm_['name'])
        created = create_attach_volumes(
            vm_['name'],
            {
                'volumes': volumes,
                'service_name': service_name,
                'deployment_name': vm_['name'],
                'media_link': media_link,
                'role_name': vm_['name'],
                'del_all_vols_on_destroy': vm_.get('set_del_all_vols_on_destroy', False)
            },
            call='action'
        )
        ret['Attached Volumes'] = created

    data = show_instance(vm_['name'], call='action')
    log.info('Created Cloud VM \'%s\'', vm_)
    log.debug('\'%s\' VM creation details:\n%s', vm_['name'], pprint.pformat(data))

    ret.update(data)

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('created', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return ret