def update_floatingip(self, context, fpid, floatingip): port_id_specified = 'port_id' in floatingip['floatingip'] if not port_id_specified: LOG.error(_LE("port_id key is not found in %s"), floatingip) raise exc.PortNotFound(port_id=None) port_id = floatingip['floatingip'].get('port_id') try: if port_id_specified and not port_id: floating = context.session.query(l3_db.FloatingIP).filter_by( id=fpid).one() self._delete_nat(context, floating) except sa.orm.exc.NoResultFound: raise exc.PortNotFound(port_id=port_id) ret = super(NECNWAL3Plugin, self).update_floatingip( context, fpid, floatingip) try: if port_id_specified and port_id: floating = context.session.query(l3_db.FloatingIP).filter_by( id=fpid).one() tenant_id = nwa_l3_db.get_tenant_id_by_router( context.session, floating['router_id'] ) nwa_tenant_id = nwa_com_utils.get_nwa_tenant_id(tenant_id) fl_data = { 'floating_ip_address': floating['floating_ip_address'], 'fixed_ip_address': floating['fixed_ip_address'], 'id': fpid, 'device_id': floating['router_id'], 'floating_network_id': floating['floating_network_id'], 'tenant_id': floating['tenant_id'], 'floating_port_id': floating['floating_port_id'] } LOG.info(_LI('setting_nat fl_data is %s'), fl_data) proxy = self._get_nwa_proxy(self, tenant_id) proxy.setting_nat( context, tenant_id=tenant_id, nwa_tenant_id=nwa_tenant_id, floating=fl_data ) except sa.orm.exc.NoResultFound: raise exc.PortNotFound(port_id=port_id) return ret
def disassociate_port(context, id, ip_address_id): """Disassociates a port from an IP address. : param context: neutron api request context : param id: UUID representing the port to disassociate. : param ip_address_id: UUID representing the IP address to disassociate. """ LOG.info("disassociate_port %s for tenant %s ip_address_id %s" % (id, context.tenant_id, ip_address_id)) port = db_api.port_find(context, id=id, ip_address_id=[ip_address_id], scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=id, net_id='') the_address = [ address for address in port["ip_addresses"] if address["id"] == ip_address_id ][0] port["ip_addresses"] = [ address for address in port["ip_addresses"] if address.id != ip_address_id ] if len(the_address["ports"]) == 0: the_address["deallocated"] = 1 return v._make_port_dict(port)
def get_port_for_ip_address(context, ip_id, id, fields=None): """Retrieve a port. : param context: neutron api request context : param id: UUID representing the port to fetch. : param fields: a list of strings that are valid keys in a port dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_port %s for tenant %s fields %s" % (id, context.tenant_id, fields)) addr = db_api.ip_address_find(context, id=ip_id, scope=db_api.ONE) if not addr: raise quark_exceptions.IpAddressNotFound(addr_id=ip_id) filters = {'ip_address_id': [ip_id]} results = db_api.port_find(context, id=id, fields=fields, scope=db_api.ONE, **filters) if not results: raise exceptions.PortNotFound(port_id=id, net_id='') return v._make_port_for_ip_dict(addr, results)
def delete_port(context, id): """Delete a port. : param context: neutron api request context : param id: UUID representing the port to delete. """ LOG.info("delete_port %s for tenant %s" % (id, context.tenant_id)) port = db_api.port_find(context, id=id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(net_id=id) backend_key = port["backend_key"] mac_address = netaddr.EUI(port["mac_address"]).value ipam_driver = ipam.IPAM_REGISTRY.get_strategy( port["network"]["ipam_strategy"]) ipam_driver.deallocate_mac_address(context, mac_address) ipam_driver.deallocate_ips_by_port( context, port, ipam_reuse_after=CONF.QUARK.ipam_reuse_after) net_driver = registry.DRIVER_REGISTRY.get_driver( port.network["network_plugin"]) net_driver.delete_port(context, backend_key, device_id=port["device_id"], mac_address=port["mac_address"]) with context.session.begin(): db_api.port_delete(context, port)
def _set_port_status(self, port_id, status): session = db.get_session() try: port = session.query(models_v2.Port).filter_by(id=port_id).one() port['status'] = status session.flush() except sqlexc.NoResultFound: raise exceptions.PortNotFound(port_id=port_id)
def set_port_status(session, port_id, status): try: port = session.query(models_v2.Port).filter_by(id=port_id).one() port['status'] = status session.merge(port) session.flush() except orm_exc.NoResultFound: raise n_exc.PortNotFound(port_id=port_id)
def test_update_device_up_with_dvr_when_port_not_found(self): kwargs = { 'agent_id': 'foo_agent', 'device': 'foo_device' } self.l3plugin.dvr_vmarp_table_update.side_effect = ( exceptions.PortNotFound(port_id='foo_port_id')) self._test_update_device_up(['router', 'dvr'], kwargs) self.assertTrue(self.l3plugin.dvr_vmarp_table_update.call_count)
def set_port_status(self, port_id, status): session = db_api.get_session() try: port = session.query(models_v2.Port).filter_by(id=port_id).one() port['status'] = status session.merge(port) session.flush() except exc.NoResultFound: raise q_exc.PortNotFound(port_id=port_id)
def update_port(self, context, id, port): attrs = port['port'] need_port_update_notify = False session = context.session changed_fixed_ips = 'fixed_ips' in port['port'] with session.begin(subtransactions=True): try: port_db = (session.query( models_v2.Port).enable_eagerloads(False).filter_by( id=id).with_lockmode('update').one()) except sa_exc.NoResultFound: raise exc.PortNotFound(port_id=id) original_port = self._make_port_dict(port_db) updated_port = super(Ml2Plugin, self).update_port(context, id, port) if self.is_address_pairs_attribute_updated(original_port, port): self._delete_allowed_address_pairs(context, id) self._process_create_allowed_address_pairs( context, updated_port, port['port'][addr_pair.ADDRESS_PAIRS]) need_port_update_notify = True elif changed_fixed_ips: self._check_fixed_ips_and_address_pairs_no_overlap( context, updated_port) need_port_update_notify |= self.update_security_group_on_port( context, id, port, original_port, updated_port) network = self.get_network(context, original_port['network_id']) need_port_update_notify |= self._update_extra_dhcp_opts_on_port( context, id, port, updated_port) mech_context = driver_context.PortContext( self, context, updated_port, network, original_port=original_port) need_port_update_notify |= self._process_port_binding( mech_context, attrs) self.mechanism_manager.update_port_precommit(mech_context) # TODO(apech) - handle errors raised by update_port, potentially # by re-calling update_port with the previous attributes. For # now the error is propogated to the caller, which is expected to # either undo/retry the operation or delete the resource. self.mechanism_manager.update_port_postcommit(mech_context) need_port_update_notify |= self.is_security_group_member_updated( context, original_port, updated_port) if original_port['admin_state_up'] != updated_port['admin_state_up']: need_port_update_notify = True if need_port_update_notify: self._notify_port_updated(mech_context) return updated_port
def test_delete_floatingip_deleted_port_no_notify(self): port_id = 'bee50827-bcee-4cc8-91c1-a27b0ce54222' with mock.patch.object( self.nova_notifier._plugin_ref, 'get_port', side_effect=n_exc.PortNotFound(port_id=port_id)): returned_obj = {'floatingip': {'port_id': port_id}} event = self.nova_notifier.create_port_changed_event( 'delete_floatingip', {}, returned_obj) self.assertIsNone(event)
def post_update_port(context, id, port): LOG.info("post_update_port %s for tenant %s" % (id, context.tenant_id)) if not port.get("port"): raise exceptions.BadRequest(resource="ports", msg="Port body required") port_db = db_api.port_find(context, id=id, scope=db_api.ONE) if not port_db: raise exceptions.PortNotFound(port_id=id, net_id="") port = port["port"] if "fixed_ips" in port and port["fixed_ips"]: for ip in port["fixed_ips"]: address = None ipam_driver = ipam.IPAM_REGISTRY.get_strategy( port_db["network"]["ipam_strategy"]) if ip: if "ip_id" in ip: ip_id = ip["ip_id"] address = db_api.ip_address_find( context, id=ip_id, tenant_id=context.tenant_id, scope=db_api.ONE) elif "ip_address" in ip: ip_address = ip["ip_address"] net_address = netaddr.IPAddress(ip_address) address = db_api.ip_address_find( context, ip_address=net_address, network_id=port_db["network_id"], tenant_id=context.tenant_id, scope=db_api.ONE) if not address: address = ipam_driver.allocate_ip_address( context, port_db["network_id"], id, CONF.QUARK.ipam_reuse_after, ip_address=ip_address) else: address = ipam_driver.allocate_ip_address( context, port_db["network_id"], id, CONF.QUARK.ipam_reuse_after) address["deallocated"] = 0 already_contained = False for port_address in port_db["ip_addresses"]: if address["id"] == port_address["id"]: already_contained = True break if not already_contained: port_db["ip_addresses"].append(address) return v._make_port_dict(port_db)
def set_port_status(port_id, status): """Set the port status.""" LOG.debug(_("Set_port_status as %s called"), status) session = db.get_session() try: port = session.query(models_v2.Port).filter_by(id=port_id).one() port['status'] = status session.merge(port) session.flush() except exc.NoResultFound: raise q_exc.PortNotFound(port_id=port_id)
def update_port(context, id, port): """Update values of a port. : param context: neutron api request context : param id: UUID representing the port to update. : param port: dictionary with keys indicating fields to update. valid keys are those that have a value of True for 'allow_put' as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. """ LOG.info("update_port %s for tenant %s" % (id, context.tenant_id)) port_db = db_api.port_find(context, id=id, scope=db_api.ONE) if not port_db: raise exceptions.PortNotFound(port_id=id) address_pairs = [] fixed_ips = port["port"].pop("fixed_ips", None) if fixed_ips: ipam_driver.deallocate_ip_address( context, port_db, ipam_reuse_after=CONF.QUARK.ipam_reuse_after) addresses = [] for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id and ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id and ip_address required") # Note: we don't allow overlapping subnets, thus subnet_id is # ignored. addresses.append( ipam_driver.allocate_ip_address(context, port_db["network_id"], id, CONF.QUARK.ipam_reuse_after, ip_address=ip_address)) port["port"]["addresses"] = addresses mac_address_string = str( netaddr.EUI(port_db.mac_address, dialect=netaddr.mac_unix)) address_pairs = [{ 'mac_address': mac_address_string, 'ip_address': address.get('address_readable', '') } for address in addresses] group_ids, security_groups = v.make_security_group_list( context, port["port"].pop("security_groups", None)) net_driver.update_port(context, port_id=port_db.backend_key, security_groups=group_ids, allowed_pairs=address_pairs) port["port"]["security_groups"] = security_groups port = db_api.port_update(context, port_db, **port["port"]) return v._make_port_dict(port)
def test_update_routers_states_port_not_found(self): router1 = self._create_router() self._bind_router(router1['id']) port = {'id': 'foo', 'device_id': router1['id']} with mock.patch.object(self.core_plugin, 'get_ports', return_value=[port]): with mock.patch.object( self.core_plugin, 'update_port', side_effect=n_exc.PortNotFound(port_id='foo')): states = {router1['id']: 'active'} self.plugin.update_routers_states( self.admin_ctx, states, self.agent1['host'])
def test_delete_resource_port_handle_port_not_found(self): mgmt_port_id = 'fake_port_id' mocked_plugin = mock.MagicMock() mock_ctx = mock.MagicMock() mocked_plugin.delete_port = mock.MagicMock( side_effect=n_exc.PortNotFound(port_id=mgmt_port_id)) with mock.patch.object(VIFHotPlugPluggingDriver, '_core_plugin') as plugin: plugin.__get__ = mock.MagicMock(return_value=mocked_plugin) vif_plugging_driver = VIFHotPlugPluggingDriver() vif_plugging_driver._delete_resource_port(mock_ctx, mgmt_port_id) self.assertEqual(1, mocked_plugin.delete_port.call_count)
def clean_by_port(self, port): """Detach port from policy and cleanup data we don't need anymore.""" port_id = port['port_id'] if port_id in self.port_policies: del self.port_policies[port_id] for qos_policy_id, port_dict in self.qos_policy_ports.items(): if port_id in port_dict: del port_dict[port_id] if not port_dict: self._clean_policy_info(qos_policy_id) return raise exceptions.PortNotFound(port_id=port['port_id'])
def diagnose_port(context, id, fields): if not context.is_admin: raise exceptions.NotAuthorized() if id == "*": return {'ports': [_diag_port(context, port, fields) for port in db_api.port_find(context).all()]} db_port = db_api.port_find(context, id=id, scope=db_api.ONE) if not db_port: raise exceptions.PortNotFound(port_id=id, net_id='') port = _diag_port(context, db_port, fields) return {'ports': port}
def test_synchronize_port_not_found_in_db_no_raise(self): ctx = context.get_admin_context() with self._populate_data(ctx): # Put a port down to verify synchronization lp_uuid = self.fc._fake_lswitch_lport_dict.keys()[0] lport = self.fc._fake_lswitch_lport_dict[lp_uuid] q_port_id = self._get_tag_dict(lport['tags'])['q_port_id'] lport['status'] = 'true' q_port_data = self._plugin._get_port(ctx, q_port_id) with mock.patch.object(self._plugin, '_get_port') as _get_port: _get_port.side_effect = n_exc.PortNotFound( port_id=q_port_data['id']) self._plugin._synchronizer.synchronize_port(ctx, q_port_data)
def set_port_status(port_id, status): """ Set the status of the port. :param port_id: UUID representing the port :param status: string representing the new status """ db_session = db.get_session() try: port = db_session.query(models_v2.Port).filter_by(id=port_id).one() port.status = status except exc.NoResultFound: raise q_exc.PortNotFound(port_id=port_id)
def create_ip_address(context, ip_address): LOG.info("create_ip_address for tenant %s" % context.tenant_id) port = None ip_dict = ip_address["ip_address"] port_ids = ip_dict.get('port_ids') network_id = ip_dict.get('network_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') ports = [] if device_ids and not network_id: raise exceptions.BadRequest( resource="ip_addresses", msg="network_id is required if device_ids are supplied.") with context.session.begin(): if network_id and device_ids: for device_id in device_ids: port = db_api.port_find( context, network_id=network_id, device_id=device_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) if not ports: raise exceptions.PortNotFound(port_id=port_ids, net_id=network_id) address = ipam_driver.allocate_ip_address( context, port['network_id'], port['id'], CONF.QUARK.ipam_reuse_after, ip_version, ip_addresses=[ip_address]) for port in ports: port["ip_addresses"].append(address) return v._make_ip_dict(address)
def delete_port(context, id): """Delete a port. : param context: neutron api request context : param id: UUID representing the port to delete. """ LOG.info("delete_port %s for tenant %s" % (id, context.tenant_id)) port = db_api.port_find(context, id=id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(net_id=id) backend_key = port["backend_key"] mac_address = netaddr.EUI(port["mac_address"]).value ipam_driver.deallocate_mac_address(context, mac_address) ipam_driver.deallocate_ip_address( context, port, ipam_reuse_after=CONF.QUARK.ipam_reuse_after) db_api.port_delete(context, port) net_driver.delete_port(context, backend_key)
def test_prevent_l3_port_deletion_port_not_found(self, gp): # port not found doesn't prevent gp.return_value.get_port.side_effect = n_exc.PortNotFound(port_id='1') self.db.prevent_l3_port_deletion(None, None)
def test_port_delete_helper_tolerates_failure(self): plugin = manager.NeutronManager.get_plugin() with mock.patch.object(plugin, "delete_port", side_effect=exc.PortNotFound(port_id="123")): plugin._delete_ports(None, [mock.MagicMock()])
def create_floatingip(context, content): """Allocate or reallocate a floating IP. :param context: neutron api request context. :param content: dictionary describing the floating ip, with keys as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. All keys will be populated. :returns: Dictionary containing details for the new floating IP. If values are declared in the fields parameter, then only those keys will be present. """ LOG.info('create_floatingip %s for tenant %s and body %s' % (id, context.tenant_id, content)) tenant_id = content.get('tenant_id') network_id = content.get('floating_network_id') fixed_ip_address = content.get('fixed_ip_address') ip_address = content.get('floating_ip_address') port_id = content.get('port_id') if not tenant_id: tenant_id = context.tenant_id if not network_id: raise exceptions.BadRequest(resource='floating_ip', msg='floating_network_id is required.') network = db_api.network_find(context, id=network_id, scope=db_api.ONE) if not network: raise exceptions.NetworkNotFound(net_id=network_id) fixed_ip = None port = None if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if not port.ip_addresses or len(port.ip_addresses) == 0: raise qex.NoAvailableFixedIpsForPort(port_id=port_id) if not fixed_ip_address: fixed_ip = _get_next_available_fixed_ip(port) if not fixed_ip: raise qex.NoAvailableFixedIpsForPort( port_id=port_id) else: fixed_ip = next((ip for ip in port.ip_addresses if (ip['address_readable'] == fixed_ip_address and ip.get('address_type') == ip_types.FIXED)), None) if not fixed_ip: raise qex.FixedIpDoesNotExistsForPort( fixed_ip=fixed_ip_address, port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get('address_type') == ip_types.FLOATING and ip.fixed_ip['address_readable'] == fixed_ip_address)): raise qex.PortAlreadyContainsFloatingIp( port_id=port_id) new_addresses = [] ip_addresses = [] if ip_address: ip_addresses.append(ip_address) seg_name = CONF.QUARK.floating_ip_segment_name strategy_name = CONF.QUARK.floating_ip_ipam_strategy if strategy_name.upper() == 'NETWORK': strategy_name = network.get("ipam_strategy") ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name) ipam_driver.allocate_ip_address(context, new_addresses, network_id, port_id, CONF.QUARK.ipam_reuse_after, seg_name, version=4, ip_addresses=ip_addresses, address_type=ip_types.FLOATING) flip = new_addresses[0] if fixed_ip and port: context.session.begin() try: flip = db_api.port_associate_ip(context, [port], flip, [port_id]) flip = db_api.floating_ip_associate_fixed_ip(context, flip, fixed_ip) flip_driver = registry.DRIVER_REGISTRY.get_driver() flip_driver.register_floating_ip(flip, port, fixed_ip) context.session.commit() except Exception: context.session.rollback() raise return v._make_floating_ip_dict(flip, port_id)
def update_floatingip(context, id, content): """Update an existing floating IP. :param context: neutron api request context. :param id: id of the floating ip :param content: dictionary with keys indicating fields to update. valid keys are those that have a value of True for 'allow_put' as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. :returns: Dictionary containing details for the new floating IP. If values are declared in the fields parameter, then only those keys will be present. """ LOG.info('update_floatingip %s for tenant %s and body %s' % (id, context.tenant_id, content)) if 'port_id' not in content: raise exceptions.BadRequest(resource='floating_ip', msg='port_id is required.') port_id = content.get('port_id') port = None fixed_ip = None current_port = None context.session.begin() try: flip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE) if not flip: raise qex.FloatingIpNotFound(id=id) current_ports = flip.ports if current_ports and len(current_ports) > 0: current_port = current_ports[0] if not port_id and not current_port: raise qex.FloatingIpUpdateNoPortIdSupplied() if port_id: port = db_api.port_find(context, id=port_id, scope=db_api.ONE) if not port: raise exceptions.PortNotFound(port_id=port_id) if any(ip for ip in port.ip_addresses if (ip.get('address_type') == ip_types.FLOATING)): raise qex.PortAlreadyContainsFloatingIp(port_id=port_id) if current_port and current_port.id == port_id: d = dict(flip_id=id, port_id=port_id) raise qex.PortAlreadyAssociatedToFloatingIp(**d) fixed_ip = _get_next_available_fixed_ip(port) LOG.info('new fixed ip: %s' % fixed_ip) if not fixed_ip: raise qex.NoAvailableFixedIpsForPort(port_id=port_id) LOG.info('current ports: %s' % current_ports) if current_port: flip = db_api.port_disassociate_ip(context, [current_port], flip) if flip.fixed_ip: flip = db_api.floating_ip_disassociate_fixed_ip(context, flip) if port: flip = db_api.port_associate_ip(context, [port], flip, [port_id]) flip = db_api.floating_ip_associate_fixed_ip(context, flip, fixed_ip) flip_driver = registry.DRIVER_REGISTRY.get_driver() if port: if current_port: flip_driver.update_floating_ip(flip, port, fixed_ip) else: flip_driver.register_floating_ip(flip, port, fixed_ip) else: flip_driver.remove_floating_ip(flip) context.session.commit() except (qex.RegisterFloatingIpFailure, qex.RemoveFloatingIpFailure): context.session.rollback() raise # Note(alanquillin) The ports parameters on the model is not # properly getting cleaned up when removed. Manually cleaning them up. # Need to fix the db api to correctly update the model. if not port: flip.ports = [] return v._make_floating_ip_dict(flip, port_id)
def test_update_device_up_notify_not_sent_with_port_not_found(self): self.plugin._get_port.side_effect = (exceptions.PortNotFound( port_id='foo_port_id')) notify = self._test_update_device_up() self.assertFalse(notify.call_count)
def test_get_dhcp_port_create_new_with_failure_on_port_update(self): self._test_get_dhcp_port_create_new( update_port=n_exc.PortNotFound(port_id='foo'))
def _get_port(self, context, id): try: port = self._get_by_id(context, models_v2.Port, id) except exc.NoResultFound: raise n_exc.PortNotFound(port_id=id) return port
def update_port(context, id, port): """Update values of a port. : param context: neutron api request context : param id: UUID representing the port to update. : param port: dictionary with keys indicating fields to update. valid keys are those that have a value of True for 'allow_put' as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. """ LOG.info("update_port %s for tenant %s" % (id, context.tenant_id)) port_db = db_api.port_find(context, id=id, scope=db_api.ONE) if not port_db: raise exceptions.PortNotFound(port_id=id) port_dict = port["port"] fixed_ips = port_dict.pop("fixed_ips", None) admin_only = ["mac_address", "device_owner", "bridge", "admin_state_up", "device_id"] always_filter = ["network_id", "backend_key"] utils.filter_body(context, port_dict, admin_only=admin_only, always_filter=always_filter) # Pre-check the requested fixed_ips before making too many db trips. # Note that this is the only check we need, since this call replaces # the entirety of the IP addresses document if fixed_ips are provided. if fixed_ips: quota.QUOTAS.limit_check(context, context.tenant_id, fixed_ips_per_port=len(fixed_ips)) # TODO(anyone): security groups are not currently supported on port create, # nor on isolated networks today. Please see RM8615 new_security_groups = utils.pop_param(port_dict, "security_groups") if new_security_groups is not None: if not STRATEGY.is_parent_network(port_db["network_id"]): raise q_exc.TenantNetworkSecurityGroupsNotImplemented() if new_security_groups is not None and not port_db["device_id"]: raise q_exc.SecurityGroupsRequireDevice() group_ids, security_group_mods = _make_security_group_list( context, new_security_groups) quota.QUOTAS.limit_check(context, context.tenant_id, security_groups_per_port=len(group_ids)) if fixed_ips is not None: # NOTE(mdietz): we want full control over IPAM since # we're allocating by subnet instead of # network. ipam_driver = ipam.IPAM_REGISTRY.get_strategy( ipam.QuarkIpamANY.get_name()) addresses, subnet_ids = [], [] ip_addresses = {} for fixed_ip in fixed_ips: subnet_id = fixed_ip.get("subnet_id") ip_address = fixed_ip.get("ip_address") if not (subnet_id or ip_address): raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id or ip_address required") if ip_address and not subnet_id: raise exceptions.BadRequest( resource="fixed_ips", msg="subnet_id required for ip_address allocation") if subnet_id and ip_address: ip_netaddr = netaddr.IPAddress(ip_address).ipv6() ip_addresses[ip_netaddr] = subnet_id else: subnet_ids.append(subnet_id) port_ips = set([netaddr.IPAddress(int(a["address"])) for a in port_db["ip_addresses"]]) new_ips = set([a for a in ip_addresses.keys()]) ips_to_allocate = list(new_ips - port_ips) ips_to_deallocate = list(port_ips - new_ips) for ip in ips_to_allocate: if ip in ip_addresses: # NOTE: Fix for RM10187 - we were losing the list of IPs if # more than one IP was to be allocated. Track an # aggregate list instead, and add it to the running total # after each allocate allocated = [] ipam_driver.allocate_ip_address( context, allocated, port_db["network_id"], port_db["id"], reuse_after=None, ip_addresses=[ip], subnets=[ip_addresses[ip]]) addresses.extend(allocated) for ip in ips_to_deallocate: ipam_driver.deallocate_ips_by_port( context, port_db, ip_address=ip) for subnet_id in subnet_ids: ipam_driver.allocate_ip_address( context, addresses, port_db["network_id"], port_db["id"], reuse_after=CONF.QUARK.ipam_reuse_after, subnets=[subnet_id]) # Need to return all existing addresses and the new ones if addresses: port_dict["addresses"] = port_db["ip_addresses"] port_dict["addresses"].extend(addresses) net_driver = registry.DRIVER_REGISTRY.get_driver( port_db.network["network_plugin"]) # TODO(anyone): What do we want to have happen here if this fails? Is it # ok to continue to keep the IPs but fail to apply security # groups? Is there a clean way to have a multi-status? Since # we're in a beta-y status, I'm going to let this sit for # a future patch where we have time to solve it well. kwargs = {} if new_security_groups is not None: kwargs["security_groups"] = security_group_mods net_driver.update_port(context, port_id=port_db["backend_key"], mac_address=port_db["mac_address"], device_id=port_db["device_id"], **kwargs) port_dict["security_groups"] = security_group_mods with context.session.begin(): port = db_api.port_update(context, port_db, **port_dict) # NOTE(mdietz): fix for issue 112, we wanted the IPs to be in # allocated_at order, so get a fresh object every time if port_db in context.session: context.session.expunge(port_db) port_db = db_api.port_find(context, id=id, scope=db_api.ONE) return v._make_port_dict(port_db)
def get_port_db(self, context, port_id): try: port = self._get_by_id(context, netforce_model.Port, port_id) except orm_exc.NoResultFound: raise n_exc.PortNotFound(port_id=port_id) return port