Creates a virtual machine from the given VM information

    This is what is used to request a virtual machine to be created by the
    cloud provider, wait for it to become available, and then (optionally) log
    in and install Salt on it.

    Events fired:

    This function fires the event ``salt/cloud/vm_name/creating``, with the
    payload containing the names of the VM, profile, and provider.

    @param vm_info

    .. code-block:: text

        {
            name: <str>
            profile: <dict>
            driver: <provider>:<profile>
            clonefrom: <vm_name>
            clonemode: <mode> (default: state, choices: state, child, all)
        }

    @type vm_info dict
    @return dict of resulting vm. !!!Passwords can and should be included!!!

def create(vm_info):
    '''
    Creates a virtual machine from the given VM information

    This is what is used to request a virtual machine to be created by the
    cloud provider, wait for it to become available, and then (optionally) log
    in and install Salt on it.

    Events fired:

    This function fires the event ``salt/cloud/vm_name/creating``, with the
    payload containing the names of the VM, profile, and provider.

    @param vm_info

    .. code-block:: text

        {
            name: <str>
            profile: <dict>
            driver: <provider>:<profile>
            clonefrom: <vm_name>
            clonemode: <mode> (default: state, choices: state, child, all)
        }

    @type vm_info dict
    @return dict of resulting vm. !!!Passwords can and should be included!!!
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_info['profile'] and config.is_profile_configured(
            __opts__,
                __active_provider_name__ or 'virtualbox',
            vm_info['profile']
        ) is False:
            return False
    except AttributeError:
        pass

    vm_name = vm_info["name"]
    deploy = config.get_cloud_config_value(
        'deploy', vm_info, __opts__, search_global=False, default=True
    )
    wait_for_ip_timeout = config.get_cloud_config_value(
        'wait_for_ip_timeout', vm_info, __opts__, default=60
    )
    boot_timeout = config.get_cloud_config_value(
        'boot_timeout', vm_info, __opts__, default=60 * 1000
    )
    power = config.get_cloud_config_value(
        'power_on', vm_info, __opts__, default=False
    )
    key_filename = config.get_cloud_config_value(
        'private_key', vm_info, __opts__, search_global=False, default=None
    )
    clone_mode = map_clonemode(vm_info)
    wait_for_pattern = vm_info['waitforpattern'] if 'waitforpattern' in vm_info.keys() else None
    interface_index = vm_info['interfaceindex'] if 'interfaceindex' in vm_info.keys() else 0

    log.debug("Going to fire event: starting create")
    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_info['name']),
        args=__utils__['cloud.filter_event']('creating', vm_info, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    # to create the virtual machine.
    request_kwargs = {
        'name': vm_info['name'],
        'clone_from': vm_info['clonefrom'],
        'clone_mode': clone_mode
    }

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_info['name']),
        args=__utils__['cloud.filter_event']('requesting', request_kwargs, list(request_kwargs)),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )
    vm_result = vb_clone_vm(**request_kwargs)

    # Booting and deploying if needed
    if power:
        vb_start_vm(vm_name, timeout=boot_timeout)
        ips = vb_wait_for_network_address(wait_for_ip_timeout, machine_name=vm_name, wait_for_pattern=wait_for_pattern)

        if ips:
            ip = ips[interface_index]
            log.info("[ %s ] IPv4 is: %s", vm_name, ip)
            # ssh or smb using ip and install salt only if deploy is True
            if deploy:
                vm_info['key_filename'] = key_filename
                vm_info['ssh_host'] = ip

                res = __utils__['cloud.bootstrap'](vm_info, __opts__)
                vm_result.update(res)

    __utils__['cloud.fire_event'](
        'event',
        'created machine',
        'salt/cloud/{0}/created'.format(vm_info['name']),
        args=__utils__['cloud.filter_event']('created', vm_result, list(vm_result)),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    # Passwords should be included in this object!!
    return vm_result