docs: def create_virtual(hostname, username, password, name, destination,
                     pool=None,
                     address_status=None,
                     auto_lasthop=None,
                     bwc_policy=None,
                     cmp_enabled=None,
                     connection_limit=None,
                     dhcp_relay=None,
                     description=None,
                     fallback_persistence=None,
                     flow_eviction_policy=None,
                     gtm_score=None,
                     ip_forward=None,
                     ip_protocol=None,
                     internal=None,
                     twelve_forward=None,
                     last_hop_pool=None,
                     mask=None,
                     mirror=None,
                     nat64=None,
                     persist=None,
                     profiles=None,
                     policies=None,
                     rate_class=None,
                     rate_limit=None,
                     rate_limit_mode=None,
                     rate_limit_dst=None,
                     rate_limit_src=None,
                     rules=None,
                     related_rules=None,
                     reject=None,
                     source=None,
                     source_address_translation=None,
                     source_port=None,
                     state=None,
                     traffic_classes=None,
                     translate_address=None,
                     translate_port=None,
                     vlans=None):
      r'''
      A function to connect to a bigip device and create a virtual server.
  
      hostname
          The host/address of the bigip device
      username
          The iControl REST username
      password
          The iControl REST password
      name
          The name of the virtual to create
      destination
          [ [virtual_address_name:port] | [ipv4:port] | [ipv6.port] ]
      pool
          [ [pool_name] | none]
      address_status
          [yes | no]
      auto_lasthop
          [default | enabled | disabled ]
      bwc_policy
          [none] | string]
      cmp_enabled
          [yes | no]
      dhcp_relay
          [yes | no]
      connection_limit
          [integer]
      description
          [string]
      state
          [disabled | enabled]
      fallback_persistence
          [none | [profile name] ]
      flow_eviction_policy
          [none | [eviction policy name] ]
      gtm_score
          [integer]
      ip_forward
          [yes | no]
      ip_protocol
          [any | protocol]
      internal
          [yes | no]
      twelve_forward
          (12-forward)
          [yes | no]
      last_hop-pool
          [ [pool_name] | none]
      mask
          { [ipv4] | [ipv6] }
      mirror
          { [disabled | enabled | none] }
      nat64
          [enabled | disabled]
      persist
          [none | profile1,profile2,profile3 ... ]
      profiles
          [none | default | profile1,profile2,profile3 ... ]
      policies
          [none | default | policy1,policy2,policy3 ... ]
      rate_class
          [name]
      rate_limit
          [integer]
      rate_limit_mode
          [destination | object | object-destination |
          object-source | object-source-destination |
          source | source-destination]
      rate_limit_dst
          [integer]
      rate_limitçsrc
          [integer]
      rules
          [none | [rule_one,rule_two ...] ]
      related_rules
          [none | [rule_one,rule_two ...] ]
      reject
          [yes | no]
      source
          { [ipv4[/prefixlen]] | [ipv6[/prefixlen]] }
      source_address_translation
          [none | snat:pool_name | lsn | automap ]
      source_port
          [change | preserve | preserve-strict]
      state
          [enabled | disabled]
      traffic_classes
          [none | default | class_one,class_two ... ]
      translate_address
          [enabled | disabled]
      translate_port
          [enabled | disabled]
      vlans
          [none | default | [enabled|disabled]:vlan1,vlan2,vlan3 ... ]
  
      CLI Examples::
  
          salt '*' bigip.create_virtual bigip admin admin my-virtual-3 26.2.2.5:80 \
              pool=my-http-pool-http profiles=http,tcp
  
          salt '*' bigip.create_virtual bigip admin admin my-virtual-3 43.2.2.5:80 \
              pool=test-http-pool-http profiles=http,websecurity persist=cookie,hash \
              policies=asm_auto_l7_policy__http-virtual \
              rules=_sys_APM_ExchangeSupport_helper,_sys_https_redirect \
              related_rules=_sys_APM_activesync,_sys_APM_ExchangeSupport_helper \
              source_address_translation=snat:my-snat-pool \
              translate_address=enabled translate_port=enabled \
              traffic_classes=my-class,other-class \
              vlans=enabled:external,internal
  
      '''
  
      params = {
          'pool': pool,
          'auto-lasthop': auto_lasthop,
          'bwc-policy': bwc_policy,
          'connection-limit': connection_limit,
          'description': description,
          'fallback-persistence': fallback_persistence,
          'flow-eviction-policy': flow_eviction_policy,
          'gtm-score': gtm_score,
          'ip-protocol': ip_protocol,
          'last-hop-pool': last_hop_pool,
          'mask': mask,
          'mirror': mirror,
          'nat64': nat64,
          'persist': persist,
          'rate-class': rate_class,
          'rate-limit': rate_limit,
          'rate-limit-mode': rate_limit_mode,
          'rate-limit-dst': rate_limit_dst,
          'rate-limit-src': rate_limit_src,
          'source': source,
          'source-port': source_port,
          'translate-address': translate_address,
          'translate-port': translate_port
      }
  
      # some options take yes no others take true false.  Figure out when to use which without
      # confusing the end user
      toggles = {
          'address-status': {'type': 'yes_no', 'value': address_status},
          'cmp-enabled': {'type': 'yes_no', 'value': cmp_enabled},
          'dhcp-relay': {'type': 'true_false', 'value': dhcp_relay},
          'reject': {'type': 'true_false', 'value': reject},
          '12-forward': {'type': 'true_false', 'value': twelve_forward},
          'internal': {'type': 'true_false', 'value': internal},
          'ip-forward': {'type': 'true_false', 'value': ip_forward}
      }
  
      #build session
      bigip_session = _build_session(username, password)
  
      #build payload
      payload = _loop_payload(params)
  
      payload['name'] = name
      payload['destination'] = destination
  
      #determine toggles
      payload = _determine_toggles(payload, toggles)
  
      #specify profiles if provided
      if profiles is not None:
          payload['profiles'] = _build_list(profiles, 'ltm:virtual:profile')
  
      #specify persist if provided
      if persist is not None:
          payload['persist'] = _build_list(persist, 'ltm:virtual:persist')
  
      #specify policies if provided
      if policies is not None:
          payload['policies'] = _build_list(policies, 'ltm:virtual:policy')
  
      #specify rules if provided
      if rules is not None:
          payload['rules'] = _build_list(rules, None)
  
      #specify related-rules if provided
      if related_rules is not None:
          payload['related-rules'] = _build_list(related_rules, None)
  
      #handle source-address-translation
      if source_address_translation is not None:
  
          #check to see if this is already a dictionary first
          if isinstance(source_address_translation, dict):
              payload['source-address-translation'] = source_address_translation
          elif source_address_translation == 'none':
              payload['source-address-translation'] = {'pool': 'none', 'type': 'none'}
          elif source_address_translation == 'automap':
              payload['source-address-translation'] = {'pool': 'none', 'type': 'automap'}
          elif source_address_translation == 'lsn':
              payload['source-address-translation'] = {'pool': 'none', 'type': 'lsn'}
          elif source_address_translation.startswith('snat'):
              snat_pool = source_address_translation.split(':')[1]
              payload['source-address-translation'] = {'pool': snat_pool, 'type': 'snat'}
  
      #specify related-rules if provided
      if traffic_classes is not None:
          payload['traffic-classes'] = _build_list(traffic_classes, None)
  
      #handle vlans
      if vlans is not None:
          #ceck to see if vlans is a dictionary (used when state makes use of function)
          if isinstance(vlans, dict):
              try:
                  payload['vlans'] = vlans['vlan_ids']
                  if vlans['enabled']:
                      payload['vlans-enabled'] = True
                  elif vlans['disabled']:
                      payload['vlans-disabled'] = True
              except Exception:
                  return 'Error: Unable to Parse vlans dictionary: \n\tvlans={vlans}'.format(vlans=vlans)
          elif vlans == 'none':
              payload['vlans'] = 'none'
          elif vlans == 'default':
              payload['vlans'] = 'default'
          elif isinstance(vlans, six.string_types) and (vlans.startswith('enabled') or vlans.startswith('disabled')):
              try:
                  vlans_setting = vlans.split(':')[0]
                  payload['vlans'] = vlans.split(':')[1].split(',')
                  if vlans_setting == 'disabled':
                      payload['vlans-disabled'] = True
                  elif vlans_setting == 'enabled':
                      payload['vlans-enabled'] = True
              except Exception:
                  return 'Error: Unable to Parse vlans option: \n\tvlans={vlans}'.format(vlans=vlans)
          else:
              return 'Error: vlans must be a dictionary or string.'
  
      #determine state
      if state is not None:
          if state == 'enabled':
              payload['enabled'] = True
          elif state == 'disabled':
              payload['disabled'] = True
  
      #post to REST
      try:
          response = bigip_session.post(
              BIG_IP_URL_BASE.format(host=hostname) + '/ltm/virtual',
              data=salt.utils.json.dumps(payload)
          )
      except requests.exceptions.ConnectionError as e:
          return _load_connection_error(hostname, e)
  
      return _load_response(response)