[ovs-discuss] [OVN] [networking-ovn] [networking-sfc] SFC and OVN

John McDowall jmcdowall at paloaltonetworks.com
Wed May 11 16:30:07 UTC 2016


Ryan,

Apologies for missing the _init_.py files – removed them and remerged. When I do a compare from my repo to main I see three files changed (which I think is correct):

networking_ovn/ovsdb/commands.py
networking_ovn/ovsdb/impl_idl_ovn.py
networking_ovn/ovsdb/ovn_api.py

I could be doing something wrong as not an expert at merging repos. If I am doing something wrong let me know and I will fix it.

Regards

John

From: Ryan Moats <rmoats at us.ibm.com<mailto:rmoats at us.ibm.com>>
Date: Wednesday, May 11, 2016 at 7:12 AM
To: John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>>
Cc: "discuss at openvswitch.org<mailto:discuss at openvswitch.org>" <discuss at openvswitch.org<mailto:discuss at openvswitch.org>>, OpenStack Development Mailing List <openstack-dev at lists.openstack.org<mailto:openstack-dev at lists.openstack.org>>
Subject: Re: [OVN] [networking-ovn] [networking-sfc] SFC and OVN


John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>> wrote on 05/10/2016 11:11:57 AM:

> From: John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>>
> To: Ryan Moats/Omaha/IBM at IBMUS
> Cc: "discuss at openvswitch.org<mailto:discuss at openvswitch.org>" <discuss at openvswitch.org<mailto:discuss at openvswitch.org>>, "OpenStack
> Development Mailing List" <openstack-dev at lists.openstack.org<mailto:openstack-dev at 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<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_doonhammer_networking-2Dovn&d=CwMGaQ&c=V9IgWpI5PvzTw83UyHGVSoW3Uc1MFWe5J8PTfkrzVSo&r=vZ6VUDaavDpfOdPQrz1ED54jEjvAE36A8TVJroVlrOQ&m=OnZUOTNe2_owNOAk55Ngsx_q6nlfnk5q4cKw_8EZYUk&s=bP5OEAy91qoSaK3krK_S9J-Mh1hsS9O8drNgQeWIUQA&e=> 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 <rmoats at us.ibm.com<mailto:rmoats at us.ibm.com>>
> Date: Tuesday, May 10, 2016 at 7:38 AM
> To: John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>>
> Cc: "discuss at openvswitch.org<mailto:discuss at openvswitch.org>" <discuss at openvswitch.org<mailto:discuss at openvswitch.org>>, OpenStack
> Development Mailing List <openstack-dev at lists.openstack.org<mailto:openstack-dev at lists.openstack.org>>
> Subject: Re: [OVN] [networking-ovn] [networking-sfc] SFC and OVN
>
> John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>> wrote on 05/09/2016
> 10:46:41 AM:
>
> > From: John McDowall <jmcdowall at paloaltonetworks.com<mailto:jmcdowall at paloaltonetworks.com>>
> > To: Ryan Moats/Omaha/IBM at IBMUS
> > Cc: "discuss at openvswitch.org<mailto:discuss at openvswitch.org>" <discuss at openvswitch.org<mailto:discuss at openvswitch.org>>, "OpenStack
> > Development Mailing List" <openstack-dev at lists.openstack.org<mailto:openstack-dev at 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





-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://openvswitch.org/pipermail/ovs-discuss/attachments/20160511/46fb19a5/attachment-0002.html>


More information about the discuss mailing list