backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / integrated / test_of_config.py
1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 """
18 How to run this test
19
20 edit linc config file. LINC-Switch/rel/linc/releases/1.0/sys.config
21 You can find the sample config I used for the test below
22
23 For this following config to work, the network interface
24 linc-port and linc-port2 must be created before hand.
25 (Or edit the port name depending on your environment)
26 An easy way is to create them as follows
27 # ip link add linc-port type veth peer name linc-port-peer
28 # ip link set linc-port up
29 # ip link add linc-port2 type veth peer name linc-port-peer2
30 # ip link set linc-port2 up
31
32 Then run linc
33 # rel/linc/bin/linc console
34
35 Then run ryu
36 # PYTHONPATH=. ./bin/ryu-manager --verbose \
37         ryu/tests/integrated/test_of_config.py
38
39
40 Here is my sys.config used for this test.
41 -->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8---
42 [
43  {linc,
44   [
45    {of_config, enabled},
46
47    {logical_switches,
48     [
49      {switch, 0,
50       [
51        {backend, linc_us4},
52
53        {controllers,
54         [
55          {"Switch0-DefaultController", "localhost", 6633, tcp}
56         ]},
57
58        {ports,
59         [
60          {port, 1, [{interface, "linc-port"}]},
61          {port, 2, [{interface, "linc-port2"}]}
62         ]},
63
64        {queues_status, disabled},
65
66        {queues,
67         [
68         ]}
69       ]}
70     ]}
71   ]},
72
73  {enetconf,
74   [
75    {capabilities, [{base, {1, 1}},
76                    {startup, {1, 0}},
77                    {'writable-running', {1, 0}}]},
78    {callback_module, linc_ofconfig},
79    {sshd_ip, any},
80    {sshd_port, 1830},
81    {sshd_user_passwords,
82     [
83      {"linc", "linc"}
84     ]}
85   ]},
86
87  {lager,
88   [
89    {handlers,
90     [
91      {lager_console_backend, info},
92      {lager_file_backend,
93       [
94        {"log/error.log", error, 10485760, "$D0", 5},
95        {"log/console.log", info, 10485760, "$D0", 5}
96       ]}
97     ]}
98   ]},
99
100  {sasl,
101   [
102    {sasl_error_logger, {file, "log/sasl-error.log"}},
103    {errlog_type, error},
104    {error_logger_mf_dir, "log/sasl"},      % Log directory
105    {error_logger_mf_maxbytes, 10485760},   % 10 MB max file size
106    {error_logger_mf_maxfiles, 5}           % 5 files max
107   ]}
108 ].
109 -->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8--
110
111 """
112
113 from __future__ import print_function
114
115 import traceback
116
117 import lxml.etree
118 import ncclient
119
120 from ryu.base import app_manager
121 from ryu.lib.netconf import constants as nc_consts
122 from ryu.lib import hub
123 from ryu.lib import of_config
124 from ryu.lib.of_config import capable_switch
125 from ryu.lib.of_config import constants as ofc_consts
126
127
128 # Change those depending on switch configuration
129 HOST = '127.0.0.1'
130 PORT = 1830
131 USERNAME = 'linc'
132 PASSWORD = 'linc'
133
134 CAPABLE_SWITCH_ID = 'CapableSwitch0'
135 LOGICAL_SWITCH = 'LogicalSwitch0'
136 PORT_ID = 'LogicalSwitch0-Port2'
137 CONTROLLER_ID = 'Switch0-DefaultController'
138
139 PORT_DICT = {
140     'capable_switch': CAPABLE_SWITCH_ID,
141     'port_id': PORT_ID,
142     'logical_switch': LOGICAL_SWITCH,
143     'controller_id': CONTROLLER_ID,
144     'ip': HOST,
145 }
146
147 SWITCH_PORT_DOWN = '''
148 <nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
149   <capable-switch xmlns="urn:onf:of111:config:yang">
150     <id>%(capable_switch)s</id>
151     <resources>
152       <port>
153         <resource-id>%(port_id)s</resource-id>
154         <configuration operation="merge">
155           <admin-state>down</admin-state>
156           <no-receive>false</no-receive>
157           <no-forward>false</no-forward>
158           <no-packet-in>false</no-packet-in>
159         </configuration>
160       </port>
161     </resources>
162   </capable-switch>
163 </nc:config>
164 ''' % PORT_DICT
165
166 SWITCH_ADVERTISED = '''
167 <nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
168   <capable-switch xmlns="urn:onf:of111:config:yang">
169     <id>%(capable_switch)s</id>
170     <resources>
171       <port>
172         <resource-id>%(port_id)s</resource-id>
173         <features>
174           <advertised operation="merge">
175             <rate>10Mb-FD</rate>
176             <auto-negotiate>true</auto-negotiate>
177             <medium>copper</medium>
178             <pause>unsupported</pause>
179           </advertised>
180         </features>
181       </port>
182     </resources>
183   </capable-switch>
184 </nc:config>
185 ''' % PORT_DICT
186
187 SWITCH_CONTROLLER = '''
188 <nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
189   <capable-switch xmlns="urn:onf:of111:config:yang">
190     <id>%(capable_switch)s</id>
191     <logical-switches>
192       <switch>
193         <id>%(logical_switch)s</id>
194           <controllers>
195             <controller operation="merge">
196               <id>%(controller_id)s</id>
197               <role>master</role>
198               <ip-address>%(ip)s</ip-address>
199               <port>6633</port>
200               <protocol>tcp</protocol>
201             </controller>
202           </controllers>
203       </switch>
204     </logical-switches>
205   </capable-switch>
206 </nc:config>
207 ''' % PORT_DICT
208
209
210 def _get_schema():
211     # file_name = of_config.OF_CONFIG_1_0_XSD
212     # file_name = of_config.OF_CONFIG_1_1_XSD
213     file_name = of_config.OF_CONFIG_1_1_1_XSD
214     return lxml.etree.XMLSchema(file=file_name)
215
216
217 class OFConfigClient(app_manager.RyuApp):
218     def __init__(self, *args, **kwargs):
219         super(OFConfigClient, self).__init__(*args, **kwargs)
220         self.switch = capable_switch.OFCapableSwitch(
221             host=HOST, port=PORT, username=USERNAME, password=PASSWORD,
222             unknown_host_cb=lambda host, fingeprint: True)
223         hub.spawn(self._do_of_config)
224
225     def _validate(self, tree):
226         xmlschema = _get_schema()
227         try:
228             xmlschema.assertValid(tree)
229         except:
230             traceback.print_exc()
231
232     def _do_get(self):
233         data_xml = self.switch.raw_get()
234
235         tree = lxml.etree.fromstring(data_xml)
236         # print(lxml.etree.tostring(tree, pretty_print=True))
237         self._validate(tree)
238
239         name_spaces = set()
240         for e in tree.getiterator():
241             name_spaces.add(capable_switch.get_ns_tag(e.tag)[0])
242         print(name_spaces)
243
244         return tree
245
246     def _do_get_config(self, source):
247         print('source = %s' % source)
248         config_xml = self.switch.raw_get_config(source)
249
250         tree = lxml.etree.fromstring(config_xml)
251         # print(lxml.etree.tostring(tree, pretty_print=True))
252         self._validate(tree)
253
254     def _do_edit_config(self, config):
255         tree = lxml.etree.fromstring(config)
256         self._validate(tree)
257         self.switch.raw_edit_config(target='running', config=config)
258
259     def _print_ports(self, tree, ns):
260         for port in tree.findall('{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
261                                                     ns, ofc_consts.PORT)):
262             print(lxml.etree.tostring(port, pretty_print=True))
263
264     def _set_ports_down(self):
265         """try to set all ports down with etree operation"""
266         tree = self._do_get()
267         print(lxml.etree.tostring(tree, pretty_print=True))
268
269         qname = lxml.etree.QName(tree.tag)
270         ns = qname.namespace
271         self._print_ports(tree, ns)
272
273         switch_id = tree.find('{%s}%s' % (ns, ofc_consts.ID))
274         resources = tree.find('{%s}%s' % (ns, ofc_consts.RESOURCES))
275         configuration = tree.find(
276             '{%s}%s/{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
277                                       ns, ofc_consts.PORT,
278                                       ns, ofc_consts.CONFIGURATION))
279         admin_state = tree.find(
280             '{%s}%s/{%s}%s/{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
281                                              ns, ofc_consts.PORT,
282                                              ns, ofc_consts.CONFIGURATION,
283                                              ns, ofc_consts.ADMIN_STATE))
284
285         config_ = lxml.etree.Element(
286             '{%s}%s' % (ncclient.xml_.BASE_NS_1_0, nc_consts.CONFIG))
287         capable_switch_ = lxml.etree.SubElement(config_, tree.tag)
288         switch_id_ = lxml.etree.SubElement(capable_switch_, switch_id.tag)
289         switch_id_.text = switch_id.text
290         resources_ = lxml.etree.SubElement(capable_switch_,
291                                            resources.tag)
292         for port in tree.findall(
293                 '{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
294                                    ns, ofc_consts.PORT)):
295             resource_id = port.find('{%s}%s' % (ns, ofc_consts.RESOURCE_ID))
296
297             port_ = lxml.etree.SubElement(resources_, port.tag)
298             resource_id_ = lxml.etree.SubElement(port_, resource_id.tag)
299             resource_id_.text = resource_id.text
300             configuration_ = lxml.etree.SubElement(port_, configuration.tag)
301             configuration_.set(ofc_consts.OPERATION, nc_consts.MERGE)
302             admin_state_ = lxml.etree.SubElement(configuration_,
303                                                  admin_state.tag)
304             admin_state_.text = ofc_consts.DOWN
305         self._do_edit_config(lxml.etree.tostring(config_, pretty_print=True))
306
307         tree = self._do_get()
308         self._print_ports(tree, ns)
309
310     def _do_of_config(self):
311         self._do_get()
312         self._do_get_config('running')
313         self._do_get_config('startup')
314
315         # LINC doesn't support 'candidate' datastore
316         try:
317             self._do_get_config('candidate')
318         except ncclient.NCClientError:
319             traceback.print_exc()
320
321         # use raw XML format
322         self._do_edit_config(SWITCH_PORT_DOWN)
323         self._do_edit_config(SWITCH_ADVERTISED)
324         self._do_edit_config(SWITCH_CONTROLLER)
325
326         self._set_ports_down()
327
328         self.switch.close_session()