blob: 01d2127341351da53fca2b93884f6c9d7f634f12 [file] [log] [blame]
#!/usr/bin/env python
# encoding: utf-8
"""This module contains functions for handling requests in relation to
instances.
"""
from flask import current_app
from ec2stack.providers import cloudstack
from ec2stack.providers.cloudstack import requester, service_offerings, zones, \
disk_offerings
from ec2stack import helpers, errors
@helpers.authentication_required
def describe_instance_attribute():
"""
Describes an instance attribute.
@return: Response.
"""
instance_id = helpers.get('InstanceId')
attribute = helpers.get('Attribute')
supported_attribute_map = {
'instanceType': 'serviceofferingname',
'groupSet': 'securitygroup'
}
if attribute not in supported_attribute_map.iterkeys():
errors.invalid_parameter_value(
'The specified attribute is not valid, please specify a valid ' +
'instance attribute.'
)
response = describe_instance_by_id(instance_id)
return _describe_instance_attribute_response(
response, attribute, supported_attribute_map)
def _describe_instance_attribute_response(response, attribute, attr_map):
"""
Generates a response for a describe instance attribute request.
@param response: Response from Cloudstack.
@param attribute: Attribute to Describe.
@param attr_map: Map of attributes from EC2 to Cloudstack.
@return: Response.
"""
response = {
'template_name_or_list': 'instance_attribute.xml',
'response_type': 'DescribeInstanceAttributeResponse',
'attribute': attribute,
'response': response[attr_map[attribute]],
'id': response['id']
}
return response
@helpers.authentication_required
def describe_instances():
"""
Describe a specific instance or all instances.
@return: Response.
"""
args = {'command': 'listVirtualMachines'}
response = cloudstack.describe_item(
args, 'virtualmachine', errors.invalid_instance_id, 'InstanceId'
)
return _describe_instances_response(
response
)
def describe_instance_by_id(instance_id):
"""
Describe an instance by Id.
@param instance_id: Id of the instance.
@return: Response.
"""
args = {'id': instance_id, 'command': 'listVirtualMachines'}
response = cloudstack.describe_item_request(
args, 'virtualmachine', errors.invalid_instance_id
)
return response
def _describe_instances_response(response):
"""
Generates a response for a describe instance request.
@param response: Response from Cloudstack.
@return: Response.
"""
return {
'template_name_or_list': 'instances.xml',
'response_type': 'DescribeInstancesResponse',
'response': response
}
@helpers.authentication_required
def reboot_instance():
"""
Reboot an instance.
@return: Response.
"""
helpers.require_parameters(['InstanceId.1'])
instance_id = helpers.get('InstanceId.1')
_reboot_instance_request(instance_id)
return _reboot_instance_response()
def _reboot_instance_request(instance_id):
"""
Request to reboot an instance.
@param instance_id: Id of instance to be rebooted.
@return: Response.
"""
args = {'command': 'rebootVirtualMachine',
'id': instance_id}
response = requester.make_request_async(args)
response = response['virtualmachine']
return response
def _reboot_instance_response():
"""
Generates a response for a reboot instance request.
@return: Response.
"""
response = {
'template_name_or_list': 'status.xml',
'response_type': 'RebootInstancesResponse',
'return': 'true'
}
return response
@helpers.authentication_required
def run_instance():
"""
Run a instance.
@return: Response.
"""
helpers.require_parameters(
['ImageId', 'MinCount', 'MaxCount'])
response = _run_instance_request()
return _run_instance_response(response)
def _run_instance_request():
"""
Request to bring up an instance.
@return: Response.
"""
args = {}
if helpers.contains_parameter('Placement.AvailabilityZone'):
args['zoneid'] = zones.get_zone(
helpers.get('Placement.AvailabilityZone')
)
else:
args['zoneid'] = zones.get_zone(
current_app.config['CLOUDSTACK_DEFAULT_ZONE']
)['id']
if helpers.get('BlockDeviceMapping.1.Ebs.VolumeType') is not None:
disk_type = helpers.get('BlockDeviceMapping.1.Ebs.VolumeType')
if disk_type == 'gp2':
args['diskofferingid'] = disk_offerings.get_disk_offering(
current_app.config['CLOUDSTACK_CUSTOM_DISK_OFFERING']
)['id']
if helpers.get('BlockDeviceMapping.1.Ebs.VolumeSize') is None:
errors.invalid_request("VolumeSize not found in BlockDeviceMapping")
else:
args['size'] = helpers.get('BlockDeviceMapping.1.Ebs.VolumeSize')
if helpers.get('InstanceType') is None:
instance_type = 'm1.small'
else:
instance_type = helpers.get('InstanceType')
if instance_type in current_app.config['INSTANCE_TYPE_MAP']:
instance_type = current_app.config[
'INSTANCE_TYPE_MAP'][instance_type]
else:
instance_type = instance_type
args['serviceofferingid'] = \
service_offerings.get_service_offering(instance_type)['id']
args['templateid'] = helpers.get('ImageId')
if helpers.contains_parameter('KeyName'):
args['keypair'] = helpers.get('KeyName')
if helpers.contains_parameter('UserData'):
args['userdata'] = helpers.get('UserData')
if helpers.contains_parameter_with_keyword('SecurityGroupId.'):
keys = helpers.get_request_parameter_keys('SecurityGroupId.')
securitygroupids = []
for key in keys:
securitygroupids.append(helpers.get(key))
args['securitygroupids'] = ",".join(securitygroupids)
if helpers.contains_parameter_with_keyword('SecurityGroup.'):
keys = helpers.get_request_parameter_keys('SecurityGroup.')
securitygroupnames = []
for key in keys:
securitygroupnames.append(helpers.get(key))
args['securitygroupnames'] = ",".join(securitygroupnames)
args['command'] = 'deployVirtualMachine'
response = requester.make_request_async(args)
return response
def _run_instance_response(response):
"""
Generates a response for a run instance request.
@param response: Response from Cloudstack.
@return: Response.
"""
if 'errortext' in response:
if 'Object vm_template' in response['errortext']:
errors.invalid_image_id()
elif 'Object security_group' in response['errortext']:
errors.invalid_security_group()
elif 'A key pair with name' in response['errortext']:
errors.invalid_keypair_name()
else:
errors.invalid_request(response['errortext'])
else:
response = response['virtualmachine']
response = {
'template_name_or_list': 'run_instance.xml',
'response_type': 'RunInstancesResponse',
'response': response
}
return response
@helpers.authentication_required
def start_instance():
"""
Starts an instance.
@return: Response.
"""
helpers.require_parameters(['InstanceId.1'])
instance_id = helpers.get('InstanceId.1')
previous_state = describe_instance_by_id(instance_id)
new_state = _start_instance_request(instance_id)
return _modify_instance_state_response(
'StartInstancesResponse',
previous_state,
new_state
)
def _start_instance_request(instance_id):
"""
Request to start an instance.
@param instance_id: Id of instance to start.
@return: Response.
"""
args = {'command': 'startVirtualMachine',
'id': instance_id}
response = requester.make_request_async(args)
response = response['virtualmachine']
return response
def _modify_instance_state_response(response_type, previous_state, new_state):
"""
Generates a response for a Start, Stop, Terminate requests.
@param response_type: Cloudstack response.
@param previous_state: The previous state of the instance.
@param new_state: The new state of the instance.
@return: Response.
"""
response = {
'template_name_or_list': 'change_instance_state.xml',
'response_type': response_type,
'previous_state': previous_state,
'new_state': new_state
}
return response
@helpers.authentication_required
def stop_instance():
"""
Stop an instance.
@return: Response.
"""
helpers.require_parameters(['InstanceId.1'])
instance_id = helpers.get('InstanceId.1')
previous_state = describe_instance_by_id(instance_id)
new_state = _stop_instance_request(instance_id)
return _modify_instance_state_response(
'StopInstancesResponse',
previous_state,
new_state
)
def _stop_instance_request(instance_id):
"""
Request to stop an instance.
@param instance_id: Id of instance to stop.
@return: Response.
"""
args = {'command': 'stopVirtualMachine',
'id': instance_id}
response = requester.make_request_async(args)
response = response['virtualmachine']
return response
@helpers.authentication_required
def terminate_instance():
"""
Terminate an instance.
@return: Response.
"""
helpers.require_parameters(['InstanceId.1'])
instance_id = helpers.get('InstanceId.1')
previous_state = describe_instance_by_id(instance_id)
new_state = _terminate_instance_request(instance_id)
return _modify_instance_state_response(
'TerminateInstancesResponse',
previous_state,
new_state
)
def _terminate_instance_request(instance_id):
"""
Request to terminate an instance.
@param instance_id: Id of instance to terminate.
@return: Response.
"""
args = {'command': 'destroyVirtualMachine',
'id': instance_id}
response = requester.make_request_async(args)
response = response['virtualmachine']
return response