'Create a new DimensionData node in MCP2. However, it is still
backward compatible for MCP1 for a limited time. Please consider
using MCP2 datacenter as MCP1 will phase out soon.
Legacy Create Node for MCP1 datacenter
>>> from pprint import pprint
>>> from libcloud.compute.types import Provider
>>> from libcloud.compute.base import NodeAuthPassword
>>> from libcloud.compute.providers import get_driver
>>> import libcloud.security
>>> # Get dimension data driver
>>> libcloud.security.VERIFY_SSL_CERT = False
>>> DimensionData = get_driver(Provider.DIMENSIONDATA)
>>> driver = cls(\'myusername\',\'mypassword\', region=\'dd-au\')
>>> # Password
>>> root_pw = NodeAuthPassword(\'password123\')
>>> # Get location
>>> location = driver.ex_get_location_by_id(id=\'AU1\')
>>> # Get network by location
>>> my_network = driver.list_networks(location=location)[0]
>>> pprint(my_network)
>>> # Get Image
>>> images = driver.list_images(location=location)
>>> image = images[0]
>>> node = driver.create_node(name=\'test_blah_2\', image=image,
>>>                           auth=root_pw,
>>>                           ex_description=\'test3 node\',
>>>                           ex_network=my_network,
>>>                           ex_is_started=False)
>>> pprint(node)
Create Node in MCP2 Data Center
>>> from pprint import pprint
>>> from libcloud.compute.types import Provider
>>> from libcloud.compute.base import NodeAuthPassword
>>> from libcloud.compute.providers import get_driver
>>> import libcloud.security
>>> # Get dimension data driver
>>> libcloud.security.VERIFY_SSL_CERT = True
>>> cls = get_driver(Provider.DIMENSIONDATA)
>>> driver = cls(\'myusername\',\'mypassword\', region=\'dd-au\')
>>> # Password
>>> root_pw = NodeAuthPassword(\'password123\')
>>> # Get location
>>> location = driver.ex_get_location_by_id(id=\'AU9\')
>>> # Get network domain by location
>>> networkDomainName = "Baas QA"
>>> network_domains = driver.ex_list_network_domains(location=location)
>>> my_network_domain = [d for d in network_domains if d.name ==
networkDomainName][0]
>>> vlan = driver.ex_list_vlans(location=location,
>>>                             network_domain=my_network_domain)[0]
>>> pprint(vlan)
>>> # Get Image
>>> images = driver.list_images(location=location)
>>> image = images[0]
>>> # Create node using vlan instead of private IPv4
>>> node = driver.create_node(name=\'test_server_01\', image=image,
>>>                           auth=root_pw,
>>>                           ex_description=\'test2 node\',
>>>                           ex_network_domain=my_network_domain,
>>>                           ex_primary_nic_vlan=vlan,
>>>                           ex_is_started=False)
>>> # Option: Create node using private IPv4 instead of vlan
>>> # node = driver.create_node(name=\'test_server_02\', image=image,
>>> #                           auth=root_pw,
>>> #                           ex_description=\'test2 node\',
>>> #                           ex_network_domain=my_network_domain,
>>> #                           ex_primary_nic_private_ipv4=\'10.1.1.7\',
>>> #                           ex_is_started=False)
>>> # Option: Create node using by specifying Network Adapter
>>> # node = driver.create_node(name=\'test_server_03\', image=image,
>>> #                           auth=root_pw,
>>> #                           ex_description=\'test2 node\',
>>> #                           ex_network_domain=my_network_domain,
>>> #                           ex_primary_nic_vlan=vlan,
>>> #                           ex_primary_nic_network_adapter=\'E1000\',
>>> #                           ex_is_started=False)
:keyword    name:   (required) String with a name for this new node
:type       name:   ``str``
:keyword    image:  (required) OS Image to boot on node.
:type       image:  :class:`NodeImage` or ``str``
:keyword    auth:   Initial authentication information for the
node. (If this is a customer LINUX
image auth will be ignored)
:type       auth:   :class:`NodeAuthPassword` or ``str`` or ``None``
:keyword    ex_description:  (optional) description for this node
:type       ex_description:  ``str``
:keyword    ex_network_domain:  (required) Network Domain or Network
Domain ID to create the node
:type       ex_network_domain: :class:`DimensionDataNetworkDomain`
or ``str``
:keyword    ex_primary_nic_private_ipv4:  Provide private IPv4. Ignore
if ex_primary_nic_vlan is
provided. Use one or the
other. Not both.
:type       ex_primary_nic_private_ipv4: :``str``
:keyword    ex_primary_nic_vlan:  Provide VLAN for the node if
ex_primary_nic_private_ipv4 NOT
provided. One or the other. Not both.
:type       ex_primary_nic_vlan: :class: DimensionDataVlan or ``str``
:keyword    ex_primary_nic_network_adapter: (Optional) Default value
for the Operating System
will be used if leave
empty. Example: "E1000".
:type       ex_primary_nic_network_adapter: :``str``
:keyword    ex_additional_nics: (optional) List
:class:\'DimensionDataNic\' or None
:type       ex_additional_nics: ``list`` of :class:\'DimensionDataNic\'
or ``str``
:keyword    ex_memory_gb:  (optional) The amount of memory in GB for
the server Can be used to override the
memory value inherited from the source
Server Image.
:type       ex_memory_gb: ``int``
:keyword    ex_cpu_specification: (optional) The spec of CPU to deploy
:type       ex_cpu_specification:
:class:`DimensionDataServerCpuSpecification`
:keyword    ex_is_started: (required) Start server after creation.
Default is set to true.
:type       ex_is_started:  ``bool``
:keyword    ex_primary_dns: (Optional) The node\'s primary DNS
:type       ex_primary_dns: ``str``
:keyword    ex_secondary_dns: (Optional) The node\'s secondary DNS
:type       ex_secondary_dns: ``str``
:keyword    ex_ipv4_gateway: (Optional) IPv4 address in dot-decimal
notation, which will be used as the
Primary NIC gateway instead of the default
gateway assigned by the system. If
ipv4Gateway is provided it does not have
to be on the VLAN of the Primary NIC
but MUST be reachable or the Guest OS
will not be configured correctly.
:type       ex_ipv4_gateway: ``str``
:keyword    ex_disks: (optional) Dimensiondata disks. Optional disk
elements can be used to define the disk speed
that each disk on the Server; inherited from the
source Server Image will be deployed to. It is
not necessary to include a diskelement for every
disk; only those that you wish to set a disk
speed value for. Note that scsiId 7 cannot be
used.Up to 13 disks can be present in addition to
the required OS disk on SCSI ID 0. Refer to
https://docs.mcp-services.net/x/UwIu for disk
:type       ex_disks: List or tuple of :class:\'DimensionDataServerDisk`
:keyword    ex_microsoft_time_zone: (optional) For use with
Microsoft Windows source Server Images only. For the exact
value to use please refer to the table of time zone
indexes in the following Microsoft Technet
documentation. If none is supplied, the default time
zone for the data center geographic region will be used.
:type       ex_microsoft_time_zone: `str``
:return: The newly created :class:`Node`.
:rtype: :class:`Node`'

def create_node(self, name, image, auth, ex_network_domain=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_description=None, ex_disks=None, ex_cpu_specification=None, ex_memory_gb=None, ex_is_started=True, ex_primary_dns=None, ex_secondary_dns=None, ex_ipv4_gateway=None, ex_microsoft_time_zone=None, **kwargs):

    if ((ex_network_domain is None) and ('ex_network' not in kwargs)):
        raise ValueError('You    must    provide    either    ex_network_domain    for    MCP2    or    ex_network    for    legacy    MCP1')
    if ((ex_network_domain is not None) and ('ex_network' in kwargs)):
        raise ValueError('You    can    only    supply    either    ex_network_domain    for    MCP2    or    ex_network    for    legacy    MCP1')
    if (not isinstance(ex_is_started, bool)):
        ex_is_started = True
    if ('ex_network' in kwargs):
        new_node = self._create_node_mcp1(name=name, image=image, auth=auth, ex_network=kwargs.get('ex_network'), ex_description=ex_description, ex_memory_gb=ex_memory_gb, ex_cpu_specification=ex_cpu_specification, ex_is_started=ex_is_started, ex_primary_ipv4=ex_primary_nic_private_ipv4, ex_disks=ex_disks, ex_additional_nics_vlan=kwargs.get('ex_additional_nics_vlan'), ex_additional_nics_ipv4=kwargs.get('ex_additional_nics_ipv4'), ex_primary_dns=ex_primary_dns, ex_secondary_dns=ex_secondary_dns)
    else:
        if ('ex_vlan' in kwargs):
            ex_primary_nic_vlan = kwargs.get('ex_vlan')
        if ('ex_primary_ipv4' in kwargs):
            ex_primary_nic_private_ipv4 = kwargs.get('ex_primary_ipv4')
        additional_nics = []
        if ('ex_additional_nics_vlan' in kwargs):
            vlans = kwargs.get('ex_additional_nics_vlan')
            if isinstance(vlans, (list, tuple)):
                for v in vlans:
                    add_nic = DimensionDataNic(vlan=v)
                    additional_nics.append(add_nic)
            else:
                raise TypeError('ex_additional_nics_vlan    must    be    None    or    a    tuple/list')
        if ('ex_additional_nics_ipv4' in kwargs):
            ips = kwargs.get('ex_additional_nics_ipv4')
            if isinstance(ips, (list, tuple)):
                for ip in ips:
                    add_nic = DimensionDataNic(private_ip_v4=ip)
                    additional_nics.append(add_nic)
            elif (ips is not None):
                raise TypeError('ex_additional_nics_ipv4    must    be    None    or    a    tuple/list')
        if (('ex_additional_nics_vlan' in kwargs) or ('ex_additional_nics_ipv4' in kwargs)):
            ex_additional_nics = additional_nics
        if (ex_network_domain is None):
            raise ValueError('ex_network_domain    must    be    specified')
        password = None
        image_needs_auth = self._image_needs_auth(image)
        if image_needs_auth:
            if isinstance(auth, basestring):
                auth_obj = NodeAuthPassword(password=auth)
                password = auth
            else:
                auth_obj = self._get_and_check_auth(auth)
                password = auth_obj.password
        server_elm = ET.Element('deployServer', {'xmlns': TYPES_URN})
        ET.SubElement(server_elm, 'name').text = name
        ET.SubElement(server_elm, 'description').text = ex_description
        image_id = self._image_to_image_id(image)
        ET.SubElement(server_elm, 'imageId').text = image_id
        ET.SubElement(server_elm, 'start').text = str(ex_is_started).lower()
        if (password is not None):
            ET.SubElement(server_elm, 'administratorPassword').text = password
        if (ex_cpu_specification is not None):
            cpu = ET.SubElement(server_elm, 'cpu')
            cpu.set('speed', ex_cpu_specification.performance)
            cpu.set('count', str(ex_cpu_specification.cpu_count))
            cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket))
        if (ex_memory_gb is not None):
            ET.SubElement(server_elm, 'memoryGb').text = str(ex_memory_gb)
        if ((ex_primary_nic_private_ipv4 is None) and (ex_primary_nic_vlan is None)):
            raise ValueError('Missing    argument.    Either    ex_primary_nic_private_ipv4    or    ex_primary_nic_vlan    must    be    specified.')
        if ((ex_primary_nic_private_ipv4 is not None) and (ex_primary_nic_vlan is not None)):
            raise ValueError('Either    ex_primary_nic_private_ipv4    or    ex_primary_nic_vlan    be    specified.    Not    both.')
        network_elm = ET.SubElement(server_elm, 'networkInfo')
        net_domain_id = self._network_domain_to_network_domain_id(ex_network_domain)
        network_elm.set('networkDomainId', net_domain_id)
        pri_nic = ET.SubElement(network_elm, 'primaryNic')
        if (ex_primary_nic_private_ipv4 is not None):
            ET.SubElement(pri_nic, 'privateIpv4').text = ex_primary_nic_private_ipv4
        if (ex_primary_nic_vlan is not None):
            vlan_id = self._vlan_to_vlan_id(ex_primary_nic_vlan)
            ET.SubElement(pri_nic, 'vlanId').text = vlan_id
        if (ex_primary_nic_network_adapter is not None):
            ET.SubElement(pri_nic, 'networkAdapter').text = ex_primary_nic_network_adapter
        if isinstance(ex_additional_nics, (list, tuple)):
            for nic in ex_additional_nics:
                additional_nic = ET.SubElement(network_elm, 'additionalNic')
                if ((nic.private_ip_v4 is None) and (nic.vlan is None)):
                    raise ValueError('Either    a    vlan    or    private_ip_v4    must    be    specified    for    each    additional    nic.')
                if ((nic.private_ip_v4 is not None) and (nic.vlan is not None)):
                    raise ValueError('Either    a    vlan    or    private_ip_v4    must    be    specified    for    each    additional    nic.    Not    both.')
                if (nic.private_ip_v4 is not None):
                    ET.SubElement(additional_nic, 'privateIpv4').text = nic.private_ip_v4
                if (nic.vlan is not None):
                    vlan_id = self._vlan_to_vlan_id(nic.vlan)
                    ET.SubElement(additional_nic, 'vlanId').text = vlan_id
                if (nic.network_adapter_name is not None):
                    ET.SubElement(additional_nic, 'networkAdapter').text = nic.network_adapter_name
        elif (ex_additional_nics is not None):
            raise TypeError('ex_additional_NICs    must    be    None    or    tuple/list')
        if ex_primary_dns:
            dns_elm = ET.SubElement(server_elm, 'primaryDns')
            dns_elm.text = ex_primary_dns
        if ex_secondary_dns:
            dns_elm = ET.SubElement(server_elm, 'secondaryDns')
            dns_elm.text = ex_secondary_dns
        if ex_ipv4_gateway:
            ET.SubElement(server_elm, 'ipv4Gateway').text = ex_ipv4_gateway
        if isinstance(ex_disks, (list, tuple)):
            for disk in ex_disks:
                disk_elm = ET.SubElement(server_elm, 'disk')
                disk_elm.set('scsiId', disk.scsi_id)
                disk_elm.set('speed', disk.speed)
        elif (ex_disks is not None):
            raise TypeError('ex_disks    must    be    None    or    tuple/list')
        if ex_microsoft_time_zone:
            ET.SubElement(server_elm, 'microsoftTimeZone').text = ex_microsoft_time_zone
        response = self.connection.request_with_orgId_api_2('server/deployServer', method='POST', data=ET.tostring(server_elm)).object
        node_id = None
        for info in findall(response, 'info', TYPES_URN):
            if (info.get('name') == 'serverId'):
                node_id = info.get('value')
        new_node = self.ex_get_node_by_id(node_id)
        if image_needs_auth:
            if getattr(auth_obj, 'generated', False):
                new_node.extra['password'] = auth_obj.password
    return new_node
