Esempio n. 1
0
def get_location(conn, vm_):
    '''
    Return the location object to use
    '''
    locations = conn.list_locations()
    vm_location = config.get_config_value('location', vm_, __opts__).encode(
        'ascii', 'salt-cloud-force-ascii')

    for img in locations:
        if isinstance(img.id, salt._compat.string_types):
            img_id = img.id.encode('ascii', 'salt-cloud-force-ascii')
        else:
            img_id = str(img.id)

        if isinstance(img.name, salt._compat.string_types):
            img_name = img.name.encode('ascii', 'salt-cloud-force-ascii')
        else:
            img_name = str(img.name)

        if vm_location and vm_location in (img_id, img_name):
            return img

    raise SaltCloudNotFound(
        'The specified location, {0!r}, could not be found.'.format(
            vm_location))
Esempio n. 2
0
def get_image(conn, vm_):
    '''
    Return the image object to use
    '''
    images = conn.list_images()

    vm_image = config.get_config_value('image', vm_, __opts__).encode(
        'ascii', 'salt-cloud-force-ascii')

    for img in images:
        if isinstance(img.id, salt._compat.string_types):
            img_id = img.id.encode('ascii', 'salt-cloud-force-ascii')
        else:
            img_id = str(img.id)

        if isinstance(img.name, salt._compat.string_types):
            img_name = img.name.encode('ascii', 'salt-cloud-force-ascii')
        else:
            img_name = str(img.name)

        if vm_image and vm_image in (img_id, img_name):
            return img

    raise SaltCloudNotFound(
        'The specified image, {0!r}, could not be found.'.format(vm_image))
Esempio n. 3
0
def get_image(vm_):
    '''
    Return the image object to use
    '''
    images = avail_images()
    vm_image = str(config.get_cloud_config_value(
        'image', vm_, __opts__, search_global=False
    ))

    if not vm_image:
        raise SaltCloudNotFound('No image specified for this VM.')

    if vm_image and str(vm_image) in images.keys():
        return images[vm_image]['ImageId']
    raise SaltCloudNotFound(
        'The specified image, {0!r}, could not be found.'.format(vm_image)
    )
Esempio n. 4
0
def get_size(vm_):
    '''
    Return the VM's size. Used by create_node().
    '''
    sizes = avail_sizes()
    vm_size = str(config.get_cloud_config_value(
        'size', vm_, __opts__, search_global=False
    ))

    if not vm_size:
        raise SaltCloudNotFound('No size specified for this VM.')

    if vm_size and str(vm_size) in sizes.keys():
        return sizes[vm_size]['InstanceTypeId']

    raise SaltCloudNotFound(
        'The specified size, {0!r}, could not be found.'.format(vm_size)
    )
Esempio n. 5
0
def get_securitygroup(vm_):
    '''
    Return the security group
    '''
    sgs = list_securitygroup()
    securitygroup = config.get_cloud_config_value('securitygroup',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False)

    if not securitygroup:
        raise SaltCloudNotFound('No securitygroup ID specified for this VM.')

    if securitygroup and str(securitygroup) in sgs.keys():
        return sgs[securitygroup]['SecurityGroupId']
    raise SaltCloudNotFound(
        'The specified security group, {0!r}, could not be found.'.format(
            securitygroup))
Esempio n. 6
0
def __get_location(vm_):
    '''
    Return the VM's location
    '''
    locations = avail_locations()
    vm_location = str(
        config.get_cloud_config_value('location',
                                      vm_,
                                      __opts__,
                                      search_global=False))

    if not vm_location:
        raise SaltCloudNotFound('No location specified for this VM.')

    if vm_location and str(vm_location) in locations.keys():
        return locations[vm_location]['RegionId']
    raise SaltCloudNotFound(
        'The specified location, {0!r}, could not be found.'.format(
            vm_location))
Esempio n. 7
0
def get_keyid(keyname):
    '''
    Return the ID of the keyname
    '''
    if not keyname:
        return None
    keypairs = list_keypairs(call='function')
    keyid = keypairs[keyname]['id']
    if keyid:
        return keyid
    raise SaltCloudNotFound('The specified ssh key could not be found.')
Esempio n. 8
0
def get_image(vm_):
    '''
    Return the image object to use
    '''
    images = avail_images()
    vm_image = str(
        config.get_config_value('image', vm_, __opts__, search_global=False))
    for image in images:
        if vm_image in (images[image]['name'], images[image]['id']):
            return images[image]['id']
    raise SaltCloudNotFound(
        'The specified image, {0!r}, could not be found.'.format(vm_image))
Esempio n. 9
0
def get_size(vm_):
    '''
    Return the VM's size. Used by create_node().
    '''
    sizes = avail_sizes()
    vm_size = str(
        config.get_config_value('size', vm_, __opts__, search_global=False))
    for size in sizes:
        if vm_size in (sizes[size]['name'], sizes[size]['id']):
            return sizes[size]['id']
    raise SaltCloudNotFound(
        'The specified size, {0!r}, could not be found.'.format(vm_size))
Esempio n. 10
0
def _get_node(name):
    attempts = 5
    while attempts >= 0:
        try:
            return list_nodes_full()[name]
        except KeyError:
            attempts -= 1
            log.debug('Failed to get the data for the node {0!r}. Remaining '
                      'attempts {1}'.format(name, attempts))
            # Just a little delay between attempts...
            time.sleep(0.5)
    raise SaltCloudNotFound(
        'The specified instance {0} not found'.format(name))
Esempio n. 11
0
def get_size(conn, vm_):
    '''
    Return the VM's size object
    '''
    sizes = conn.list_sizes()
    vm_size = config.get_cloud_config_value('size', vm_, __opts__)
    if not vm_size:
        return sizes[0]

    for size in sizes:
        if vm_size and str(vm_size) in (str(sizes[size]['id']), str(size)):
            return sizes[size]['id']
    raise SaltCloudNotFound(
        'The specified size, {0!r}, could not be found.'.format(vm_size))
Esempio n. 12
0
def get_location(vm_):
    '''
    Return the VM's location
    '''
    locations = avail_locations()
    vm_location = str(
        config.get_config_value('location', vm_, __opts__,
                                search_global=False))

    for location in locations:
        if vm_location in (locations[location]['name'],
                           locations[location]['id']):
            return locations[location]['id']
    raise SaltCloudNotFound(
        'The specified location, {0!r}, could not be found.'.format(
            vm_location))
Esempio n. 13
0
def get_image(conn, vm_):
    '''
    Return the image object to use
    '''
    image_list = conn.image_list()

    vm_image = config.get_cloud_config_value('image', vm_, __opts__).encode(
        'ascii', 'salt-cloud-force-ascii'
    )

    for img in image_list.keys():
        if vm_image in (image_list[img]['id'], img):
            return image_list[img]['id']

    raise SaltCloudNotFound(
        'The specified image, {0!r}, could not be found.'.format(vm_image)
    )
Esempio n. 14
0
def get_image(conn, vm_):
    '''
    Return the image object to use
    '''
    image_list = conn.image_list()

    vm_image = config.get_cloud_config_value('image', vm_, __opts__).encode(
        'ascii', 'salt-cloud-force-ascii')

    for img in image_list.keys():
        if vm_image in (image_list[img]['id'], img):
            return image_list[img]['id']

    try:
        image = conn.image_show(vm_image)
        return image['id']
    except novaclient.exceptions.NotFound as exc:
        raise SaltCloudNotFound(
            'The specified image, {0!r}, could not be found: {1}'.format(
                vm_image, exc.message))
Esempio n. 15
0
def show_image(kwargs, call=None):
    '''
    Show the details from aliyun image
    '''
    if call != 'function':
        raise SaltCloudSystemExit(
            'The show_images function must be called with '
            '-f or --function'
        )

    if not isinstance(kwargs, dict):
        kwargs = {}

    location = get_location()
    if 'location' in kwargs:
        location = kwargs['location']

    params = {
        'Action': 'DescribeImages',
        'RegionId': location,
        'ImageId': kwargs['image']
    }

    ret = {}
    items = query(params=params)
    # DescribeImages so far support input multi-image. And
    # if not found certain image, the response will include
    # blank image list other than 'not found' error message
    if 'Code' in items or len(items['Images']['Image']) == 0:
        raise SaltCloudNotFound('The specified image could not be found.')

    log.debug('Total {0} image found in Region {1}'.format(
        items['TotalCount'], location)
    )

    for image in items['Images']['Image']:
        ret[image['ImageId']] = {}
        for item in image.keys():
            ret[image['ImageId']][item] = str(image[item])

    return ret
Esempio n. 16
0
def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
    key_filename = config.get_cloud_config_value('ssh_key_file',
                                                 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_key_file {0!r} does not exist'.format(
                key_filename))

    if deploy is True and key_filename is None and \
            salt.utils.which('sshpass') is None:
        raise SaltCloudSystemExit(
            'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
            'is not set and \'sshpass\' binary is not present on the '
            'system for the password.')

    salt.utils.cloud.fire_event('event',
                                'starting create',
                                'salt/cloud/{0}/creating'.format(vm_['name']),
                                {
                                    'name': vm_['name'],
                                    'profile': vm_['profile'],
                                    'provider': vm_['provider'],
                                },
                                transport=__opts__['transport'])

    log.info('Creating Cloud VM {0}'.format(vm_['name']))
    salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = {'name': vm_['name']}

    try:
        kwargs['image_id'] = get_image(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find image {1}: {2}\n'.format(vm_['name'], vm_['image'],
                                                     exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    try:
        kwargs['flavor_id'] = get_size(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find size {1}: {2}\n'.format(vm_['name'], vm_['size'],
                                                    exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    kwargs['key_name'] = config.get_cloud_config_value('ssh_key_name',
                                                       vm_,
                                                       __opts__,
                                                       search_global=False)

    security_groups = config.get_cloud_config_value('security_groups',
                                                    vm_,
                                                    __opts__,
                                                    search_global=False)
    if security_groups is not None:
        vm_groups = security_groups.split(',')
        avail_groups = conn.ex_list_security_groups()
        group_list = []

        for vmg in vm_groups:
            if vmg in [ag.name for ag in avail_groups]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg))

        kwargs['ex_security_groups'] = [
            g for g in avail_groups if g.name in group_list
        ]

    networks = config.get_cloud_config_value('networks',
                                             vm_,
                                             __opts__,
                                             search_global=False)

    floating = []

    files = config.get_cloud_config_value('files',
                                          vm_,
                                          __opts__,
                                          search_global=False)
    if files:
        kwargs['files'] = {}
        for src_path in files:
            with salt.utils.fopen(files[src_path], 'r') as fp_:
                kwargs['files'][src_path] = fp_.read()
    userdata_file = config.get_cloud_config_value('userdata_file',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False)

    if userdata_file is not None:
        with salt.utils.fopen(userdata_file, 'r') as fp:
            kwargs['ex_userdata'] = fp.read()

    salt.utils.cloud.fire_event('event',
                                'requesting instance',
                                'salt/cloud/{0}/requesting'.format(
                                    vm_['name']), {
                                        'kwargs': {
                                            'name': kwargs['name'],
                                            'image': kwargs['image_id'],
                                            'size': kwargs['flavor_id']
                                        }
                                    },
                                transport=__opts__['transport'])

    try:
        data = conn.boot(**kwargs)
    except Exception as exc:
        log.error(
            'Error creating {0} on Nova\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(vm_['name'], exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    def __query_node_data(vm_, data, floating):
        try:
            nodelist = list_nodes_full()
            log.debug('Loaded node data for {0}:\n{1}'.format(
                vm_['name'], pprint.pformat(nodelist[vm_['name']].__dict__)))
        except Exception as err:
            log.error(
                'Failed to get nodes list: {0}'.format(err),
                # Show the traceback if the debug logging level is enabled
                exc_info=log.isEnabledFor(logging.DEBUG))
            # Trigger a failure in the wait for IP function
            return False

        running = nodelist[vm_['name']].state == 'ACTIVE'
        if not running:
            # Still not running, trigger another iteration
            return

        if rackconnect(vm_) is True:
            extra = nodelist[vm_['name']].get('extra', {})
            rc_status = extra.get('metadata',
                                  {}).get('rackconnect_automation_status', '')
            access_ip = extra.get('access_ip', '')

            if rc_status != 'DEPLOYED':
                log.debug('Waiting for Rackconnect automation to complete')
                return

        if managedcloud(vm_) is True:
            extra = conn.server_show_libcloud(nodelist[vm_['name']].id).extra
            mc_status = extra.get('metadata',
                                  {}).get('rax_service_level_automation', '')

            if mc_status != 'Complete':
                log.debug('Waiting for managed cloud automation to complete')
                return

        if floating:
            try:
                name = data.name
                ip = floating[0].ip_address
                conn.ex_attach_floating_ip_to_node(data, ip)
                log.info(('Attaching floating IP "{0}"'
                          ' to node "{1}"').format(ip, name))
            except Exception as e:
                # Note(pabelanger): Because we loop, we only want to attach the
                # floating IP address one. So, expect failures if the IP is
                # already attached.
                pass

        result = []
        private = nodelist[vm_['name']].private_ips
        public = nodelist[vm_['name']].public_ips
        if private and not public:
            log.warn('Private IPs returned, but not public... Checking for '
                     'misidentified IPs')
            for private_ip in private:
                private_ip = preferred_ip(vm_, [private_ip])
                if salt.utils.cloud.is_public_ip(private_ip):
                    log.warn('{0} is a public IP'.format(private_ip))
                    data.public_ips.append(private_ip)
                    log.warn(('Public IP address was not ready when we last'
                              ' checked.  Appending public IP address now.'))
                    public = data.public_ips
                else:
                    log.warn('{0} is a private IP'.format(private_ip))
                    ignore_ip = ignore_cidr(vm_, private_ip)
                    if private_ip not in data.private_ips and not ignore_ip:
                        result.append(private_ip)

        if rackconnect(vm_) is True:
            if ssh_interface(vm_) != 'private_ips':
                data.public_ips = access_ip
                return data

        if result:
            log.debug('result = {0}'.format(result))
            data.private_ips = result
            if ssh_interface(vm_) == 'private_ips':
                return data

        if public:
            data.public_ips = public
            if ssh_interface(vm_) != 'private_ips':
                return data

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

    log.debug('VM is now running')

    if ssh_interface(vm_) == 'private_ips':
        ip_address = preferred_ip(vm_, data.private_ips)
    elif rackconnect(vm_) is True and ssh_interface(vm_) != 'private_ips':
        ip_address = data.public_ips
    else:
        ip_address = preferred_ip(vm_, data.public_ips)
    log.debug('Using IP address {0}'.format(ip_address))

    if not ip_address:
        raise SaltCloudSystemExit('A valid IP address was not found')

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

    deploy_kwargs = {
        'opts':
        __opts__,
        'host':
        ip_address,
        'name':
        vm_['name'],
        'sock_dir':
        __opts__['sock_dir'],
        'tmp_dir':
        config.get_cloud_config_value('tmp_dir',
                                      vm_,
                                      __opts__,
                                      default='/tmp/.saltcloud'),
        'deploy_command':
        config.get_cloud_config_value(
            'deploy_command',
            vm_,
            __opts__,
            default='/tmp/.saltcloud/deploy.sh',
        ),
        'start_action':
        __opts__['start_action'],
        'parallel':
        __opts__['parallel'],
        'minion_pem':
        vm_['priv_key'],
        'minion_pub':
        vm_['pub_key'],
        'keep_tmp':
        __opts__['keep_tmp'],
        'preseed_minion_keys':
        vm_.get('preseed_minion_keys', None),
        'sudo':
        config.get_cloud_config_value('sudo',
                                      vm_,
                                      __opts__,
                                      default=(ssh_username != 'root')),
        'sudo_password':
        config.get_cloud_config_value('sudo_password',
                                      vm_,
                                      __opts__,
                                      default=None),
        'tty':
        config.get_cloud_config_value('tty', vm_, __opts__, default=False),
        'display_ssh_output':
        config.get_cloud_config_value('display_ssh_output',
                                      vm_,
                                      __opts__,
                                      default=True),
        'script_args':
        config.get_cloud_config_value('script_args', vm_, __opts__),
        'script_env':
        config.get_cloud_config_value('script_env', vm_, __opts__),
        'minion_conf':
        salt.utils.cloud.minion_config(__opts__, vm_)
    }

    if ssh_username != 'root':
        deploy_kwargs['username'] = ssh_username
        deploy_kwargs['tty'] = True

    log.debug('Using {0} as SSH username'.format(ssh_username))

    if key_filename is not None:
        deploy_kwargs['key_filename'] = key_filename
        log.debug('Using {0} as SSH key file'.format(key_filename))
    elif 'password' in data.extra:
        deploy_kwargs['password'] = data.extra['password']
        log.debug('Logging into SSH using password')

    ret = {}
    if config.get_cloud_config_value('deploy', vm_, __opts__) is True:
        deploy_script = script(vm_)
        deploy_kwargs['script'] = deploy_script.script

        # Deploy salt-master files, if necessary
        if 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 = salt.utils.cloud.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'] = config.get_cloud_config_value(
            'make_minion', vm_, __opts__, default=True)

        # Check for Windows install params
        win_installer = config.get_cloud_config_value('win_installer', vm_,
                                                      __opts__)
        if win_installer:
            deploy_kwargs['win_installer'] = win_installer
            minion = salt.utils.cloud.minion_config(__opts__, vm_)
            deploy_kwargs['master'] = minion['master']
            deploy_kwargs['username'] = config.get_cloud_config_value(
                'win_username', vm_, __opts__, default='Administrator')
            deploy_kwargs['password'] = config.get_cloud_config_value(
                'win_password', vm_, __opts__, default='')

        # Store what was used to the deploy the VM
        event_kwargs = copy.deepcopy(deploy_kwargs)
        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

        salt.utils.cloud.fire_event('event',
                                    'executing deploy script',
                                    'salt/cloud/{0}/deploying'.format(
                                        vm_['name']), {'kwargs': event_kwargs},
                                    transport=__opts__['transport'])

        deployed = False
        if win_installer:
            deployed = salt.utils.cloud.deploy_windows(**deploy_kwargs)
        else:
            deployed = salt.utils.cloud.deploy_script(**deploy_kwargs)

        if deployed:
            log.info('Salt installed on {0}'.format(vm_['name']))
        else:
            log.error('Failed to deploy and start Salt on Cloud VM {0}'.format(
                vm_['name']))

    ret.update(data.__dict__)

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

    log.info('Created Cloud VM {0[name]!r}'.format(vm_))
    log.debug('{0[name]!r} VM creation details:\n{1}'.format(
        vm_, pprint.pformat(data)))

    salt.utils.cloud.fire_event('event',
                                'created instance',
                                'salt/cloud/{0}/created'.format(vm_['name']), {
                                    'name': vm_['name'],
                                    'profile': vm_['profile'],
                                    'provider': vm_['provider'],
                                },
                                transport=__opts__['transport'])

    return ret
Esempio n. 17
0
def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
    key_filename = config.get_cloud_config_value('ssh_key_file',
                                                 vm_,
                                                 __opts__,
                                                 search_global=False,
                                                 default=None)
    if key_filename is not None:
        key_filename = os.path.expanduser(key_filename)
        if not os.path.isfile(key_filename):
            raise SaltCloudConfigError(
                'The defined ssh_key_file {0!r} does not exist'.format(
                    key_filename))

    if deploy is True and key_filename is None and \
            salt.utils.which('sshpass') is None:
        raise SaltCloudSystemExit(
            'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
            'is not set and \'sshpass\' binary is not present on the '
            'system for the password.')

    salt.utils.cloud.fire_event('event',
                                'starting create',
                                'salt/cloud/{0}/creating'.format(vm_['name']),
                                {
                                    'name': vm_['name'],
                                    'profile': vm_['profile'],
                                    'provider': vm_['provider'],
                                },
                                transport=__opts__['transport'])

    log.info('Creating Cloud VM {0}'.format(vm_['name']))
    salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = {'name': vm_['name']}

    try:
        kwargs['image'] = get_image(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find image {1}: {2}\n'.format(vm_['name'], vm_['image'],
                                                     exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    try:
        kwargs['size'] = get_size(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find size {1}: {2}\n'.format(vm_['name'], vm_['size'],
                                                    exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    kwargs['ex_keyname'] = config.get_cloud_config_value('ssh_key_name',
                                                         vm_,
                                                         __opts__,
                                                         search_global=False)

    security_groups = config.get_cloud_config_value('security_groups',
                                                    vm_,
                                                    __opts__,
                                                    search_global=False)
    if security_groups is not None:
        vm_groups = security_groups.split(',')
        avail_groups = conn.ex_list_security_groups()
        group_list = []

        for vmg in vm_groups:
            if vmg in [ag.name for ag in avail_groups]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg))

        kwargs['ex_security_groups'] = [
            g for g in avail_groups if g.name in group_list
        ]

    networks = config.get_cloud_config_value('networks',
                                             vm_,
                                             __opts__,
                                             search_global=False)

    floating = []

    if HAS014:
        if networks is not None:
            for net in networks:
                if 'fixed' in net:
                    kwargs['networks'] = [
                        OpenStackNetwork(n, None, None, None)
                        for n in net['fixed']
                    ]
                elif 'floating' in net:
                    pool = OpenStack_1_1_FloatingIpPool(
                        net['floating'], conn.connection)
                    for idx in pool.list_floating_ips():
                        if idx.node_id is None:
                            floating.append(idx)
                    if not floating:
                        # Note(pabelanger): We have no available floating IPs.
                        # For now, we raise an exception and exit.
                        # A future enhancement might be to allow salt-cloud
                        # to dynamically allocate new address but that might
                        raise SaltCloudSystemExit(
                            'Floating pool {0!r} does not have any more '
                            'please create some more or use a different '
                            'pool.'.format(net['floating']))
        # otherwise, attempt to obtain list without specifying pool
        # this is the same as 'nova floating-ip-list'
        elif ssh_interface(vm_) != 'private_ips':
            try:
                # This try/except is here because it appears some
                # *cough* Rackspace *cough*
                # OpenStack providers return a 404 Not Found for the
                # floating ip pool URL if there are no pools setup
                pool = OpenStack_1_1_FloatingIpPool('', conn.connection)
                for idx in pool.list_floating_ips():
                    if idx.node_id is None:
                        floating.append(idx)
                if not floating:
                    # Note(pabelanger): We have no available floating IPs.
                    # For now, we raise an exception and exit.
                    # A future enhancement might be to allow salt-cloud to
                    # dynamically allocate new address but that might be
                    # tricky to manage.
                    raise SaltCloudSystemExit(
                        'There are no more floating IP addresses '
                        'available, please create some more')
            except Exception as e:
                if str(e).startswith('404'):
                    pass
                else:
                    raise

    files = config.get_cloud_config_value('files',
                                          vm_,
                                          __opts__,
                                          search_global=False)
    if files:
        kwargs['ex_files'] = {}
        for src_path in files:
            with salt.utils.fopen(files[src_path], 'r') as fp_:
                kwargs['ex_files'][src_path] = fp_.read()

    userdata_file = config.get_cloud_config_value('userdata_file',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False)

    if userdata_file is not None:
        with salt.utils.fopen(userdata_file, 'r') as fp:
            kwargs['ex_userdata'] = fp.read()

    salt.utils.cloud.fire_event('event',
                                'requesting instance',
                                'salt/cloud/{0}/requesting'.format(
                                    vm_['name']), {
                                        'kwargs': {
                                            'name': kwargs['name'],
                                            'image': kwargs['image'].name,
                                            'size': kwargs['size'].name,
                                            'profile': vm_['profile']
                                        }
                                    },
                                transport=__opts__['transport'])

    default_profile = {}
    if 'profile' in vm_ and vm_['profile'] is not None:
        default_profile = {'profile': vm_['profile']}

    kwargs['ex_metadata'] = config.get_cloud_config_value(
        'metadata',
        vm_,
        __opts__,
        default=default_profile,
        search_global=False)
    if not isinstance(kwargs['ex_metadata'], dict):
        raise SaltCloudConfigError('\'metadata\' should be a dict.')

    try:
        data = conn.create_node(**kwargs)
    except Exception as exc:
        log.error(
            'Error creating {0} on OpenStack\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(vm_['name'], exc),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG))
        return False

    def __query_node_data(vm_, data, floating):
        try:
            nodelist = list_nodes_full()
            log.debug('Loaded node data for {0}:\n{1}'.format(
                vm_['name'], pprint.pformat(nodelist[vm_['name']])))
        except Exception as err:
            log.error(
                'Failed to get nodes list: {0}'.format(err),
                # Show the traceback if the debug logging level is enabled
                exc_info=log.isEnabledFor(logging.DEBUG))
            # Trigger a failure in the wait for IP function
            return False

        running = nodelist[vm_['name']]['state'] == NodeState.RUNNING
        if not running:
            # Still not running, trigger another iteration
            return

        if rackconnect(vm_) is True:
            check_libcloud_version((0, 14, 0), why='rackconnect: True')
            extra = nodelist[vm_['name']].get('extra')
            rc_status = extra.get('metadata',
                                  {}).get('rackconnect_automation_status', '')
            access_ip = extra.get('access_ip', '')

            if rc_status != 'DEPLOYED':
                log.debug('Waiting for Rackconnect automation to complete')
                return

        if managedcloud(vm_) is True:
            extra = nodelist[vm_['name']].get('extra')
            mc_status = extra.get('metadata',
                                  {}).get('rax_service_level_automation', '')

            if mc_status != 'Complete':
                log.debug('Waiting for managed cloud automation to complete')
                return

        if floating:
            try:
                name = data.name
                ip = floating[0].ip_address
                conn.ex_attach_floating_ip_to_node(data, ip)
                log.info('Attaching floating IP {0!r} to node {1!r}'.format(
                    ip, name))
            except Exception:
                # Note(pabelanger): Because we loop, we only want to attach the
                # floating IP address one. So, expect failures if the IP is
                # already attached.
                pass

        result = []
        private = nodelist[vm_['name']]['private_ips']
        public = nodelist[vm_['name']]['public_ips']
        if private and not public:
            log.warn('Private IPs returned, but not public... Checking for '
                     'misidentified IPs')
            for private_ip in private:
                private_ip = preferred_ip(vm_, [private_ip])
                if salt.utils.cloud.is_public_ip(private_ip):
                    log.warn('{0} is a public IP'.format(private_ip))
                    data.public_ips.append(private_ip)
                    log.warn(
                        'Public IP address was not ready when we last checked.'
                        ' Appending public IP address now.')
                    public = data.public_ips
                else:
                    log.warn('{0} is a private IP'.format(private_ip))
                    ignore_ip = ignore_cidr(vm_, private_ip)
                    if private_ip not in data.private_ips and not ignore_ip:
                        result.append(private_ip)

        if rackconnect(vm_) is True:
            if ssh_interface(vm_) != 'private_ips':
                data.public_ips = access_ip
                return data

        # populate return data with private_ips
        # when ssh_interface is set to private_ips and public_ips exist
        if not result and ssh_interface(vm_) == 'private_ips':
            for private_ip in private:
                ignore_ip = ignore_cidr(vm_, private_ip)
                if private_ip not in data.private_ips and not ignore_ip:
                    result.append(private_ip)

        if result:
            log.debug('result = {0}'.format(result))
            data.private_ips = result
            if ssh_interface(vm_) == 'private_ips':
                return data

        if public:
            data.public_ips = public
            if ssh_interface(vm_) != 'private_ips':
                return data

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

    log.debug('VM is now running')

    if ssh_interface(vm_) == 'private_ips':
        ip_address = preferred_ip(vm_, data.private_ips)
    elif rackconnect(vm_) is True and ssh_interface(vm_) != 'private_ips':
        ip_address = data.public_ips
    else:
        ip_address = preferred_ip(vm_, data.public_ips)
    log.debug('Using IP address {0}'.format(ip_address))

    if not ip_address:
        raise SaltCloudSystemExit('A valid IP address was not found')

    ssh_username = config.get_cloud_config_value('ssh_username',
                                                 vm_,
                                                 __opts__,
                                                 default='root')
    deploy_kwargs = {
        'opts':
        __opts__,
        'host':
        ip_address,
        'name':
        vm_['name'],
        'sock_dir':
        __opts__['sock_dir'],
        'tmp_dir':
        config.get_cloud_config_value('tmp_dir',
                                      vm_,
                                      __opts__,
                                      default='/tmp/.saltcloud'),
        'deploy_command':
        config.get_cloud_config_value(
            'deploy_command',
            vm_,
            __opts__,
            default='/tmp/.saltcloud/deploy.sh',
        ),
        'start_action':
        __opts__['start_action'],
        'parallel':
        __opts__['parallel'],
        'minion_pem':
        vm_['priv_key'],
        'minion_pub':
        vm_['pub_key'],
        'keep_tmp':
        __opts__['keep_tmp'],
        'preseed_minion_keys':
        vm_.get('preseed_minion_keys', None),
        'sudo':
        config.get_cloud_config_value('sudo',
                                      vm_,
                                      __opts__,
                                      default=(ssh_username != 'root')),
        'sudo_password':
        config.get_cloud_config_value('sudo_password',
                                      vm_,
                                      __opts__,
                                      default=None),
        'display_ssh_output':
        config.get_cloud_config_value('display_ssh_output',
                                      vm_,
                                      __opts__,
                                      default=True),
        'script_args':
        config.get_cloud_config_value('script_args', vm_, __opts__),
        'script_env':
        config.get_cloud_config_value('script_env', vm_, __opts__),
        'minion_conf':
        salt.utils.cloud.minion_config(__opts__, vm_)
    }

    if ssh_username != 'root':
        deploy_kwargs['username'] = ssh_username
        deploy_kwargs['tty'] = True

    log.debug('Using {0} as SSH username'.format(ssh_username))

    if key_filename is not None:
        deploy_kwargs['key_filename'] = key_filename
        log.debug('Using {0} as SSH key file'.format(key_filename))
    elif hasattr(data, 'extra') and 'password' in data.extra:
        deploy_kwargs['password'] = data.extra['password']
        log.debug('Logging into SSH using password')

    ret = {}
    sudo = config.get_cloud_config_value('sudo',
                                         vm_,
                                         __opts__,
                                         default=(ssh_username != 'root'))
    if sudo is not None:
        deploy_kwargs['sudo'] = sudo
        log.debug('Running root commands using sudo')

    if config.get_cloud_config_value('deploy', vm_, __opts__) is True:
        deploy_script = script(vm_)
        deploy_kwargs['script'] = deploy_script.script

        # Deploy salt-master files, if necessary
        if 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 = salt.utils.cloud.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'] = config.get_cloud_config_value(
            'make_minion', vm_, __opts__, default=True)

        # Check for Windows install params
        win_installer = config.get_cloud_config_value('win_installer', vm_,
                                                      __opts__)
        if win_installer:
            deploy_kwargs['win_installer'] = win_installer
            minion = salt.utils.cloud.minion_config(__opts__, vm_)
            deploy_kwargs['master'] = minion['master']
            deploy_kwargs['username'] = config.get_cloud_config_value(
                'win_username', vm_, __opts__, default='Administrator')
            deploy_kwargs['password'] = config.get_cloud_config_value(
                'win_password', vm_, __opts__, default='')

        # Store what was used to the deploy the VM
        event_kwargs = copy.deepcopy(deploy_kwargs)
        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

        salt.utils.cloud.fire_event('event',
                                    'executing deploy script',
                                    'salt/cloud/{0}/deploying'.format(
                                        vm_['name']), {'kwargs': event_kwargs},
                                    transport=__opts__['transport'])

        deployed = False
        if win_installer:
            deployed = salt.utils.cloud.deploy_windows(**deploy_kwargs)
        else:
            deployed = salt.utils.cloud.deploy_script(**deploy_kwargs)

        if deployed:
            log.info('Salt installed on {0}'.format(vm_['name']))
        else:
            log.error('Failed to deploy and start Salt on Cloud VM {0}'.format(
                vm_['name']))

    ret.update(data.__dict__)

    if hasattr(data, 'extra') and 'password' in data.extra:
        del data.extra['password']

    log.info('Created Cloud VM {0[name]!r}'.format(vm_))
    log.debug('{0[name]!r} VM creation details:\n{1}'.format(
        vm_, pprint.pformat(data.__dict__)))

    salt.utils.cloud.fire_event('event',
                                'created instance',
                                'salt/cloud/{0}/created'.format(vm_['name']), {
                                    'name': vm_['name'],
                                    'profile': vm_['profile'],
                                    'provider': vm_['provider'],
                                },
                                transport=__opts__['transport'])

    return ret
Esempio n. 18
0
def request_instance(vm_=None, call=None):
    '''
    Put together all of the information necessary to request an instance
    through Novaclient and then fire off the request the instance.

    Returns data about the instance
    '''
    if call == 'function':
        # Technically this function may be called other ways too, but it
        # definitely cannot be called with --function.
        raise SaltCloudSystemExit(
            'The request_instance action must be called with -a or --action.')
    log.info('Creating Cloud VM {0}'.format(vm_['name']))
    salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = {'name': vm_['name']}

    try:
        kwargs['image_id'] = get_image(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit('Error creating {0} on OPENSTACK\n\n'
                                  'Could not find image {1}: {2}\n'.format(
                                      vm_['name'], vm_['image'], exc))

    try:
        kwargs['flavor_id'] = get_size(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit('Error creating {0} on OPENSTACK\n\n'
                                  'Could not find size {1}: {2}\n'.format(
                                      vm_['name'], vm_['size'], exc))

    kwargs['key_name'] = config.get_cloud_config_value('ssh_key_name',
                                                       vm_,
                                                       __opts__,
                                                       search_global=False)

    security_groups = config.get_cloud_config_value('security_groups',
                                                    vm_,
                                                    __opts__,
                                                    search_global=False)
    if security_groups is not None:
        vm_groups = security_groups.split(',')
        avail_groups = conn.secgroup_list()
        group_list = []

        for vmg in vm_groups:
            if vmg in [name for name, details in avail_groups.iteritems()]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg))

        kwargs['security_groups'] = group_list

    avz = config.get_cloud_config_value('availability_zone',
                                        vm_,
                                        __opts__,
                                        default=None,
                                        search_global=False)
    if avz is not None:
        kwargs['availability_zone'] = avz

    networks = config.get_cloud_config_value('networks',
                                             vm_,
                                             __opts__,
                                             search_global=False)

    files = config.get_cloud_config_value('files',
                                          vm_,
                                          __opts__,
                                          search_global=False)
    if files:
        kwargs['files'] = {}
        for src_path in files:
            if os.path.exists(files[src_path]):
                with salt.utils.fopen(files[src_path], 'r') as fp_:
                    kwargs['files'][src_path] = fp_.read()
            else:
                kwargs['files'][src_path] = files[src_path]

    userdata_file = config.get_cloud_config_value('userdata_file',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False)

    if userdata_file is not None:
        with salt.utils.fopen(userdata_file, 'r') as fp:
            kwargs['userdata'] = fp.read()

    salt.utils.cloud.fire_event('event',
                                'requesting instance',
                                'salt/cloud/{0}/requesting'.format(
                                    vm_['name']), {
                                        'kwargs': {
                                            'name': kwargs['name'],
                                            'image': kwargs['image_id'],
                                            'size': kwargs['flavor_id']
                                        }
                                    },
                                transport=__opts__['transport'])

    try:
        data = conn.boot(**kwargs)
    except Exception as exc:
        raise SaltCloudSystemExit(
            'Error creating {0} on Nova\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(vm_['name'], exc))
    vm_['password'] = data.extra.get('password', '')

    return data, vm_
Esempio n. 19
0
def request_instance(vm_=None, call=None):
    '''
    Put together all of the information necessary to request an instance on Openstack
    and then fire off the request the instance.

    Returns data about the instance
    '''
    if call == 'function':
        # Technically this function may be called other ways too, but it
        # definitely cannot be called with --function.
        raise SaltCloudSystemExit(
            'The request_instance action must be called with -a or --action.')
    salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = {'name': vm_['name']}

    try:
        kwargs['image'] = get_image(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit('Error creating {0} on OPENSTACK\n\n'
                                  'Could not find image {1}: {2}\n'.format(
                                      vm_['name'], vm_['image'], exc))

    try:
        kwargs['size'] = get_size(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit('Error creating {0} on OPENSTACK\n\n'
                                  'Could not find size {1}: {2}\n'.format(
                                      vm_['name'], vm_['size'], exc))

    # Note: This currently requires libcloud trunk
    avz = config.get_cloud_config_value('availability_zone',
                                        vm_,
                                        __opts__,
                                        default=None,
                                        search_global=False)
    if avz is not None:
        kwargs['ex_availability_zone'] = avz

    kwargs['ex_keyname'] = config.get_cloud_config_value('ssh_key_name',
                                                         vm_,
                                                         __opts__,
                                                         search_global=False)

    security_groups = config.get_cloud_config_value('security_groups',
                                                    vm_,
                                                    __opts__,
                                                    search_global=False)
    if security_groups is not None:
        vm_groups = security_groups.split(',')
        avail_groups = conn.ex_list_security_groups()
        group_list = []

        for vmg in vm_groups:
            if vmg in [ag.name for ag in avail_groups]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg))

        kwargs['ex_security_groups'] = [
            g for g in avail_groups if g.name in group_list
        ]

    networks = config.get_cloud_config_value('networks',
                                             vm_,
                                             __opts__,
                                             search_global=False)

    floating = []

    if HAS014:
        if networks is not None:
            for net in networks:
                if 'fixed' in net:
                    kwargs['networks'] = [
                        OpenStackNetwork(n, None, None, None)
                        for n in net['fixed']
                    ]
                elif 'floating' in net:
                    pool = OpenStack_1_1_FloatingIpPool(
                        net['floating'], conn.connection)
                    for idx in pool.list_floating_ips():
                        if idx.node_id is None:
                            floating.append(idx)
                    if not floating:
                        # Note(pabelanger): We have no available floating IPs.
                        # For now, we raise an exception and exit.
                        # A future enhancement might be to allow salt-cloud
                        # to dynamically allocate new address but that might
                        raise SaltCloudSystemExit(
                            'Floating pool {0!r} does not have any more '
                            'please create some more or use a different '
                            'pool.'.format(net['floating']))
        # otherwise, attempt to obtain list without specifying pool
        # this is the same as 'nova floating-ip-list'
        elif ssh_interface(vm_) != 'private_ips':
            try:
                # This try/except is here because it appears some
                # *cough* Rackspace *cough*
                # OpenStack providers return a 404 Not Found for the
                # floating ip pool URL if there are no pools setup
                pool = OpenStack_1_1_FloatingIpPool('', conn.connection)
                for idx in pool.list_floating_ips():
                    if idx.node_id is None:
                        floating.append(idx)
                if not floating:
                    # Note(pabelanger): We have no available floating IPs.
                    # For now, we raise an exception and exit.
                    # A future enhancement might be to allow salt-cloud to
                    # dynamically allocate new address but that might be
                    # tricky to manage.
                    raise SaltCloudSystemExit(
                        'There are no more floating IP addresses '
                        'available, please create some more')
            except Exception as e:
                if str(e).startswith('404'):
                    pass
                else:
                    raise
    vm_['floating'] = floating

    files = config.get_cloud_config_value('files',
                                          vm_,
                                          __opts__,
                                          search_global=False)
    if files:
        kwargs['ex_files'] = {}
        for src_path in files:
            with salt.utils.fopen(files[src_path], 'r') as fp_:
                kwargs['ex_files'][src_path] = fp_.read()

    userdata_file = config.get_cloud_config_value('userdata_file',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False)

    if userdata_file is not None:
        with salt.utils.fopen(userdata_file, 'r') as fp:
            kwargs['ex_userdata'] = fp.read()

    salt.utils.cloud.fire_event('event',
                                'requesting instance',
                                'salt/cloud/{0}/requesting'.format(
                                    vm_['name']), {
                                        'kwargs': {
                                            'name': kwargs['name'],
                                            'image': kwargs['image'].name,
                                            'size': kwargs['size'].name,
                                            'profile': vm_['profile']
                                        }
                                    },
                                transport=__opts__['transport'])

    default_profile = {}
    if 'profile' in vm_ and vm_['profile'] is not None:
        default_profile = {'profile': vm_['profile']}

    kwargs['ex_metadata'] = config.get_cloud_config_value(
        'metadata',
        vm_,
        __opts__,
        default=default_profile,
        search_global=False)
    if not isinstance(kwargs['ex_metadata'], dict):
        raise SaltCloudConfigError('\'metadata\' should be a dict.')

    try:
        data = conn.create_node(**kwargs)
    except Exception as exc:
        raise SaltCloudSystemExit(
            'Error creating {0} on OpenStack\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(vm_['name'], exc))

    vm_['password'] = data.extra.get('password', None)
    return data, vm_
Esempio n. 20
0
def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    deploy = config.get_config_value('deploy', vm_, __opts__)
    key_filename = config.get_config_value(
        'ssh_key_file', 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_key_file {0!r} does not exist'.format(
                key_filename
            )
        )

    if deploy is True and key_filename is None and \
            salt.utils.which('sshpass') is None:
        raise SaltCloudSystemExit(
            'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
            'is not set and \'sshpass\' binary is not present on the '
            'system for the password.'
        )

    salt.cloud.utils.fire_event(
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        {
            'name': vm_['name'],
            'profile': vm_['profile'],
            'provider': vm_['provider'],
        },
    )

    log.info('Creating Cloud VM {0}'.format(vm_['name']))
    salt.cloud.utils.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = {
        'name': vm_['name']
    }

    try:
        kwargs['image'] = get_image(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find image {1}: {2}\n'.format(
                vm_['name'], vm_['image'], exc
            ),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG)
        )
        return False

    try:
        kwargs['size'] = get_size(conn, vm_)
    except Exception as exc:
        log.error(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find size {1}: {2}\n'.format(
                vm_['name'], vm_['size'], exc
            ),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG)
        )
        return False

    kwargs['ex_keyname'] = config.get_config_value(
        'ssh_key_name', vm_, __opts__, search_global=False
    )

    security_groups = config.get_config_value(
        'security_groups', vm_, __opts__, search_global=False
    )
    if security_groups is not None:
        vm_groups = security_groups.split(',')
        avail_groups = conn.ex_list_security_groups()
        group_list = []

        for vmg in vm_groups:
            if vmg in [ag.name for ag in avail_groups]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg)
                )

        kwargs['ex_security_groups'] = [
            g for g in avail_groups if g.name in group_list
        ]

    networks = config.get_config_value(
        'networks', vm_, __opts__, search_global=False
    )

    floating = []

    if HAS014 and networks is not None:
        for net in networks:
            if 'fixed' in net:
                kwargs['networks'] = [
                    OpenStackNetwork(n, None, None, None) for n in net['fixed']
                ]
            elif 'floating' in net:
                pool = OpenStack_1_1_FloatingIpPool(
                    net['floating'], conn.connection
                )
                for idx in pool.list_floating_ips():
                    if idx.node_id is None:
                        floating.append(idx)
                if not floating:
                    # Note(pabelanger): We have no available floating IPs. For
                    # now, we raise an execption and exit. A future enhancement
                    # might be to allow salt-cloud to dynamically allociate new
                    # address but that might be tricky to manage.
                    raise SaltCloudSystemExit(
                        "Floating pool '%s' has not more address available, "
                        "please create some more or use a different pool." %
                        net['floating']
                    )

    files = config.get_config_value(
        'files', vm_, __opts__, search_global=False
    )
    if files:
        kwargs['ex_files'] = {}
        for src_path in files:
            with salt.utils.fopen(files[src_path], 'r') as fp_:
                kwargs['ex_files'][src_path] = fp_.read()

    userdata_file = config.get_config_value(
        'userdata_file', vm_, __opts__, search_global=False
    )

    if userdata_file is not None:
        with salt.utils.fopen(userdata_file, 'r') as fp:
            kwargs['ex_userdata'] = fp.read()

    salt.cloud.utils.fire_event(
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        {'kwargs': {'name': kwargs['name'],
                    'image': kwargs['image'].name,
                    'size': kwargs['size'].name}},
    )

    kwargs['ex_metadata'] = config.get_config_value(
        'metadata', vm_, __opts__, default={}, search_global=False
    )
    if not isinstance(kwargs['ex_metadata'], dict):
        raise SaltCloudConfigError(
                '\'metadata\' should be a dict.'
        )

    try:
        data = conn.create_node(**kwargs)
    except Exception as exc:
        log.error(
            'Error creating {0} on OpenStack\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(
                vm_['name'], exc
            ),
            # Show the traceback if the debug logging level is enabled
            exc_info=log.isEnabledFor(logging.DEBUG)
        )
        return False

    def __query_node_data(vm_, data, floating):
        try:
            nodelist = list_nodes()
            log.debug(
                'Loaded node data for {0}:\n{1}'.format(
                    vm_['name'],
                    pprint.pformat(
                        nodelist[vm_['name']]
                    )
                )
            )
        except Exception, err:
            log.error(
                'Failed to get nodes list: {0}'.format(
                    err
                ),
                # Show the traceback if the debug logging level is enabled
                exc_info=log.isEnabledFor(logging.DEBUG)
            )
            # Trigger a failure in the wait for IP function
            return False

        running = nodelist[vm_['name']]['state'] == node_state(
            NodeState.RUNNING
        )
        if not running:
            # Still not running, trigger another iteration
            return

        if rackconnect(vm_) is True:
            extra = nodelist[vm_['name']].get('extra')
            rc_status = extra.get('metadata').get('rackconnect_automation_status')
            access_ip = extra.get('access_ip')

            if rc_status != 'DEPLOYED':
                log.debug('Waiting for Rackconnect automation to complete')
                return

        if managedcloud(vm_) is True:
            extra = nodelist[vm_['name']].get('extra')
            mc_status = extra.get('metadata').get('rax_service_level_automation')

            if mc_status != 'Complete':
                log.debug('Waiting for managed cloud automation to complete')
                return

        if floating:
            try:
                name = data.name
                ip = floating[0].ip_address
                conn.ex_attach_floating_ip_to_node(data, ip)
                log.info(
                    'Attaching floating IP "{0}" to node "{1}"'.format(ip, name)
                )
            except Exception:
                # Note(pabelanger): Because we loop, we only want to attach the
                # floating IP address one. So, expect failures if the IP is
                # already attached.
                pass

        result = []
        private = nodelist[vm_['name']]['private_ips']
        public = nodelist[vm_['name']]['public_ips']
        if private and not public:
            log.warn(
                'Private IPs returned, but not public... Checking for '
                'misidentified IPs'
            )
            for private_ip in private:
                private_ip = preferred_ip(vm_, [private_ip])
                if salt.cloud.utils.is_public_ip(private_ip):
                    log.warn('{0} is a public IP'.format(private_ip))
                    data.public_ips.append(private_ip)
                    log.warn(
                        'Public IP address was not ready when we last checked.  Appending public IP address now.'
                    )
                    public = data.public_ips
                else:
                    log.warn('{0} is a private IP'.format(private_ip))
                    ignore_ip = ignore_cidr(vm_, private_ip)
                    if private_ip not in data.private_ips and not ignore_ip:
                        result.append(private_ip)

        if rackconnect(vm_) is True:
            if ssh_interface(vm_) != 'private_ips':
                data.public_ips = access_ip
                return data

        if result:
            log.debug('result = {0}'.format(result))
            data.private_ips = result
            if ssh_interface(vm_) == 'private_ips':
                return data

        if public:
            data.public_ips = public
            if ssh_interface(vm_) != 'private_ips':
                return data