docs: def create(vm_):
      '''
      Create a single VM from a data dict
      '''
      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