예제 #1
0
def get_ami_from_profile(profile_id):
    with app.app_context():
        profile = profiles.get_profile(profile_id)

        if 'ami' in profile and profile['ami']:
            return profile['ami']

        client = boto3.client('ec2',
                              region_name=current_app.config['aws']['region'])
        filters = yaml.load(profile['filter'])
        if 'owner' in profile:
            response = client.describe_images(Owners=[profile['owner']],
                                              Filters=filters)
        else:
            response = client.describe_images(Filters=filters)

        if 'Images' not in response:
            raise LookupError('Unable to find AMI with required filters')

        response['Images']
        latest = None
        for image in response['Images']:
            if not latest:
                latest = image
                continue
            if parser.parse(image['CreationDate']) > parser.parse(
                    latest['CreationDate']):
                latest = image
        return latest['ImageId']
예제 #2
0
def get_launch_instance_arguments_from_profile(profile_id,
                                               owner,
                                               group_id,
                                               size,
                                               label=False,
                                               shutdown=False,
                                               gpuidle=False):
    # within this block, current_app points to app.
    profile = profiles.get_profile(profile_id)
    userdata = profile['userdata']
    ImageID = get_ami_from_profile(profile_id)

    startArgs = {
        'DryRun': False,
        'ImageId': ImageID,
        'MinCount': 1,
        'MaxCount': 1,
        'UserData': userdata,
        'Monitoring': {
            'Enabled': True
        },
        'DisableApiTermination': False,
        'InstanceInitiatedShutdownBehavior': 'stop',
        'EbsOptimized': app.config['aws'].get('ebs_optimized', False),
    }

    if 'subnets' not in current_app.config['aws']:
        raise ValueError("SUBNET_ID must be saved in configuration")

    if 'security_group' in current_app.config['aws']:
        startArgs['SecurityGroupIds'] = [
            current_app.config['aws']['security_group']
        ]

    if 'iam_instance_profile' in current_app.config['aws']:
        startArgs['IamInstanceProfile'] = {
            'Arn': current_app.config['aws']['iam_instance_profile']
        }

    tags = get_base_tags(profile['name'], owner, group_id, size, label,
                         shutdown, gpuidle)

    if profile['tags']:
        for line in profile['tags'].splitlines():
            if len(line) > 3 and '=' in line:
                tag_name, tag_value = line.split('=', 1)
                tags.append({'Key': tag_name, 'Value': tag_value})

    startArgs['TagSpecifications'] = [
        {
            'ResourceType': 'instance',
            'Tags': tags
        },
        {
            'ResourceType': 'volume',
            'Tags': tags
        },
    ]

    return startArgs
예제 #3
0
def api_profiles_delete(profile_id):
    if request.method == 'DELETE':
        # Remove profile stored at specified id.
        if not profiles.get_profile(profile_id):
            # Profile does not exist
            return abort(404)
        profiles.remove_profile(profile_id)
        return jsonify({'status': 'ok'})
예제 #4
0
def profiles_update(profile_id):
    profile = profiles.get_profile(profile_id)
    print(profile)
    if request.method == 'POST':
        name = request.form.get('name', profile['name'])
        ami = request.form.get('ami', profile['ami'])
        owner = request.form.get('owner', profile['owner'])
        filter = request.form.get('filter', profile['filter'])
        userdata = request.form.get('userdata', None)
        profiles.update_profile(profile_id, name, ami, owner, filter, userdata)
        return redirect(url_for('profiles_list'))
    return render_template("profile_form.html", profile=profile)
예제 #5
0
def api_profiles_update(profile_id):
    """Update or delete specified profile id."""
    if request.method == 'PUT':
        existing_profile = profiles.get_profile(profile_id)
        # Update existing profile with new profile object.
        if not existing_profile:
            # Profile does not exist
            return abort(404)

        profile = request.get_json()
        name = profile.get('name', existing_profile['name'])
        ami = profile.get('ami', existing_profile['ami'])
        userdata = profile.get('userdata', existing_profile['userdata'])
        profiles.update_profile(profile_id, name, ami, userdata)
        return jsonify({'status': 'ok', 'id': profile_id})
예제 #6
0
def launch_instance(group_id,
                    profile_id,
                    instancetype,
                    owner,
                    size=120,
                    label=False,
                    shutdown=False,
                    gpuidle=False):

    with app.app_context():
        # within this block, current_app points to app.
        profile = profiles.get_profile(profile_id)
        print('Launching %s for %s with profile "%s"' %
              (instancetype, owner, profile))
        userdata = profile['userdata']
        ImageID = get_ami_from_profile(profile_id)

        startArgs = {
            'DryRun':
            False,
            'ImageId':
            ImageID,
            'MinCount':
            1,
            'MaxCount':
            1,
            'UserData':
            userdata,
            'InstanceType':
            instancetype,
            'Monitoring': {
                'Enabled': True
            },
            'DisableApiTermination':
            False,
            'InstanceInitiatedShutdownBehavior':
            'stop',
            'EbsOptimized':
            app.config['aws'].get('ebs_optimized', False),
            'BlockDeviceMappings': [{
                'DeviceName': '/dev/sda1',
                'Ebs': {
                    'VolumeSize': size,
                    'VolumeType': 'gp2'
                }
            }]
        }

        if 'subnets' not in current_app.config['aws']:
            raise ValueError("SUBNET_ID must be saved in configuration")

        if 'security_group' in current_app.config['aws']:
            startArgs['SecurityGroupIds'] = [
                current_app.config['aws']['security_group']
            ]

        if 'iam_instance_profile' in current_app.config['aws']:
            startArgs['IamInstanceProfile'] = {
                'Arn': current_app.config['aws']['iam_instance_profile']
            }

        ec2 = get_ec2_client()

        # Attempt on all available subnets
        subnets = current_app.config['aws']['subnets'][:]
        while True:
            startArgs['SubnetId'] = subnets.pop(0)
            try:
                instances = ec2.create_instances(**startArgs)
                break
            except ClientError as e:
                if len(subnets) < 1:
                    raise e

        # Wait for all machine requests to process so we can tag them.
        while True:
            launched = True
            for instance in instances:
                if instance.state == 16:
                    launched = False
            if launched:
                break
            time.sleep(5)

        autolive = app.config['aws'].get('auto_live', False)
        sitetag = app.config['general'].get('site_name', 'nebula')
        for instance in instances:
            print('Cluster start - tag')
            tags = [{
                'Key': sitetag,
                'Value': 'true'
            }, {
                'Key': 'User',
                'Value': owner
            }, {
                'Key': 'Profile',
                'Value': profile['name']
            }, {
                'Key': 'Group',
                'Value': group_id
            }]

            # Tag network devices- useful for cost exploration.
            for eni in instance.network_interfaces:
                print('tagging network interface')
                eni.create_tags(Tags=tags)

            # Tag attached devices. Volumes initialize slowly so schedule another task.
            tag_instance_volumes.delay(instance.instance_id, tags)

            tags.append({'Key': 'Disk_Space', 'Value': str(size)})
            if label:
                tags.append({'Key': 'Label', 'Value': label})
            if shutdown:
                tags.append({'Key': 'Shutdown', 'Value': shutdown})
            if gpuidle:
                tags.append({'Key': 'GPU_Shutdown', 'Value': gpuidle})
            if autolive:
                tags.append({'Key': 'Status', 'Value': 'Live'})
            instance.create_tags(Tags=tags)

        return True