def make_ec2_nodes(<EOL>security_groupid,<EOL>subnet_id,<EOL>keypair_name,<EOL>iam_instance_profile_arn,<EOL>launch_instances=<NUM_LIT:1>,<EOL>ami='<STR_LIT>',<EOL>instance='<STR_LIT>',<EOL>ebs_optimized=True,<EOL>user_data=None,<EOL>wait_until_up=True,<EOL>client=None,<EOL>raiseonfail=False,<EOL>):
if not client:<EOL><INDENT>client = boto3.client('<STR_LIT>')<EOL><DEDENT>if isinstance(user_data, str) and os.path.exists(user_data):<EOL><INDENT>with open(user_data,'<STR_LIT:r>') as infd:<EOL><INDENT>udata = infd.read()<EOL><DEDENT><DEDENT>elif isinstance(user_data, str):<EOL><INDENT>udata = user_data<EOL><DEDENT>else:<EOL><INDENT>udata = (<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % datetime.utcnow().isoformat()<EOL>)<EOL><DEDENT>try:<EOL><INDENT>resp = client.run_instances(<EOL>ImageId=ami,<EOL>InstanceType=instance,<EOL>SecurityGroupIds=[<EOL>security_groupid,<EOL>],<EOL>SubnetId=subnet_id,<EOL>UserData=udata,<EOL>IamInstanceProfile={'<STR_LIT>':iam_instance_profile_arn},<EOL>InstanceInitiatedShutdownBehavior='<STR_LIT>',<EOL>KeyName=keypair_name,<EOL>MaxCount=launch_instances,<EOL>MinCount=launch_instances,<EOL>EbsOptimized=ebs_optimized,<EOL>)<EOL>if not resp:<EOL><INDENT>LOGERROR('<STR_LIT>')<EOL>return None<EOL><DEDENT>else:<EOL><INDENT>instance_dict = {}<EOL>instance_list = resp.get('<STR_LIT>',[])<EOL>if len(instance_list) > <NUM_LIT:0>:<EOL><INDENT>for instance in instance_list:<EOL><INDENT>LOGINFO('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (instance['<STR_LIT>'],<EOL>instance['<STR_LIT>'],<EOL>instance['<STR_LIT>'].isoformat(),<EOL>instance['<STR_LIT>']['<STR_LIT:Name>']))<EOL>instance_dict[instance['<STR_LIT>']] = {<EOL>'<STR_LIT:type>':instance['<STR_LIT>'],<EOL>'<STR_LIT>':instance['<STR_LIT>'],<EOL>'<STR_LIT:state>':instance['<STR_LIT>']['<STR_LIT:Name>'],<EOL>'<STR_LIT:info>':instance<EOL>}<EOL><DEDENT><DEDENT>if wait_until_up:<EOL><INDENT>ready_instances = []<EOL>LOGINFO('<STR_LIT>')<EOL>ntries = <NUM_LIT:5><EOL>curr_try = <NUM_LIT:0><EOL>while ( (curr_try < ntries) or<EOL>( len(ready_instances) <<EOL>len(list(instance_dict.keys()))) ):<EOL><INDENT>resp = client.describe_instances(<EOL>InstanceIds=list(instance_dict.keys()),<EOL>)<EOL>if len(resp['<STR_LIT>']) > <NUM_LIT:0>:<EOL><INDENT>for resv in resp['<STR_LIT>']:<EOL><INDENT>if len(resv['<STR_LIT>']) > <NUM_LIT:0>:<EOL><INDENT>for instance in resv['<STR_LIT>']:<EOL><INDENT>if instance['<STR_LIT>']['<STR_LIT:Name>'] == '<STR_LIT>':<EOL><INDENT>ready_instances.append(<EOL>instance['<STR_LIT>']<EOL>)<EOL>instance_dict[<EOL>instance['<STR_LIT>']<EOL>]['<STR_LIT:state>'] = '<STR_LIT>'<EOL>instance_dict[<EOL>instance['<STR_LIT>']<EOL>]['<STR_LIT>'] = instance['<STR_LIT>']<EOL>instance_dict[<EOL>instance['<STR_LIT>']<EOL>]['<STR_LIT:info>'] = instance<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>curr_try = curr_try + <NUM_LIT:1><EOL>time.sleep(<NUM_LIT>)<EOL><DEDENT>if len(ready_instances) == len(list(instance_dict.keys())):<EOL><INDENT>LOGINFO('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>LOGWARNING(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>)<EOL><DEDENT><DEDENT>return instance_dict<EOL><DEDENT><DEDENT>except ClientError as e:<EOL><INDENT>LOGEXCEPTION('<STR_LIT>')<EOL>if raiseonfail:<EOL><INDENT>raise<EOL><DEDENT>return None<EOL><DEDENT>except Exception as e:<EOL><INDENT>LOGEXCEPTION('<STR_LIT>')<EOL>if raiseonfail:<EOL><INDENT>raise<EOL><DEDENT>return None<EOL><DEDENT>
This makes new EC2 worker nodes.

    This requires a security group ID attached to a VPC config and subnet, a
    keypair generated beforehand, and an IAM role ARN for the instance. See:

    https://docs.aws.amazon.com/cli/latest/userguide/tutorial-ec2-ubuntu.html

    Use `user_data` to launch tasks on instance launch.

    Parameters
    ----------

    security_groupid : str
        The security group ID of the AWS VPC where the instances will be
        launched.

    subnet_id : str
        The subnet ID of the AWS VPC where the instances will be
        launched.

    keypair_name : str
        The name of the keypair to be used to allow SSH access to all instances
        launched here. This corresponds to an already downloaded AWS keypair PEM
        file.

    iam_instance_profile_arn : str
        The ARN string corresponding to the AWS instance profile that describes
        the permissions the launched instances have to access other AWS
        resources. Set this up in AWS IAM.

    launch_instances : int
        The number of instances to launch in this request.

    ami : str
        The Amazon Machine Image ID that describes the OS the instances will use
        after launch. The default ID is Amazon Linux 2 in the US East region.

    instance : str
        The instance type to launch. See the following URL for a list of IDs:
        https://aws.amazon.com/ec2/pricing/on-demand/

    ebs_optimized : bool
        If True, will enable EBS optimization to speed up IO. This is usually
        True for all instances made available in the last couple of years.

    user_data : str or None
        This is either the path to a file on disk that contains a shell-script
        or a string containing a shell-script that will be executed by root
        right after the instance is launched. Use to automatically set up
        workers and queues. If None, will not execute anything at instance
        start up.

    wait_until_up : bool
        If True, will not return from this function until all launched instances
        are verified as running by AWS.

    client : boto3.Client or None
        If None, this function will instantiate a new `boto3.Client` object to
        use in its operations. Alternatively, pass in an existing `boto3.Client`
        instance to re-use it here.

    raiseonfail : bool
        If True, will re-raise whatever Exception caused the operation to fail
        and break out immediately.

    Returns
    -------

    dict
        Returns launched instance info as a dict, keyed by instance ID.