def describe_image_attribute(context, image_id, attribute): def _block_device_mapping_attribute(os_image, image, result): properties = ec2utils.deserialize_os_image_properties(os_image) mappings = _format_mappings(context, properties) if mappings: result['blockDeviceMapping'] = mappings def _description_attribute(os_image, image, result): result['description'] = {'value': image.get('description')} def _launch_permission_attribute(os_image, image, result): result['launchPermission'] = [] if os_image.is_public: result['launchPermission'].append({'group': 'all'}) def _kernel_attribute(os_image, image, result): kernel_id = os_image.properties.get('kernel_id') if kernel_id: result['kernel'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'aki', kernel_id) } def _ramdisk_attribute(os_image, image, result): ramdisk_id = os_image.properties.get('ramdisk_id') if ramdisk_id: result['ramdisk'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'ari', ramdisk_id) } # NOTE(ft): Openstack extension, AWS-incompability def _root_device_name_attribute(os_image, image, result): properties = ec2utils.deserialize_os_image_properties(os_image) result['rootDeviceName'] = ( ec2utils.block_device_properties_root_device_name(properties)) supported_attributes = { 'blockDeviceMapping': _block_device_mapping_attribute, 'description': _description_attribute, 'launchPermission': _launch_permission_attribute, 'kernel': _kernel_attribute, 'ramdisk': _ramdisk_attribute, # NOTE(ft): Openstack extension, AWS-incompability 'rootDeviceName': _root_device_name_attribute, } fn = supported_attributes.get(attribute) if fn is None: raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) if not os_image: # TODO(ft): figure out corresponding AWS error raise exception.IncorrectState( reason='Image is still being created or failed') _check_owner(context, os_image) image = ec2utils.get_db_item(context, image_id) result = {'imageId': image_id} fn(os_image, image, result) return result
def invoke(self, context): try: method = getattr(self.controller, ec2utils.camelcase_to_underscore(self.action)) except AttributeError: LOG.exception(_('Unsupported API request: action = %(action)s'), {'action': self.action}) raise exception.InvalidRequest() args = ec2utils.dict_from_dotted_str(self.args.items()) def convert_dicts_to_lists(args): if not isinstance(args, dict): return args for key in args.keys(): # NOTE(vish): Turn numeric dict keys into lists # NOTE(Alex): Turn "value"-only dict keys into values if isinstance(args[key], dict): if args[key] == {}: continue first_subkey = next(six.iterkeys(args[key])) if first_subkey.isdigit(): s = args[key] args[key] = [ convert_dicts_to_lists(s[k]) for k in sorted(s) ] elif (first_subkey == 'value' and len(args[key]) == 1): args[key] = args[key]['value'] return args args = convert_dicts_to_lists(args) result = method(context, **args) return self._render_response(result, context.request_id)
def reset_image_attribute(context, image_id, attribute): if attribute != 'launchPermission': raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) os_image.update(is_public=False) return True
def reset_image_attribute(context, image_id, attribute): if attribute != 'launchPermission': raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) glance = clients.glance(context) glance.images.update(os_image.id, visibility='private') return True
def describe_image_attribute(context, image_id, attribute): def _block_device_mapping_attribute(os_image, image, result): _cloud_format_mappings(context, os_image.properties, result) def _description_attribute(os_image, image, result): result['description'] = {'value': image.get('description')} def _launch_permission_attribute(os_image, image, result): result['launchPermission'] = [] if os_image.is_public: result['launchPermission'].append({'group': 'all'}) def _kernel_attribute(os_image, image, result): kernel_id = os_image.properties.get('kernel_id') if kernel_id: result['kernel'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'jki', kernel_id) } def _ramdisk_attribute(os_image, image, result): ramdisk_id = os_image.properties.get('ramdisk_id') if ramdisk_id: result['ramdisk'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'jri', ramdisk_id) } # NOTE(ft): Openstack extension, AWS-incompability def _root_device_name_attribute(os_image, image, result): result['rootDeviceName'] = (_block_device_properties_root_device_name( os_image.properties)) supported_attributes = { 'blockDeviceMapping': _block_device_mapping_attribute, 'description': _description_attribute, 'launchPermission': _launch_permission_attribute, 'kernel': _kernel_attribute, 'ramdisk': _ramdisk_attribute, # NOTE(ft): Openstack extension, AWS-incompability 'rootDeviceName': _root_device_name_attribute, } fn = supported_attributes.get(attribute) if fn is None: raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) _prepare_mappings(os_image) image = ec2utils.get_db_item(context, image_id) result = {'imageId': image_id} fn(os_image, image, result) return result
def is_ec2_timestamp_expired(request, expires=None): """Checks the timestamp or expiry time included in an EC2 request and returns true if the request is expired """ query_time = None timestamp = request.get('Timestamp') expiry_time = request.get('Expires') def parse_strtime(strtime): if _ms_time_regex.match(strtime): # NOTE(MotoKen): time format for aws-sdk-java contains millisecond time_format = "%Y-%m-%dT%H:%M:%S.%fZ" else: time_format = "%Y-%m-%dT%H:%M:%SZ" return timeutils.parse_strtime(strtime, time_format) try: if timestamp and expiry_time: msg = _("Request must include either Timestamp or Expires," " but cannot contain both") LOG.error(msg) raise exception.InvalidRequest(msg) elif expiry_time: query_time = parse_strtime(expiry_time) return timeutils.is_older_than(query_time, -1) elif timestamp: query_time = parse_strtime(timestamp) # Check if the difference between the timestamp in the request # and the time on our servers is larger than 5 minutes, the # request is too old (or too new). if query_time and expires: return (timeutils.is_older_than(query_time, expires) or timeutils.is_newer_than(query_time, expires)) return False except ValueError: LOG.exception(_("Timestamp is invalid: ")) return True
def _set_route(context, route_table_id, destination_cidr_block, gateway_id, instance_id, network_interface_id, vpc_peering_connection_id, do_replace): route_table = ec2utils.get_db_item(context, route_table_id) vpc = db_api.get_item_by_id(context, route_table['vpc_id']) vpc_ipnet = netaddr.IPNetwork(vpc['cidr_block']) route_ipnet = netaddr.IPNetwork(destination_cidr_block) if route_ipnet in vpc_ipnet: msg = _('Cannot create a more specific route for ' '%(destination_cidr_block)s than local route ' '%(vpc_cidr_block)s in route table %(rtb_id)s') msg = msg % {'rtb_id': route_table_id, 'destination_cidr_block': destination_cidr_block, 'vpc_cidr_block': vpc['cidr_block']} raise exception.InvalidParameterValue(msg) obj_param_count = len([p for p in (gateway_id, network_interface_id, instance_id, vpc_peering_connection_id) if p is not None]) if obj_param_count != 1: msg = _('The request must contain exactly one of gatewayId, ' 'networkInterfaceId, vpcPeeringConnectionId or instanceId') if obj_param_count == 0: raise exception.MissingParameter(msg) else: raise exception.InvalidParameterCombination(msg) rollabck_route_table_state = copy.deepcopy(route_table) if do_replace: route_index, old_route = next( ((i, r) for i, r in enumerate(route_table['routes']) if r['destination_cidr_block'] == destination_cidr_block), (None, None)) if route_index is None: msg = _("There is no route defined for " "'%(destination_cidr_block)s' in the route table. " "Use CreateRoute instead.") msg = msg % {'destination_cidr_block': destination_cidr_block} raise exception.InvalidParameterValue(msg) else: del route_table['routes'][route_index] if gateway_id: gateway = ec2utils.get_db_item(context, gateway_id) if gateway.get('vpc_id') != route_table['vpc_id']: if ec2utils.get_ec2_id_kind(gateway_id) == 'vgw': raise exception.InvalidGatewayIDNotFound(id=gateway['id']) else: # igw raise exception.InvalidParameterValue( _('Route table %(rtb_id)s and network gateway %(igw_id)s ' 'belong to different networks') % {'rtb_id': route_table_id, 'igw_id': gateway_id}) route = {'gateway_id': gateway['id']} elif network_interface_id: network_interface = ec2utils.get_db_item(context, network_interface_id) if network_interface['vpc_id'] != route_table['vpc_id']: msg = _('Route table %(rtb_id)s and interface %(eni_id)s ' 'belong to different networks') msg = msg % {'rtb_id': route_table_id, 'eni_id': network_interface_id} raise exception.InvalidParameterValue(msg) route = {'network_interface_id': network_interface['id']} elif instance_id: # TODO(ft): implement search in DB layer network_interfaces = [eni for eni in db_api.get_items(context, 'eni') if eni.get('instance_id') == instance_id] if len(network_interfaces) == 0: msg = _("Invalid value '%(i_id)s' for instance ID. " "Instance is not in a VPC.") msg = msg % {'i_id': instance_id} raise exception.InvalidParameterValue(msg) elif len(network_interfaces) > 1: raise exception.InvalidInstanceId(instance_id=instance_id) network_interface = network_interfaces[0] if network_interface['vpc_id'] != route_table['vpc_id']: msg = _('Route table %(rtb_id)s and interface %(eni_id)s ' 'belong to different networks') msg = msg % {'rtb_id': route_table_id, 'eni_id': network_interface['id']} raise exception.InvalidParameterValue(msg) route = {'network_interface_id': network_interface['id']} else: raise exception.InvalidRequest('Parameter VpcPeeringConnectionId is ' 'not supported by this implementation') route['destination_cidr_block'] = destination_cidr_block update_target = _get_route_target(route) if do_replace: idempotent_call = False old_target = _get_route_target(old_route) if old_target != update_target: update_target = None else: old_route = next((r for r in route_table['routes'] if r['destination_cidr_block'] == destination_cidr_block), None) idempotent_call = old_route == route if old_route and not idempotent_call: raise exception.RouteAlreadyExists( destination_cidr_block=destination_cidr_block) if not idempotent_call: route_table['routes'].append(route) with common.OnCrashCleaner() as cleaner: db_api.update_item(context, route_table) cleaner.addCleanup(db_api.update_item, context, rollabck_route_table_state) _update_routes_in_associated_subnets(context, cleaner, route_table, update_target=update_target) return True