def create_port(self, context, port): # If PORTSECURITY is not the default value ATTR_NOT_SPECIFIED # then we pass the port to the policy engine. The reason why we don't # pass the value to the policy engine when the port is # ATTR_NOT_SPECIFIED is for the case where a port is created on a # shared network that is not owned by the tenant. port_data = port['port'] with context.session.begin(subtransactions=True): # First we allocate port in neutron database neutron_db = super(NsxDvsV2, self).create_port(context, port) port_security = self._get_network_security_binding( context, neutron_db['network_id']) port_data[psec.PORTSECURITY] = port_security self._process_port_port_security_create(context, port_data, neutron_db) # Update fields obtained from neutron db (eg: MAC address) port["port"].update(neutron_db) has_ip = self._ip_on_port(neutron_db) # security group extension checks if has_ip: self._ensure_default_security_group_on_port(context, port) elif validators.is_attr_set(port_data.get(ext_sg.SECURITYGROUPS)): raise psec.PortSecurityAndIPRequiredForSecurityGroups() port_data[ext_sg.SECURITYGROUPS] = ( self._get_security_groups_on_port(context, port)) self._process_port_create_security_group( context, port_data, port_data[ext_sg.SECURITYGROUPS]) self._process_portbindings_create_and_update( context, port['port'], port_data) # allowed address pair checks if validators.is_attr_set(port_data.get(addr_pair.ADDRESS_PAIRS)): if not port_security: raise addr_pair.AddressPairAndPortSecurityRequired() else: self._process_create_allowed_address_pairs( context, neutron_db, port_data[addr_pair.ADDRESS_PAIRS]) else: # remove ATTR_NOT_SPECIFIED port_data[addr_pair.ADDRESS_PAIRS] = [] LOG.debug( "create_port completed on NSX for tenant " "%(tenant_id)s: (%(id)s)", port_data) self._process_portbindings_create_and_update( context, port['port'], port_data) # DB Operation is complete, perform DVS operation port_data = port['port'] # this extra lookup is necessary to get the # latest db model for the extension functions port_model = self._get_port(context, port_data['id']) self._apply_dict_extend_functions('ports', port_data, port_model) self.handle_port_dhcp_access(context, port_data, action='create_port') return port_data
def update_port(self, context, id, port): delete_addr_pairs = self._check_update_deletes_allowed_address_pairs( port) has_addr_pairs = self._check_update_has_allowed_address_pairs(port) with context.session.begin(subtransactions=True): ret_port = super(NsxDvsV2, self).update_port( context, id, port) # Save current mac learning state to check whether it's # being updated or not # copy values over - except fixed_ips as # they've already been processed port['port'].pop('fixed_ips', None) ret_port.update(port['port']) # populate port_security setting if psec.PORTSECURITY not in port['port']: ret_port[psec.PORTSECURITY] = self._get_port_security_binding( context, id) # validate port security and allowed address pairs if not ret_port[psec.PORTSECURITY]: # has address pairs in request if has_addr_pairs: raise addr_pair.AddressPairAndPortSecurityRequired() elif not delete_addr_pairs: # check if address pairs are in db ret_port[addr_pair.ADDRESS_PAIRS] = ( self.get_allowed_address_pairs(context, id)) if ret_port[addr_pair.ADDRESS_PAIRS]: raise addr_pair.AddressPairAndPortSecurityRequired() if delete_addr_pairs or has_addr_pairs: # delete address pairs and read them in self._delete_allowed_address_pairs(context, id) self._process_create_allowed_address_pairs( context, ret_port, ret_port[addr_pair.ADDRESS_PAIRS]) if psec.PORTSECURITY in port['port']: self._process_port_port_security_update( context, port['port'], ret_port) LOG.debug("Updating port: %s", port) self._process_portbindings_create_and_update(context, port['port'], ret_port) return ret_port
def update_port(self, context, id, port): LOG.debug( "MidonetPluginV2.update_port called: id=%(id)s " "port=%(port)r", { 'id': id, 'port': port }) with context.session.begin(subtransactions=True): # update the port DB original_port = super(MidonetPluginV2, self).get_port(context, id) p = super(MidonetPluginV2, self).update_port(context, id, port) c_utils.check_update_port(original_port, p) self.extension_manager.process_update_port(context, port['port'], p) has_sg = self._check_update_has_security_groups(port) delete_sg = self._check_update_deletes_security_groups(port) if delete_sg or has_sg: # delete the port binding and read it with the new rules. self._delete_port_security_group_bindings(context, id) sg_ids = self._get_security_groups_on_port(context, port) self._process_port_create_security_group(context, p, sg_ids) self._update_extra_dhcp_opts_on_port(context, id, port, p) self._process_portbindings_create_and_update( context, port['port'], p) self._process_mido_portbindings_create_and_update( context, port['port'], p) self.update_address_pairs_on_port(context, id, port, original_port, p) self._process_port_port_security_update(context, port['port'], p) port_psec = p.get(psec.PORTSECURITY) if port_psec is False: if p.get(ext_sg.SECURITYGROUPS): raise psec.PortSecurityPortHasSecurityGroup() if p.get(addr_pair.ADDRESS_PAIRS): raise addr_pair.AddressPairAndPortSecurityRequired() # NOTE(yamamoto): Retrieve the db object to get the correct # revision context.session.flush() context.session.expire_all() p = self.get_port(context, id) self.client.update_port_precommit(context, id, p) # Set status along admin_state_up to update. if p['admin_state_up']: update_status = n_const.PORT_STATUS_ACTIVE else: update_status = n_const.PORT_STATUS_DOWN try: self.client.update_port_postcommit(id, p) data = {'port': {'status': update_status}} new_port = super(MidonetPluginV2, self).update_port(context, id, data) # prevent binding:profile information from lacking p['status'] = new_port['status'] if 'revision_number' in new_port: p['revision_number'] = new_port['revision_number'] except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error( _LE("Failed to update a port %(port_id)s in " "MidoNet: %(err)s"), { "port_id": id, "err": ex }) try: data = {'port': {'status': n_const.PORT_STATUS_ERROR}} super(MidonetPluginV2, self).update_port(context, id, data) except Exception: LOG.exception(_LE("Failed to update port status %s"), id) LOG.debug("MidonetPluginV2.update_port exiting: p=%r", p) return p
def create_port(self, context, port): LOG.debug("MidonetPluginV2.create_port called: port=%r", port) port_data = port['port'] # REVISIT(yamamoto): this nested transaction is a workaround # for bug #1490917. with db_api.autonested_transaction(context.session): # Set status along admin_state_up if the parameter is specified. if port['port'].get('admin_state_up') is not None: if not port['port']['admin_state_up']: port['port']['status'] = n_const.PORT_STATUS_DOWN # Create a Neutron port port_db = self.create_port_db(context, port) new_port = self._make_port_dict(port_db, process_extensions=False) self.extension_manager.process_create_port(context, port_data, new_port) # Do not create a gateway port if it has no IP address assigned as # MidoNet does not yet handle this case. if (new_port.get('device_owner') == n_const.DEVICE_OWNER_ROUTER_GW and not new_port['fixed_ips']): msg = (_("No IPs assigned to the gateway port for" " router %s") % port_data['device_id']) raise n_exc.BadRequest(resource='router', msg=msg) dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, []) # Make sure that the port created is valid if "id" not in new_port: raise n_exc.BadRequest(resource='port', msg="Invalid port created") # Update fields port_data.update(new_port) port_psec, has_ip = self._determine_port_security_and_has_ip( context, port['port']) port['port'][psec.PORTSECURITY] = port_psec self._process_port_port_security_create(context, port['port'], new_port) if port_psec is False: if self._check_update_has_security_groups(port): raise psec.PortSecurityAndIPRequiredForSecurityGroups() if self._check_update_has_allowed_address_pairs(port): raise addr_pair.AddressPairAndPortSecurityRequired() else: # Bind security groups to the port self._ensure_default_security_group_on_port(context, port) sg_ids = self._get_security_groups_on_port(context, port) self._process_port_create_security_group(context, new_port, sg_ids) # Process port bindings self._process_portbindings_create_and_update( context, port_data, new_port) self._process_mido_portbindings_create_and_update( context, port_data, new_port) self._process_port_create_extra_dhcp_opts(context, new_port, dhcp_opts) new_port[addr_pair.ADDRESS_PAIRS] = ( self._process_create_allowed_address_pairs( context, new_port, port_data.get(addr_pair.ADDRESS_PAIRS))) self.client.create_port_precommit(context, new_port) try: self.client.create_port_postcommit(new_port) except Exception as ex: with excutils.save_and_reraise_exception(): LOG.error(_LE("Failed to create a port %(new_port)s: %(err)s"), { "new_port": new_port, "err": ex }) try: self.delete_port(context, new_port['id'], l3_port_check=False) except Exception: LOG.exception(_LE("Failed to delete port %s"), new_port['id']) self._apply_dict_extend_functions('ports', new_port, port_db) LOG.debug("MidonetPluginV2.create_port exiting: port=%r", new_port) return new_port