def _subnet_create(self, context, subnet, clean_on_err=True): if subnet['enable_dhcp']: network_id = subnet['network_id'] # Create port for DHCP service dhcp_port = { "name": "", "admin_state_up": True, "device_id": "", "device_owner": const.DEVICE_OWNER_DHCP, "network_id": network_id, "tenant_id": subnet["tenant_id"], "mac_address": attr.ATTR_NOT_SPECIFIED, "fixed_ips": [{ "subnet_id": subnet['id'] }] } try: # This will end up calling handle_port_dhcp_access # down below as well as handle_port_metadata_access self.plugin.create_port(context, {'port': dhcp_port}) except p_exc.PortConfigurationError as e: LOG.error( _LE("Error while creating subnet %(cidr)s for " "network %(network)s. Please, contact " "administrator"), { "cidr": subnet["cidr"], "network": network_id }) db_base_plugin_v2.NeutronDbPluginV2.delete_port( self.plugin, context, e.port_id) if clean_on_err: self.plugin.delete_subnet(context, subnet['id']) raise n_exc.Conflict()
def _setup_existing_dhcp_port(self, network, device_id, dhcp_subnets): """Set up the existing DHCP port, if there is one.""" # To avoid pylint thinking that port might be undefined after # the following loop... port = None # Look for an existing DHCP port for this network. for port in network.ports: port_device_id = getattr(port, 'device_id', None) if port_device_id == device_id: # If using gateway IPs on this port, we can skip the # following code, whose purpose is just to review and # update the Neutron-allocated IP addresses for the # port. if self.driver.use_gateway_ips: return port # Otherwise break out, as we now have the DHCP port # whose subnets and addresses we need to review. break else: return None # Compare what the subnets should be against what is already # on the port. dhcp_enabled_subnet_ids = set(dhcp_subnets) port_subnet_ids = set(ip.subnet_id for ip in port.fixed_ips) # If those differ, we need to call update. if dhcp_enabled_subnet_ids != port_subnet_ids: # Collect the subnets and fixed IPs that the port already # has, for subnets that are still in the DHCP-enabled set. wanted_fixed_ips = [] for fixed_ip in port.fixed_ips: if fixed_ip.subnet_id in dhcp_enabled_subnet_ids: wanted_fixed_ips.append({ 'subnet_id': fixed_ip.subnet_id, 'ip_address': fixed_ip.ip_address }) # Add subnet IDs for new DHCP-enabled subnets. wanted_fixed_ips.extend( dict(subnet_id=s) for s in dhcp_enabled_subnet_ids - port_subnet_ids) # Update the port to have the calculated subnets and fixed # IPs. The Neutron server will allocate a fresh IP for # each subnet that doesn't already have one. port = self.plugin.update_dhcp_port(port.id, { 'port': { 'network_id': network.id, 'fixed_ips': wanted_fixed_ips } }) if not port: raise exceptions.Conflict() return port
def setup_dhcp_port(self, network): """Create/update DHCP port for the host if needed and return port.""" # The ID that the DHCP port will have (or already has). device_id = self.get_device_id(network) # Get the set of DHCP-enabled subnets on this network. dhcp_subnets = { subnet.id: subnet for subnet in network.subnets if subnet.enable_dhcp } # There are 3 cases: either the DHCP port already exists (but # might need to be updated for a changed set of subnets); or # some other code has already prepared a 'reserved' DHCP port, # and we just need to adopt that; or we need to create a new # DHCP port. Try each of those in turn until we have a DHCP # port. for setup_method in (self._setup_existing_dhcp_port, self._setup_reserved_dhcp_port, self._setup_new_dhcp_port): dhcp_port = setup_method(network, device_id, dhcp_subnets) if dhcp_port: break else: raise exceptions.Conflict() # Convert subnet_id to subnet dict fixed_ips = [ dict(subnet_id=fixed_ip.subnet_id, ip_address=fixed_ip.ip_address, subnet=dhcp_subnets[fixed_ip.subnet_id]) for fixed_ip in dhcp_port.fixed_ips ] ips = [ DictModel(item) if isinstance(item, dict) else item for item in fixed_ips ] dhcp_port.fixed_ips = ips return dhcp_port
def setup_dhcp_port(self, network): """Create/update DHCP port for the host if needed and return port.""" device_id = self.get_device_id(network) subnets = {} dhcp_enabled_subnet_ids = [] for subnet in network.subnets: if subnet.enable_dhcp: dhcp_enabled_subnet_ids.append(subnet.id) subnets[subnet.id] = subnet dhcp_port = None for port in network.ports: port_device_id = getattr(port, 'device_id', None) if port_device_id == device_id: port_fixed_ips = [] ips_needs_removal = False for fixed_ip in port.fixed_ips: if fixed_ip.subnet_id in dhcp_enabled_subnet_ids: port_fixed_ips.append({ 'subnet_id': fixed_ip.subnet_id, 'ip_address': fixed_ip.ip_address }) dhcp_enabled_subnet_ids.remove(fixed_ip.subnet_id) else: ips_needs_removal = True # If there are dhcp_enabled_subnet_ids here that means that # we need to add those to the port and call update. if dhcp_enabled_subnet_ids or ips_needs_removal: port_fixed_ips.extend( [dict(subnet_id=s) for s in dhcp_enabled_subnet_ids]) dhcp_port = self.plugin.update_dhcp_port( port.id, { 'port': { 'network_id': network.id, 'fixed_ips': port_fixed_ips } }) if not dhcp_port: raise exceptions.Conflict() else: dhcp_port = port # break since we found port that matches device_id break # check for a reserved DHCP port if dhcp_port is None: LOG.debug( 'DHCP port %(device_id)s on network %(network_id)s' ' does not yet exist. Checking for a reserved port.', { 'device_id': device_id, 'network_id': network.id }) for port in network.ports: port_device_id = getattr(port, 'device_id', None) if port_device_id == constants.DEVICE_ID_RESERVED_DHCP_PORT: dhcp_port = self.plugin.update_dhcp_port( port.id, { 'port': { 'network_id': network.id, 'device_id': device_id } }) if dhcp_port: break # DHCP port has not yet been created. if dhcp_port is None: LOG.debug( 'DHCP port %(device_id)s on network %(network_id)s' ' does not yet exist.', { 'device_id': device_id, 'network_id': network.id }) port_dict = dict( name='', admin_state_up=True, device_id=device_id, network_id=network.id, tenant_id=network.tenant_id, fixed_ips=[dict(subnet_id=s) for s in dhcp_enabled_subnet_ids]) dhcp_port = self.plugin.create_dhcp_port({'port': port_dict}) if not dhcp_port: raise exceptions.Conflict() # Convert subnet_id to subnet dict fixed_ips = [ dict(subnet_id=fixed_ip.subnet_id, ip_address=fixed_ip.ip_address, subnet=subnets[fixed_ip.subnet_id]) for fixed_ip in dhcp_port.fixed_ips ] ips = [ DictModel(item) if isinstance(item, dict) else item for item in fixed_ips ] dhcp_port.fixed_ips = ips return dhcp_port
def setup_dhcp_port(self, network): """Create/update DHCP port for the host if needed and return port.""" device_id = self.get_device_id(network) subnets = {} dhcp_enabled_subnet_ids = [] for subnet in network.subnets: if subnet.enable_dhcp: dhcp_enabled_subnet_ids.append(subnet.id) subnets[subnet.id] = subnet dhcp_port = None for port in network.ports: port_device_id = getattr(port, 'device_id', None) if port_device_id == device_id: if self.driver.bridged(): port_fixed_ips = [] for fixed_ip in port.fixed_ips: port_fixed_ips.append({'subnet_id': fixed_ip.subnet_id, 'ip_address': fixed_ip.ip_address}) if fixed_ip.subnet_id in dhcp_enabled_subnet_ids: dhcp_enabled_subnet_ids.remove(fixed_ip.subnet_id) # If there are dhcp_enabled_subnet_ids here that means that # we need to add those to the port and call update. if dhcp_enabled_subnet_ids: port_fixed_ips.extend( [dict(subnet_id=s) for s in dhcp_enabled_subnet_ids]) dhcp_port = self.plugin.update_dhcp_port( port.id, {'port': {'fixed_ips': port_fixed_ips}}) if not dhcp_port: raise exceptions.Conflict() else: dhcp_port = port else: # When the DHCP port and VM TAP interfaces are not # bridged, we don't allocate a unique IP address # for the DHCP port. LOG.debug("port.fixed_ips = %s" % port.fixed_ips) dhcp_port = port # break since we found port that matches device_id break # DHCP port has not yet been created. if dhcp_port is None: LOG.debug(_('DHCP port %(device_id)s on network %(network_id)s' ' does not yet exist.'), {'device_id': device_id, 'network_id': network.id}) # When the DHCP port and VM TAP interfaces are not # bridged, we don't allocate a unique IP address for the # DHCP port. port_fixed_ips = [] if self.driver.bridged(): port_fixed_ips=[dict(subnet_id=s) for s in dhcp_enabled_subnet_ids] port_dict = dict( name='', admin_state_up=True, device_id=device_id, network_id=network.id, tenant_id=network.tenant_id, fixed_ips=port_fixed_ips) dhcp_port = self.plugin.create_dhcp_port({'port': port_dict}) if not dhcp_port: raise exceptions.Conflict() # Convert subnet_id to subnet dict fixed_ips = [dict(subnet_id=fixed_ip.subnet_id, ip_address=fixed_ip.ip_address, subnet=subnets[fixed_ip.subnet_id]) for fixed_ip in dhcp_port.fixed_ips] ips = [DictModel(item) if isinstance(item, dict) else item for item in fixed_ips] dhcp_port.fixed_ips = ips return dhcp_port