John McDowall <jmcdow...@paloaltonetworks.com> wrote on 05/10/2016 11:11:57 AM:
> From: John McDowall <jmcdow...@paloaltonetworks.com> > To: Ryan Moats/Omaha/IBM@IBMUS > Cc: "discuss@openvswitch.org" <discuss@openvswitch.org>, "OpenStack > Development Mailing List" <openstack-...@lists.openstack.org> > Date: 05/10/2016 11:12 AM > Subject: Re: [OVN] [networking-ovn] [networking-sfc] SFC and OVN > > Ryan, > > Let me do that – I assume adding them to plugin.py is the right approach. > > I have cleaned up https://github.com/doonhammer/networking-ovn and > did a merge so it should be a lot easier to see the changes. I am > going to cleanup ovs/ovn next. Once I have everything cleaned up and > make sure it is still working I will move the code over to the port- > pair/port-chain model. > > Let me know if that works for you. > > Regards > > John > > From: Ryan Moats <rmo...@us.ibm.com> > Date: Tuesday, May 10, 2016 at 7:38 AM > To: John McDowall <jmcdow...@paloaltonetworks.com> > Cc: "discuss@openvswitch.org" <discuss@openvswitch.org>, OpenStack > Development Mailing List <openstack-...@lists.openstack.org> > Subject: Re: [OVN] [networking-ovn] [networking-sfc] SFC and OVN > > John McDowall <jmcdow...@paloaltonetworks.com> wrote on 05/09/2016 > 10:46:41 AM: > > > From: John McDowall <jmcdow...@paloaltonetworks.com> > > To: Ryan Moats/Omaha/IBM@IBMUS > > Cc: "discuss@openvswitch.org" <discuss@openvswitch.org>, "OpenStack > > Development Mailing List" <openstack-...@lists.openstack.org> > > Date: 05/09/2016 10:46 AM > > Subject: Re: [OVN] [networking-ovn] [networking-sfc] SFC and OVN > > > > Ryan, > > > > Thanks – let me try and get the code cleaned up and rebased. One > > area that I could use your insight on is the interface to > > networking-ovn and how it should look. > > > > Regards > > > > John > > Looking at this, the initial code that I think should move over are > _create_ovn_vnf and _delete_ovn_vnf and maybe rename them to > create_vnf and delete_vnf. > > What I haven't figured out at this point is: > 1) Is the above enough? > 2) Do we need to refactor some of OVNPlugin's calls to provide hooks > for the SFC > driver to use for when the OVNPlugin inheritance goes away. > > Ryan I like the idea, but unfortunately, I'm still not able to apply the series cleanly to openstack:master: - the list of supported extensions has moved from plugin.py to commons/extensions.py - the patches that create extensions/__init__.py and networking_ovn/db/migration/__init__.py complain of garbage - the patch that adds Logging on fixed ips doesn't align with the new code structure for handling same - the patch that removes experimental code also has a whole lot of changes that were part of the master devstack/plugin.sh and so confuses patch. Worse, almost 90% of the changes to plugin.py fail because of the same commingling. After walking through all the patches, I'm still seeing what looks like some cruft: I'm not sure what networking_ovn/db/migration and networking_ovn/extensions are doing anymore, as they only have __init__.py files in them. Even with that, I *think* the following patch below all the changes against tip of the tree master... Ryan --- networking_ovn/common/extensions.py | 1 + networking_ovn/ovsdb/commands.py | 78 +++++++++++++++++++++++++++++++ networking_ovn/ovsdb/impl_idl_ovn.py | 18 +++++++ networking_ovn/ovsdb/ovn_api.py | 49 +++++++++++++++++++ networking_ovn/plugin.py | 71 ++++++++++++++++++++++++++++ 5 files changed, 217 insertions(+), 0 deletions(-) create mode 100644 networking_ovn/db/migration/__init__.py create mode 100644 networking_ovn/extensions/__init__.py diff --git a/networking_ovn/common/extensions.py b/networking_ovn/common/extensions.py index c171e11..55fc147 100644 --- a/networking_ovn/common/extensions.py +++ b/networking_ovn/common/extensions.py @@ -37,4 +37,5 @@ SUPPORTED_API_EXTENSIONS = [ 'subnet_allocation', 'port-security', 'allowed-address-pairs', + 'sfi', ] diff --git a/networking_ovn/db/migration/__init__.py b/networking_ovn/db/migration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/networking_ovn/extensions/__init__.py b/networking_ovn/extensions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/networking_ovn/ovsdb/commands.py b/networking_ovn/ovsdb/commands.py index 7ea7a6f..68a747f 100644 --- a/networking_ovn/ovsdb/commands.py +++ b/networking_ovn/ovsdb/commands.py @@ -164,6 +164,84 @@ class DelLogicalPortCommand(BaseCommand): setattr(lswitch, 'ports', ports) self.api._tables['Logical_Port'].rows[lport.uuid].delete() +class AddLogicalServiceCommand(BaseCommand): + def __init__(self, api, lservice, lswitch, may_exist, **columns): + super(AddLogicalServiceCommand, self).__init__(api) + self.lservice = lservice + self.lswitch = lswitch + self.may_exist = may_exist + self.columns = columns + + def run_idl(self, txn): + try: + lswitch = idlutils.row_by_value(self.api.idl, 'Logical_Switch', + 'name', self.lswitch) + services= getattr(lswitch, 'services', []) + except idlutils.RowNotFound: + msg = _("Logical Switch %s does not exist") % self.lswitch + raise RuntimeError(msg) + if self.may_exist: + service = idlutils.row_by_value(self.api.idl, + 'Logical_Service', 'name', + self.lservice, None) + if service: + return + + lswitch.verify('services') + + service = txn.insert(self.api._tables['Logical_Service']) + service.name = self.lservice + for col, val in self.columns.items(): + setattr(service, col, val) + # add the newly created service to existing lswitch + services.append(service.uuid) + setattr(lswitch, 'services', services) + +class SetLogicalServiceCommand(BaseCommand): + def __init__(self, api, lservice, if_exists, **columns): + super(SetLogicalServiceCommand, self).__init__(api) + self.lservice = lservice + self.columns = columns + self.if_exists = if_exists + + def run_idl(self, txn): + try: + service = idlutils.row_by_value(self.api.idl, 'Logical_Service', + 'name', self.lservice) + except idlutils.RowNotFound: + if self.if_exists: + return + msg = _("Logical Service %s does not exist") % self.lservice + raise RuntimeError(msg) + + for col, val in self.columns.items(): + setattr(service, col, val) + +class DelLogicalServiceCommand(BaseCommand): + def __init__(self, api, lservice, lswitch, if_exists): + super(DelLogicalServiceCommand, self).__init__(api) + self.lservice = lservice + self.lswitch = lswitch + self.if_exists = if_exists + + def run_idl(self, txn): + try: + lservice = idlutils.row_by_value(self.api.idl, 'Logical_Service', + 'name', self.lservice) + lswitch = idlutils.row_by_value(self.api.idl, 'Logical_Switch', + 'name', self.lswitch) + services = getattr(lswitch, 'services', []) + except idlutils.RowNotFound: + if self.if_exists: + return + msg = _("Service %s does not exist") % self.lservice + raise RuntimeError(msg) + + lswitch.verify('services') + + services.remove(lservice) + setattr(lswitch, 'services', services) + self.api._tables['Logical_Service'].rows[lservice.uuid].delete() class AddLRouterCommand(BaseCommand): def __init__(self, api, name, may_exist, **columns): diff --git a/networking_ovn/ovsdb/impl_idl_ovn.py b/networking_ovn/ovsdb/impl_idl_ovn.py index c3411f0..38623ac 100644 --- a/networking_ovn/ovsdb/impl_idl_ovn.py +++ b/networking_ovn/ovsdb/impl_idl_ovn.py @@ -77,6 +77,24 @@ class OvsdbOvnIdl(ovn_api.API): ext_id[0], ext_id[1], if_exists) + def create_lservice(self, lservice_name, lswitch_name, may_exist=True, + **columns): + return cmd.AddLogicalServiceCommand(self, lservice_name, lswitch_name, + may_exist, **columns) + + def set_lservice(self, lservice_name, if_exists=True, **columns): + return cmd.SetLogicalServiceCommand(self, lservice_name, + if_exists, **columns) + + def delete_lservice(self, lservice_name=None, lswitch=None, + ext_id=None, if_exists=True): + if lservice_name is not None: + return cmd.DelLogicalServiceCommand(self, lservice_name, + lswitch, if_exists) + else: + raise RuntimeError(_("Currently only supports " + "delete by lservice-name")) + def create_lport(self, lport_name, lswitch_name, may_exist=True, **columns): return cmd.AddLogicalPortCommand(self, lport_name, lswitch_name, diff --git a/networking_ovn/ovsdb/ovn_api.py b/networking_ovn/ovsdb/ovn_api.py index feca916..067488c 100644 --- a/networking_ovn/ovsdb/ovn_api.py +++ b/networking_ovn/ovsdb/ovn_api.py @@ -69,6 +69,55 @@ class API(object): :returns: :class:`Command` with no result """ + + + + @abc.abstractmethod + def create_lservice(self, name, lswitch_name, may_exist=True, **columns): + """Create a command to add an OVN lservice + + :param name: The name of the lservice + :type name: string + :param lswitch_name: The name of the lswitch the lservice is created on + :type lswitch_name: string + :param may_exist: Do not fail if lservice already exists + :type may_exist: bool + :param columns: Dictionary of service columns + Supported columns: app_port, in_port, out_port + :type columns: dictionary + :returns: :class:`Command` with no result + """ + + @abc.abstractmethod + def set_lservice(self, lservice_name, if_exists=True, **columns): + """Create a command to set OVN lservice fields + + :param lservice_name: The name of the lservice + :type lservice_name: string + :param columns: Dictionary of service columns + Supported columns: app_port, in_port, out_port + :param if_exists: Do not fail if lservice does not exist + :type if_exists: bool + :type columns: dictionary + :returns: :class:`Command` with no result + """ + + @abc.abstractmethod + def delete_lservice(self, name=None, lswitch=None, ext_id=None, + if_exists=True): + """Create a command to delete an OVN lservice + + :param name: The name of the lservice + :type name: string + :param lswitch: The name of the lswitch + :type lswitch: string + :param ext_id: The external id of the lservice + :type ext_id: pair of <ext_id_key ,ext_id_value> + :param if_exists: Do not fail if the lservice does not exists + :type if_exists: bool + :returns: :class:`Command` with no result + """ + @abc.abstractmethod def create_lport(self, name, lswitch_name, may_exist=True, **columns): """Create a command to add an OVN lport diff --git a/networking_ovn/plugin.py b/networking_ovn/plugin.py index d626b15..58dcc35 100644 --- a/networking_ovn/plugin.py +++ b/networking_ovn/plugin.py @@ -171,6 +171,10 @@ class OVNPlugin(db_base_plugin_v2.NeutronDbPluginV2, if not config.is_ovn_l3(): self.start_periodic_l3_agent_status_check() + # start periodic check task for L3 agent + if not config.is_ovn_l3(): + self.start_periodic_l3_agent_status_check() + def _setup_rpc(self): self.endpoints = [dhcp_rpc.DhcpRpcCallback(), agents_db.AgentExtRpcCallback(), @@ -649,6 +653,58 @@ class OVNPlugin(db_base_plugin_v2.NeutronDbPluginV2, if security_groups: raise psec.PortSecurityPortHasSecurityGroup() + def _portsec_ext_port_create_processing(self, context, port_data, port): + # This function is borrowed from ml2 plugin + port_security = ((port_data.get(psec.PORTSECURITY) is None) or + port_data[psec.PORTSECURITY]) + + # allowed address pair checks + if self._check_update_has_allowed_address_pairs(port): + if not port_security: + raise addr_pair.AddressPairAndPortSecurityRequired() + else: + # remove ATTR_NOT_SPECIFIED + port['port'][addr_pair.ADDRESS_PAIRS] = [] + + if port_security: + self._ensure_default_security_group_on_port(context, port) + elif self._check_update_has_security_groups(port): + raise psec.PortSecurityAndIPRequiredForSecurityGroups() + + def _portsec_ext_port_update_processing(self, updated_port, context, port): + # This function is borrowed from ml2 plugin + port_security = ((updated_port.get(psec.PORTSECURITY) is None) or + updated_port[psec.PORTSECURITY]) + + if port_security: + return + + # check the address-pairs + if self._check_update_has_allowed_address_pairs(port): + # has address pairs in request + raise addr_pair.AddressPairAndPortSecurityRequired() + elif (not self._check_update_deletes_allowed_address_pairs(port)): + # not a request for deleting the address-pairs + updated_port[addr_pair.ADDRESS_PAIRS] = ( + self.get_allowed_address_pairs(context, updated_port['id'])) + + if updated_port[addr_pair.ADDRESS_PAIRS]: + raise addr_pair.AddressPairAndPortSecurityRequired() + + # checks if security groups were updated adding/modifying + # security groups, port security is set + if self._check_update_has_security_groups(port): + raise psec.PortSecurityAndIPRequiredForSecurityGroups() + elif (not self._check_update_deletes_security_groups(port)): + # Update did not have security groups passed in. Check + # that port does not have any security groups already on it. + filters = {'port_id': [updated_port['id']]} + security_groups = self._get_port_security_group_bindings( + context, filters) + + if security_groups: + raise psec.PortSecurityPortHasSecurityGroup() + def _update_port_in_ovn(self, context, original_port, port, ovn_port_info): external_ids = { @@ -1284,6 +1340,21 @@ class OVNPlugin(db_base_plugin_v2.NeutronDbPluginV2, external_ids=external_ids )) + def create_lrouter_in_ovn(self, router): + """Create lrouter in OVN + + @param router: Router to be created in OVN + @return: Nothing + """ + + router_name = utils.ovn_name(router['id']) + external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: + router.get('name', 'no_router_name')} + with self._ovn.transaction(check_error=True) as txn: + txn.add(self._ovn.create_lrouter(router_name, + external_ids=external_ids + )) + def delete_router(self, context, router_id): router_name = utils.ovn_name(router_id) ret_val = super(OVNPlugin, self).delete_router(context, -- 1.7.1
_______________________________________________ discuss mailing list discuss@openvswitch.org http://openvswitch.org/mailman/listinfo/discuss