'Create a new EC2 node.
Reference: http://bit.ly/8ZyPSy [docs.amazonwebservices.com]
@inherits: :class:`NodeDriver.create_node`
:keyword    ex_keyname: The name of the key pair
:type       ex_keyname: ``str``
:keyword    ex_userdata: User data
:type       ex_userdata: ``str``
:keyword    ex_security_groups: A list of names of security groups to
assign to the node.
:type       ex_security_groups:   ``list``
:keyword    ex_security_group_ids: A list of ids of security groups to
assign to the node.[for VPC nodes only]
:type       ex_security_group_ids:   ``list``
:keyword    ex_metadata: Key/Value metadata to associate with a node
:type       ex_metadata: ``dict``
:keyword    ex_mincount: Minimum number of instances to launch
:type       ex_mincount: ``int``
:keyword    ex_maxcount: Maximum number of instances to launch
:type       ex_maxcount: ``int``
:keyword    ex_clienttoken: Unique identifier to ensure idempotency
:type       ex_clienttoken: ``str``
:keyword    ex_blockdevicemappings: ``list`` of ``dict`` block device
mappings.
:type       ex_blockdevicemappings: ``list`` of ``dict``
:keyword    ex_iamprofile: Name or ARN of IAM profile
:type       ex_iamprofile: ``str``
:keyword    ex_ebs_optimized: EBS-Optimized if True
:type       ex_ebs_optimized: ``bool``
:keyword    ex_subnet: The subnet to launch the instance into.
:type       ex_subnet: :class:`.EC2Subnet`
:keyword    ex_placement_group: The name of the placement group to
launch the instance into.
:type       ex_placement_group: ``str``
:keyword    ex_assign_public_ip: If True, the instance will
be assigned a public ip address.
Note : It takes takes a short
while for the instance to be
assigned the public ip so the
node returned will NOT have
the public ip assigned yet.
:type       ex_assign_public_ip: ``bool``
:keyword    ex_terminate_on_shutdown: Indicates if the instance
should be terminated instead
of just shut down when using
the operating systems command
for system shutdown.
:type       ex_terminate_on_shutdown: ``bool``'

def create_node(self, **kwargs):

    image = kwargs['image']
    size = kwargs['size']
    params = {'Action': 'RunInstances', 'ImageId': image.id, 'MinCount': str(kwargs.get('ex_mincount', '1')), 'MaxCount': str(kwargs.get('ex_maxcount', '1')), 'InstanceType': size.id}
    if kwargs.get('ex_terminate_on_shutdown', False):
        params['InstanceInitiatedShutdownBehavior'] = 'terminate'
    if (('ex_security_groups' in kwargs) and ('ex_securitygroup' in kwargs)):
        raise ValueError('You    can    only    supply    ex_security_groups    or    ex_securitygroup')
    ex_security_groups = kwargs.get('ex_security_groups', None)
    ex_securitygroup = kwargs.get('ex_securitygroup', None)
    security_groups = (ex_security_groups or ex_securitygroup)
    if security_groups:
        if (not isinstance(security_groups, (tuple, list))):
            security_groups = [security_groups]
        for sig in range(len(security_groups)):
            params[('SecurityGroup.%d' % ((sig + 1),))] = security_groups[sig]
    if (('ex_security_group_ids' in kwargs) and ('ex_subnet' not in kwargs)):
        raise ValueError('You    can    only    supply    ex_security_group_ids    combinated    with    ex_subnet')
    security_group_ids = kwargs.get('ex_security_group_ids', None)
    security_group_id_params = {}
    if security_group_ids:
        if (not isinstance(security_group_ids, (tuple, list))):
            security_group_ids = [security_group_ids]
        for sig in range(len(security_group_ids)):
            security_group_id_params[('SecurityGroupId.%d' % ((sig + 1),))] = security_group_ids[sig]
    if ('location' in kwargs):
        availability_zone = getattr(kwargs['location'], 'availability_zone', None)
        if availability_zone:
            if (availability_zone.region_name != self.region_name):
                raise AttributeError(('Invalid    availability    zone:    %s' % availability_zone.name))
            params['Placement.AvailabilityZone'] = availability_zone.name
    if (('auth' in kwargs) and ('ex_keyname' in kwargs)):
        raise AttributeError('Cannot    specify    auth    and    ex_keyname    together')
    if ('auth' in kwargs):
        auth = self._get_and_check_auth(kwargs['auth'])
        key = self.ex_find_or_import_keypair_by_key_material(auth.pubkey)
        params['KeyName'] = key['keyName']
    if ('ex_keyname' in kwargs):
        params['KeyName'] = kwargs['ex_keyname']
    if ('ex_userdata' in kwargs):
        params['UserData'] = base64.b64encode(b(kwargs['ex_userdata'])).decode('utf-8')
    if ('ex_clienttoken' in kwargs):
        params['ClientToken'] = kwargs['ex_clienttoken']
    if ('ex_blockdevicemappings' in kwargs):
        params.update(self._get_block_device_mapping_params(kwargs['ex_blockdevicemappings']))
    if ('ex_iamprofile' in kwargs):
        if (not isinstance(kwargs['ex_iamprofile'], basestring)):
            raise AttributeError('ex_iamprofile    not    string')
        if kwargs['ex_iamprofile'].startswith('arn:aws:iam:'):
            params['IamInstanceProfile.Arn'] = kwargs['ex_iamprofile']
        else:
            params['IamInstanceProfile.Name'] = kwargs['ex_iamprofile']
    if ('ex_ebs_optimized' in kwargs):
        params['EbsOptimized'] = kwargs['ex_ebs_optimized']
    subnet_id = None
    if ('ex_subnet' in kwargs):
        subnet_id = kwargs['ex_subnet'].id
    if (('ex_placement_group' in kwargs) and kwargs['ex_placement_group']):
        params['Placement.GroupName'] = kwargs['ex_placement_group']
    assign_public_ip = kwargs.get('ex_assign_public_ip', False)
    if assign_public_ip:
        root_key = 'NetworkInterface.1.'
        params[(root_key + 'AssociatePublicIpAddress')] = 'true'
        params[(root_key + 'DeleteOnTermination')] = 'true'
        params[(root_key + 'DeviceIndex')] = '0'
        if subnet_id:
            params[(root_key + 'SubnetId')] = subnet_id
        for (key, security_group_id) in security_group_id_params.items():
            key = (root_key + key)
            params[key] = security_group_id
    else:
        params.update(security_group_id_params)
        if subnet_id:
            params['SubnetId'] = subnet_id
    object = self.connection.request(self.path, params=params).object
    nodes = self._to_nodes(object, 'instancesSet/item')
    for node in nodes:
        tags = {'Name': kwargs['name']}
        if ('ex_metadata' in kwargs):
            tags.update(kwargs['ex_metadata'])
        try:
            self.ex_create_tags(resource=node, tags=tags)
        except Exception:
            continue
        node.name = kwargs['name']
        node.extra.update({'tags': tags})
    if (len(nodes) == 1):
        return nodes[0]
    else:
        return nodes
