def test_get_items_by_ids(self): self._setup_items() fake_kind_items = db_api.get_items(self.context, 'fake') fake1_kind_items = db_api.get_items(self.context, 'fake1') item_id = fake_kind_items[0]['id'] other_item_id = db_api.get_items(self.other_context, 'fake')[0]['id'] items = db_api.get_items_by_ids(self.context, []) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, set([])) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, [i['id'] for i in fake_kind_items]) self.assertEqual(2, len(items)) items = db_api.get_items_by_ids( self.context, (fake_kind_items[0]['id'], fake1_kind_items[0]['id'])) self.assertEqual(2, len(items)) items = db_api.get_items_by_ids(self.context, (item_id, )) self.assertEqual(1, len(items)) self.assertEqual(item_id, items[0]['id']) items = db_api.get_items_by_ids(self.context, (other_item_id, )) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, (item_id, other_item_id)) self.assertEqual(1, len(items)) items = db_api.get_items_by_ids( self.context, (fakes.random_ec2_id('fake')), ) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, (item_id, fakes.random_ec2_id('fake'))) self.assertEqual(1, len(items))
def test_get_items_by_ids(self): self._setup_items() fake_kind_items = db_api.get_items(self.context, 'fake') fake1_kind_items = db_api.get_items(self.context, 'fake1') item_id = fake_kind_items[0]['id'] other_item_id = db_api.get_items(self.other_context, 'fake')[0]['id'] items = db_api.get_items_by_ids(self.context, []) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, set([])) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, [i['id'] for i in fake_kind_items]) self.assertEqual(2, len(items)) items = db_api.get_items_by_ids( self.context, (fake_kind_items[0]['id'], fake1_kind_items[0]['id'])) self.assertEqual(2, len(items)) items = db_api.get_items_by_ids(self.context, (item_id,)) self.assertEqual(1, len(items)) self.assertEqual(item_id, items[0]['id']) items = db_api.get_items_by_ids(self.context, (other_item_id,)) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, (item_id, other_item_id)) self.assertEqual(1, len(items)) items = db_api.get_items_by_ids(self.context, (fakes.random_ec2_id('fake')),) self.assertEqual(0, len(items)) items = db_api.get_items_by_ids(self.context, (item_id, fakes.random_ec2_id('fake'))) self.assertEqual(1, len(items))
def get_db_items(context, kind, ec2_ids): if not ec2_ids: return db_api.get_items(context, kind) if not isinstance(ec2_ids, set): ec2_ids = set(ec2_ids) items = db_api.get_items_by_ids(context, ec2_ids) if len(items) < len(ec2_ids): missed_ids = ec2_ids - set((item['id'] for item in items)) params = {'id': next(iter(missed_ids))} raise NOT_FOUND_EXCEPTION_MAP[kind](**params) return items
def _get_active_route_destinations(context, route_table): vpn_connections = {vpn['vpn_gateway_id']: vpn for vpn in db_api.get_items(context, 'vpn')} dst_ids = [route[id_key] for route in route_table['routes'] for id_key in ('gateway_id', 'network_interface_id') if route.get(id_key) is not None] dst_ids.extend(route_table.get('propagating_gateways', [])) destinations = {item['id']: item for item in db_api.get_items_by_ids(context, dst_ids) if (item['vpc_id'] == route_table['vpc_id'] and (ec2utils.get_ec2_id_kind(item['id']) != 'vgw' or item['id'] in vpn_connections))} for vpn in six.itervalues(vpn_connections): if vpn['vpn_gateway_id'] in destinations: destinations[vpn['vpn_gateway_id']]['vpn_connection'] = vpn return destinations
def get_db_items(self): # TODO(ft): we can't get all images from DB per one request due # different kinds. It's need to refactor DB API and ec2utils functions # to work with kind smarter if self.ids: local_images = db_api.get_items_by_ids(self.context, self.ids) else: local_images = sum((db_api.get_items(self.context, kind) for kind in ('ami', 'ari', 'aki')), []) public_images = sum( (db_api.get_public_items(self.context, kind, self.ids) for kind in ('ami', 'ari', 'aki')), []) mapped_ids = [] if self.ids: mapped_ids = [{ 'id': item_id, 'os_id': os_id } for kind in ('ami', 'ari', 'aki') for item_id, os_id in db_api.get_items_ids( self.context, kind, item_ids=self.ids)] # NOTE(ft): mapped_ids must be the first to let complete items from # next lists to override mappings, which do not have item body data images = sum((mapped_ids, local_images, public_images), []) if self.ids: # NOTE(ft): public images, owned by a current user, appear in both # local and public lists of images. Therefore it's not enough to # just compare length of requested and retrieved lists to make sure # that all requested images are retrieved. images_ids = set(i['id'] for i in images) if len(images_ids) < len(self.ids): missed_ids = self.ids - images_ids raise exception.InvalidAMIIDNotFound(id=next(iter(missed_ids))) self.pending_images = { i['id']: i for i in local_images if not i['os_id'] } self.snapshot_ids = dict( (s['os_id'], s['id']) for s in db_api.get_items(self.context, 'snap')) self.local_images_os_ids = set(i['os_id'] for i in local_images) self.ids_dict = {} return images
def get_db_items(self): # TODO(ft): we can't get all images from DB per one request due # different kinds. It's need to refactor DB API and ec2utils functions # to work with kind smarter if self.ids: local_images = db_api.get_items_by_ids(self.context, self.ids) else: local_images = sum((db_api.get_items(self.context, kind) for kind in ('ami', 'ari', 'aki')), []) public_images = sum((db_api.get_public_items(self.context, kind, self.ids) for kind in ('ami', 'ari', 'aki')), []) mapped_ids = [] if self.ids: mapped_ids = [{'id': item_id, 'os_id': os_id} for kind in ('ami', 'ari', 'aki') for item_id, os_id in db_api.get_items_ids( self.context, kind, item_ids=self.ids)] # NOTE(ft): mapped_ids must be the first to let complete items from # next lists to override mappings, which do not have item body data images = sum((mapped_ids, local_images, public_images), []) if self.ids: # NOTE(ft): public images, owned by a current user, appear in both # local and public lists of images. Therefore it's not enough to # just compare length of requested and retrieved lists to make sure # that all requested images are retrieved. images_ids = set(i['id'] for i in images) if len(images_ids) < len(self.ids): missed_ids = self.ids - images_ids raise exception.InvalidAMIIDNotFound(id=next(iter(missed_ids))) self.pending_images = {i['id']: i for i in local_images if not i['os_id']} self.snapshot_ids = dict( (s['os_id'], s['id']) for s in db_api.get_items(self.context, 'snap')) self.local_images_os_ids = set(i['os_id'] for i in local_images) self.ids_dict = {} return images
def create_network_interface(context, subnet_id, private_ip_address=None, private_ip_addresses=None, secondary_private_ip_address_count=None, description=None, security_group_id=None): subnet = ec2utils.get_db_item(context, subnet_id) if subnet is None: raise exception.InvalidSubnetIDNotFound(id=subnet_id) neutron = clients.neutron(context) os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] # NOTE(Alex): Combine and check ip addresses. Neutron will accept # ip_address as a parameter for specified address and subnet_id for # address to auto-allocate. # TODO(Alex): Implement better diagnostics. subnet_ipnet = netaddr.IPNetwork(os_subnet['cidr']) if not private_ip_addresses: private_ip_addresses = [] if private_ip_address is not None: private_ip_addresses.insert(0, { 'private_ip_address': private_ip_address, 'primary': True }) primary_ip = None fixed_ips = [] for ip in private_ip_addresses: ip_address = netaddr.IPAddress(ip['private_ip_address']) if ip_address not in subnet_ipnet: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddresses', reason='IP address is out of the subnet range') if ip.get('primary', False): if primary_ip is not None: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddresses', reason='More than one primary ip is supplied') else: primary_ip = str(ip_address) fixed_ips.insert(0, {'ip_address': primary_ip}) else: fixed_ips.append({'ip_address': str(ip_address)}) if not fixed_ips and not secondary_private_ip_address_count: secondary_private_ip_address_count = 1 if secondary_private_ip_address_count is None: secondary_private_ip_address_count = 0 if secondary_private_ip_address_count > 0: for _i in range(secondary_private_ip_address_count): fixed_ips.append({'subnet_id': os_subnet['id']}) vpc = db_api.get_item_by_id(context, subnet['vpc_id']) vpc_id = vpc['id'] dhcp_options_id = vpc.get('dhcp_options_id', None) if not security_group_id: default_groups = security_group_api.describe_security_groups( context, filter=[{ 'name': 'vpc-id', 'value': [vpc_id] }, { 'name': 'group-name', 'value': ['default'] }])['securityGroupInfo'] security_group_id = [ default_group['groupId'] for default_group in default_groups ] security_groups = db_api.get_items_by_ids(context, security_group_id) if any(security_group['vpc_id'] != vpc['id'] for security_group in security_groups): msg = _('You have specified two resources that belong to ' 'different networks.') raise exception.InvalidGroupNotFound(msg) os_groups = [security_group['os_id'] for security_group in security_groups] with common.OnCrashCleaner() as cleaner: os_port_body = { 'port': { 'network_id': os_subnet['network_id'], 'security_groups': os_groups } } os_port_body['port']['fixed_ips'] = fixed_ips try: os_port = neutron.create_port(os_port_body)['port'] except (neutron_exception.IpAddressGenerationFailureClient, neutron_exception.OverQuotaClient): raise exception.InsufficientFreeAddressesInSubnet() except (neutron_exception.IpAddressInUseClient, neutron_exception.BadRequest) as ex: # NOTE(ft): AWS returns InvalidIPAddress.InUse for a primary IP # address, but InvalidParameterValue for secondary one. # AWS returns PrivateIpAddressLimitExceeded, but Neutron does # general InvalidInput (converted to BadRequest) in the same case. msg = _('Specified network interface parameters are invalid. ' 'Reason: %(reason)s') % { 'reason': ex.message } raise exception.InvalidParameterValue(msg) cleaner.addCleanup(neutron.delete_port, os_port['id']) if primary_ip is None: primary_ip = os_port['fixed_ips'][0]['ip_address'] network_interface = db_api.add_item( context, 'eni', { 'os_id': os_port['id'], 'vpc_id': subnet['vpc_id'], 'subnet_id': subnet['id'], 'description': description, 'private_ip_address': primary_ip }) cleaner.addCleanup(db_api.delete_item, context, network_interface['id']) network_interface_id = network_interface['id'] neutron.update_port(os_port['id'], {'port': { 'name': network_interface_id }}) if dhcp_options_id: dhcp_options._add_dhcp_opts_to_port( context, db_api.get_item_by_id(context, dhcp_options_id), network_interface, os_port) security_groups = security_group_api._format_security_groups_ids_names( context) return { 'networkInterface': _format_network_interface(context, network_interface, os_port, security_groups=security_groups) }
def create_network_interface(context, subnet_id, private_ip_address=None, private_ip_addresses=None, secondary_private_ip_address_count=None, description=None, security_group_id=None): subnet = ec2utils.get_db_item(context, subnet_id) if subnet is None: raise exception.InvalidSubnetIDNotFound(id=subnet_id) neutron = clients.neutron(context) os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] # NOTE(Alex): Combine and check ip addresses. Neutron will accept # ip_address as a parameter for specified address and subnet_id for # address to auto-allocate. # TODO(Alex): Implement better diagnostics. subnet_ipnet = netaddr.IPNetwork(os_subnet['cidr']) if not private_ip_addresses: private_ip_addresses = [] if private_ip_address is not None: private_ip_addresses.insert(0, {'private_ip_address': private_ip_address, 'primary': True}) primary_ip = None fixed_ips = [] for ip in private_ip_addresses: ip_address = netaddr.IPAddress(ip['private_ip_address']) if ip_address not in subnet_ipnet: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddresses', reason='IP address is out of the subnet range') if ip.get('primary', False): if primary_ip is not None: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddresses', reason='More than one primary ip is supplied') else: primary_ip = str(ip_address) fixed_ips.insert(0, {'ip_address': primary_ip}) else: fixed_ips.append({'ip_address': str(ip_address)}) if not fixed_ips and not secondary_private_ip_address_count: secondary_private_ip_address_count = 1 if secondary_private_ip_address_count is None: secondary_private_ip_address_count = 0 if secondary_private_ip_address_count > 0: for _i in range(secondary_private_ip_address_count): fixed_ips.append({'subnet_id': os_subnet['id']}) vpc = db_api.get_item_by_id(context, subnet['vpc_id']) vpc_id = vpc['id'] dhcp_options_id = vpc.get('dhcp_options_id', None) if not security_group_id: default_groups = security_group_api.describe_security_groups( context, filter=[{'name': 'vpc-id', 'value': [vpc_id]}, {'name': 'group-name', 'value': ['default']}] )['securityGroupInfo'] security_group_id = [default_group['groupId'] for default_group in default_groups] security_groups = db_api.get_items_by_ids(context, security_group_id) if any(security_group['vpc_id'] != vpc['id'] for security_group in security_groups): msg = _('You have specified two resources that belong to ' 'different networks.') raise exception.InvalidGroupNotFound(msg) os_groups = [security_group['os_id'] for security_group in security_groups] with common.OnCrashCleaner() as cleaner: os_port_body = {'port': {'network_id': os_subnet['network_id'], 'security_groups': os_groups}} os_port_body['port']['fixed_ips'] = fixed_ips try: os_port = neutron.create_port(os_port_body)['port'] except (neutron_exception.IpAddressGenerationFailureClient, neutron_exception.OverQuotaClient): raise exception.InsufficientFreeAddressesInSubnet() except (neutron_exception.IpAddressInUseClient, neutron_exception.BadRequest) as ex: # NOTE(ft): AWS returns InvalidIPAddress.InUse for a primary IP # address, but InvalidParameterValue for secondary one. # AWS returns PrivateIpAddressLimitExceeded, but Neutron does # general InvalidInput (converted to BadRequest) in the same case. msg = _('Specified network interface parameters are invalid. ' 'Reason: %(reason)s') % {'reason': ex.message} raise exception.InvalidParameterValue(msg) cleaner.addCleanup(neutron.delete_port, os_port['id']) if primary_ip is None: primary_ip = os_port['fixed_ips'][0]['ip_address'] network_interface = db_api.add_item(context, 'eni', {'os_id': os_port['id'], 'vpc_id': subnet['vpc_id'], 'subnet_id': subnet['id'], 'description': description, 'private_ip_address': primary_ip}) cleaner.addCleanup(db_api.delete_item, context, network_interface['id']) network_interface_id = network_interface['id'] neutron.update_port(os_port['id'], {'port': {'name': network_interface_id}}) if dhcp_options_id: dhcp_options._add_dhcp_opts_to_port( context, db_api.get_item_by_id(context, dhcp_options_id), network_interface, os_port) security_groups = security_group_api._format_security_groups_ids_names( context) return {'networkInterface': _format_network_interface(context, network_interface, os_port, security_groups=security_groups)}