Datapath#ports is kept for compatibility with the previous openflow versions (< 
1.3). Datapath#ports is not updated when received EventOFPPortStatus. This 
behavior may confuse users. Wherefore, showing warning message when the user 
accesses to Datapath#ports with the currently openflow versions (>= 1.3) is 
friendly.

Signed-off-by: Satoshi Kobayashi <[email protected]>
---
 ryu/controller/controller.py                 | 22 +++++++-
 ryu/controller/ofp_handler.py                |  7 ++-
 ryu/tests/unit/controller/__init__.py        |  0
 ryu/tests/unit/controller/test_controller.py | 83 ++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 3 deletions(-)
 create mode 100644 ryu/tests/unit/controller/__init__.py
 create mode 100644 ryu/tests/unit/controller/test_controller.py

diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py
index 23418f5..225c21f 100644
--- a/ryu/controller/controller.py
+++ b/ryu/controller/controller.py
@@ -31,6 +31,7 @@ import traceback
 import random
 import ssl
 from socket import IPPROTO_TCP, TCP_NODELAY
+import warnings
 
 import ryu.base.app_manager
 
@@ -120,11 +121,30 @@ class Datapath(ofproto_protocol.ProtocolDesc):
 
         self.xid = random.randint(0, self.ofproto.MAX_XID)
         self.id = None  # datapath_id is unknown yet
-        self.ports = None
+        self._ports = None
         self.flow_format = ofproto_v1_0.NXFF_OPENFLOW10
         self.ofp_brick = ryu.base.app_manager.lookup_service_brick('ofp_event')
         self.set_state(handler.HANDSHAKE_DISPATCHER)
 
+    def _get_ports(self):
+        if (self.ofproto_parser is not None and
+                self.ofproto_parser.ofproto.OFP_VERSION >= 0x04):
+            message = (
+                'Datapath#ports is kept for compatibility with the previous '
+                'openflow versions (< 1.3). '
+                'This not be updated by EventOFPPortStatus message. '
+                'If you want to be updated, you can use '
+                '\'ryu.controller.dpset\' or \'ryu.topology.switches\'.'
+            )
+            warnings.warn(message, stacklevel=2)
+        return self._ports
+
+    def _set_ports(self, ports):
+        self._ports = ports
+
+    # To show warning when Datapath#ports is read
+    ports = property(_get_ports, _set_ports)
+
     def close(self):
         self.set_state(handler.DEAD_DISPATCHER)
 
diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py
index 95f9a12..553e9f4 100644
--- a/ryu/controller/ofp_handler.py
+++ b/ryu/controller/ofp_handler.py
@@ -20,6 +20,7 @@ Basic OpenFlow handling including negotiation.
 
 import itertools
 import logging
+import warnings
 
 import ryu.base.app_manager
 
@@ -224,8 +225,10 @@ class OFPHandler(ryu.base.app_manager.RyuApp):
     def multipart_reply_handler(self, ev):
         msg = ev.msg
         datapath = msg.datapath
-        for port in msg.body:
-            datapath.ports[port.port_no] = port
+        with warnings.catch_warnings():
+            warnings.simplefilter('ignore')
+            for port in msg.body:
+                datapath.ports[port.port_no] = port
 
         if msg.flags & datapath.ofproto.OFPMPF_REPLY_MORE:
             return
diff --git a/ryu/tests/unit/controller/__init__.py 
b/ryu/tests/unit/controller/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ryu/tests/unit/controller/test_controller.py 
b/ryu/tests/unit/controller/test_controller.py
new file mode 100644
index 0000000..ca5a64a
--- /dev/null
+++ b/ryu/tests/unit/controller/test_controller.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2015 Stratosphere Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+try:
+    import mock  # Python 2
+except ImportError:
+    from unittest import mock  # Python 3
+
+import warnings
+import unittest
+import logging
+
+import nose
+from nose.tools import assert_equal
+from nose.tools import assert_true
+
+from ryu.base import app_manager  # To suppress cyclic import
+from ryu.controller import controller
+from ryu.ofproto import ofproto_v1_3_parser
+from ryu.ofproto import ofproto_v1_2_parser
+from ryu.ofproto import ofproto_v1_0_parser
+
+
+LOG = logging.getLogger('test_controller')
+
+
+class Test_Datapath(unittest.TestCase):
+
+    """ Test case for Datapath
+    """
+
+    def _test_ports_accessibility(self, ofproto_parser, msgs_len):
+        with mock.patch('ryu.controller.controller.Datapath.set_state'):
+
+            # Ignore warnings
+            with warnings.catch_warnings(record=True) as msgs:
+                warnings.simplefilter('always')
+
+                # Test target
+                sock_mock = mock.Mock()
+                addr_mock = mock.Mock()
+                dp = controller.Datapath(sock_mock, addr_mock)
+                dp.ofproto_parser = ofproto_parser
+
+                # Create
+                dp.ports = {}
+
+                # Update
+                port_mock = mock.Mock()
+                dp.ports[0] = port_mock
+
+                # Read & Delete
+                del dp.ports[0]
+
+                assert_equal(len(msgs), msgs_len)
+                for msg in msgs:
+                    assert_true(issubclass(msg.category, UserWarning))
+
+    def test_ports_accessibility_v13(self):
+        self._test_ports_accessibility(ofproto_v1_3_parser, 2)
+
+    def test_ports_accessibility_v12(self):
+        self._test_ports_accessibility(ofproto_v1_2_parser, 0)
+
+    def test_ports_accessibility_v10(self):
+        self._test_ports_accessibility(ofproto_v1_0_parser, 0)
+
+
+if __name__ == '__main__':
+    nose.main(argv=['nosetests', '-s', '-v'], defaultTest=__file__)
-- 
1.9.5 (Apple Git-50.3)


------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to