r'''
    Create a single VM from a data dict.

    vm\_
        The dictionary use to create a VM.

    Optional vm\_ dict options for overwriting template:

    region_id
        Optional - OpenNebula Zone ID

    memory
        Optional - In MB

    cpu
        Optional - Percent of host CPU to allocate

    vcpu
        Optional - Amount of vCPUs to allocate

     CLI Example:

     .. code-block:: bash

         salt-cloud -p my-opennebula-profile vm_name

        salt-cloud -p my-opennebula-profile vm_name memory=16384 cpu=2.5 vcpu=16

def create(vm_):
    r'''
    Create a single VM from a data dict.

    vm\_
        The dictionary use to create a VM.

    Optional vm\_ dict options for overwriting template:

    region_id
        Optional - OpenNebula Zone ID

    memory
        Optional - In MB

    cpu
        Optional - Percent of host CPU to allocate

    vcpu
        Optional - Amount of vCPUs to allocate

     CLI Example:

     .. code-block:: bash

         salt-cloud -p my-opennebula-profile vm_name

        salt-cloud -p my-opennebula-profile vm_name memory=16384 cpu=2.5 vcpu=16

    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'opennebula',
                                                           vm_['profile']) 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'])
    kwargs = {
        'name': vm_['name'],
        'template_id': get_template(vm_),
        'region_id': get_location(vm_),
    }
    if 'template' in vm_:
        kwargs['image_id'] = get_template_id({'name': vm_['template']})

    private_networking = config.get_cloud_config_value(
        'private_networking', vm_, __opts__, search_global=False, default=None
    )
    kwargs['private_networking'] = 'true' if private_networking else 'false'

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

    template = []
    if kwargs.get('region_id'):
        template.append('SCHED_REQUIREMENTS="ID={0}"'.format(kwargs.get('region_id')))
    if vm_.get('memory'):
        template.append('MEMORY={0}'.format(vm_.get('memory')))
    if vm_.get('cpu'):
        template.append('CPU={0}'.format(vm_.get('cpu')))
    if vm_.get('vcpu'):
        template.append('VCPU={0}'.format(vm_.get('vcpu')))
    if vm_.get('disk'):
        get_disks = vm_.get('disk')
        template_name = vm_['image']
        for disk in get_disks:
            template.append(_get_device_template(disk, get_disks[disk],
                                 template=template_name))
        if 'CLONE' not in six.text_type(template):
            raise SaltCloudSystemExit(
                'Missing an image disk to clone. Must define a clone disk alongside all other disk definitions.'
            )

    template_args = "\n".join(template)

    try:
        server, user, password = _get_xml_rpc()
        auth = ':'.join([user, password])
        cret = server.one.template.instantiate(auth,
                                        int(kwargs['template_id']),
                                        kwargs['name'],
                                        False,
                                        template_args)
        if not cret[0]:
            log.error(
                'Error creating %s on OpenNebula\n\n'
                'The following error was returned when trying to '
                'instantiate the template: %s',
                vm_['name'], cret[1],
                # Show the traceback if the debug logging level is enabled
                exc_info_on_loglevel=logging.DEBUG
            )
            return False
    except Exception as exc:
        log.error(
            'Error creating %s on OpenNebula\n\n'
            'The following exception was thrown when trying to '
            'run the initial deployment: %s',
            vm_['name'], exc,
            # Show the traceback if the debug logging level is enabled
            exc_info_on_loglevel=logging.DEBUG
        )
        return False

    fqdn = vm_.get('fqdn_base')
    if fqdn is not None:
        fqdn = '{0}.{1}'.format(vm_['name'], fqdn)

    def __query_node_data(vm_name):
        node_data = show_instance(vm_name, call='action')
        if not node_data:
            # Trigger an error in the wait_for_ip function
            return False
        if node_data['state'] == '7':
            return False
        if node_data['lcm_state'] == '3':
            return node_data

    try:
        data = __utils__['cloud.wait_for_ip'](
            __query_node_data,
            update_args=(vm_['name'],),
            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=2),
        )
    except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
        try:
            # It might be already up, let's destroy it!
            destroy(vm_['name'])
        except SaltCloudSystemExit:
            pass
        finally:
            raise SaltCloudSystemExit(six.text_type(exc))

    key_filename = config.get_cloud_config_value(
        'private_key', vm_, __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
            )
        )

    if fqdn:
        vm_['ssh_host'] = fqdn
        private_ip = '0.0.0.0'
    else:
        try:
            private_ip = data['private_ips'][0]
        except KeyError:
            try:
                private_ip = data['template']['nic']['ip']
            except KeyError:
                # if IPv6 is used try this as last resort
                # OpenNebula does not yet show ULA address here so take global
                private_ip = data['template']['nic']['ip6_global']
            vm_['ssh_host'] = private_ip

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

    vm_['username'] = ssh_username
    vm_['key_filename'] = key_filename

    ret = __utils__['cloud.bootstrap'](vm_, __opts__)

    ret['id'] = data['id']
    ret['image'] = vm_['image']
    ret['name'] = vm_['name']
    ret['size'] = data['template']['memory']
    ret['state'] = data['state']
    ret['private_ips'] = private_ip
    ret['public_ips'] = []

    log.info('Created Cloud VM \'%s\'', vm_['name'])
    log.debug(
        '\'%s\' VM creation details:\n%s',
        vm_['name'], pprint.pformat(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'],
    )

    return ret