Merge lp:~emagana/neutron/plugin-framework-nx-os into lp:~cisco-openstack/neutron/plugin-framework

Proposed by Edgar Magana
Status: Merged
Merged at revision: 42
Proposed branch: lp:~emagana/neutron/plugin-framework-nx-os
Merge into: lp:~cisco-openstack/neutron/plugin-framework
Diff against target: 479 lines (+315/-18)
5 files modified
quantum/plugins/cisco/README (+29/-7)
quantum/plugins/cisco/common/cisco_configuration.py (+10/-0)
quantum/plugins/cisco/l2network_plugin.py (+19/-3)
quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py (+236/-0)
quantum/plugins/cisco/nexus/cisco_nexus_plugin.py (+21/-8)
To merge this branch: bzr merge lp:~emagana/neutron/plugin-framework-nx-os
Reviewer Review Type Date Requested Status
Sumit Naiksatam (community) Approve
Ram Durairaj Pending
Review via email: mp+70106@code.launchpad.net

Description of the change

Nexus OS driver integration
VLAN configuration to Nexus 7K Switch

To post a comment you must log in.
Revision history for this message
Sumit Naiksatam (snaiksat) wrote :

Approving the request as per Ram's suggestion.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'quantum/plugins/cisco/README'
2--- quantum/plugins/cisco/README 2011-08-01 03:31:42 +0000
3+++ quantum/plugins/cisco/README 2011-08-02 04:45:54 +0000
4@@ -7,6 +7,7 @@
5 * UCS B200 series blades with M81KR VIC installed.
6 * UCSM 2.0 (Capitola) Build 230
7 * RHEL 6.1
8+* ncclcient v0.3.1 - Python library for NETCONF clients (http://schmizz.net/ncclient/)
9 * UCS & VIC installation (support for KVM) - please consult the accompanying installation guide available at:
10 http://wikicentral.cisco.com/display/GROUP/SAVBU+Palo+VM-FEX+for+Linux+KVM
11 * To run Quantum on RHEL, you will need to have the correct version of python-routes (version 1.12.3 or later). The RHEL 6.1 package contains an older version. Do the following and check your python-routes version:
12@@ -37,7 +38,7 @@
13 common/cisco_utils.py
14 __init__.py
15 ucs/get-vif.sh
16-* Configure the L2 Network Pllugin:
17+* Configure the L2 Network Plugin:
18 + In cisco_configuration.py,
19 - change the UCSM IP in the following statement to your UCSM IP
20 flags.DEFINE_string('ucsm_ip_address', "172.20.231.27", 'IP address of UCSM')
21@@ -57,12 +58,33 @@
22 flags.DEFINE_string('profile_name_prefix', "q-", 'Prefix of the name given to the port profile')
23 - Change the path to reflect the location of the get-vif.sh script, if you have followed the instructions in this README, this location should be the same as that of your other plugin modules
24 flags.DEFINE_string('get_next_vif', "/root/sumit/quantum/quantum/plugins/cisco/get-vif.sh", 'This is the location of the script to get the next available dynamic nic')
25- + In cisco_credentials.py,
26- - Change the following stucture to reflect the correct UCS and Nova DB details. Your UCSM_IP_ADDRESS has to match the ucsmm_ip_addresss which you provided in the cisco_configuration file earlier. Similarly, your NOVA_DATABSE_IP has to match the db_server_ip which you provided earlier. DB_USERNAME and DB_PASSWORD are those which you provided for the Nova MySQL DB when you setup OpenStack
27- _creds_dictionary = {
28- 'UCSM_IP_ADDRESS':["UCSM_USERNAME", "UCSM_PASSWORD"],
29- 'NOVA_DATABASE_IP':["DB_USERNAME", "DB_PASSWORD"]
30- }
31+
32+ + In cisco_credentials.py,
33+ - Change the following structure to reflect the correct UCS, N7K and Nova DB details. Your UCSM_IP_ADDRESS has to match the ucsmm_ip_addresss which you provided in the cisco_configuration file earlier. Similarly, your NOVA_DATABSE_IP has to match the db_server_ip which you provided earlier. DB_USERNAME and DB_PASSWORD are those which you provided for the Nova MySQL DB when you setup OpenStack
34+ N7K_IP_ADDRESS has to match with your Nexus 7k switch IP Address, N7K_USERNAME is the administrator user-name and N7K_PASSWORD is the password.
35+ _creds_dictionary = {
36+ 'UCSM_IP_ADDRESS':["UCSM_USERNAME", "UCSM_PASSWORD"],
37+ 'NOVA_DATABASE_IP':["DB_USERNAME", "DB_PASSWORD"]
38+ }
39+
40+* Configure the L2 Network Plugin with Nexus OS Driver for testing VLANs CRUD on Nexus 7k Switch. Making these changes requires one Nexus 7K Switch connected to the UCSM and the ncclient patch not just the regular library, otherwise the system will fail.
41+ + In cisco_configuration.py,
42+ - change the NEXUS 7K IP in the following statement to your N7K Switch IP
43+ flags.DEFINE_string('nexus_ip_address', "172.20.231.61", 'IP address of N7K')
44+ - change the NEXUS Interface in the following statement to the interface number in your N7K which is connected to your UCSM UpLink port
45+ flags.DEFINE_string('nexus_port', "3/23", 'Port number of the Interface connected from the Nexus 7K Switch to UCSM 6120')
46+ - change NEXUS Driver Flag to "on" in the following statement
47+ flags.DEFINE_string('nexus_driver_active', "off", 'Flag to activate Nexus OS Driver')
48+
49+ + In cisco_credentials.py,
50+ - Change the following structure to reflect the correct UCS, N7K and Nova DB details. Your UCSM_IP_ADDRESS has to match the ucsmm_ip_addresss which you provided in the cisco_configuration file earlier. Similarly, your NOVA_DATABSE_IP has to match the db_server_ip which you provided earlier. DB_USERNAME and DB_PASSWORD are those which you provided for the Nova MySQL DB when you setup OpenStack
51+ N7K_IP_ADDRESS has to match with your Nexus 7k switch IP Address, N7K_USERNAME is the administrator user-name and N7K_PASSWORD is the password.
52+ _creds_dictionary = {
53+ 'UCSM_IP_ADDRESS':["UCSM_USERNAME", "UCSM_PASSWORD"],
54+ 'N7K_IP_ADDRESS':["N7K_USERNAME", "N7K_PASSWORD"],
55+ 'NOVA_DATABASE_IP':["DB_USERNAME", "DB_PASSWORD"]
56+ }
57+
58 * Start the Quantum service
59
60 ** Additional installation required on Nova Compute:
61
62=== modified file 'quantum/plugins/cisco/common/cisco_configuration.py'
63--- quantum/plugins/cisco/common/cisco_configuration.py 2011-07-31 18:38:26 +0000
64+++ quantum/plugins/cisco/common/cisco_configuration.py 2011-08-02 04:45:54 +0000
65@@ -15,6 +15,7 @@
66 # under the License.
67 #
68 # @author: Sumit Naiksatam, Cisco Systems, Inc.
69+# @author: Edgar Magana, Cisco Systems, Inc.
70 #
71 from quantum.common import flags
72
73@@ -26,6 +27,12 @@
74 #
75 flags.DEFINE_string('ucsm_ip_address', "172.20.231.27", 'IP address of \
76 UCSM')
77+flags.DEFINE_string('nexus_ip_address', "172.20.231.61", 'IP address of \
78+ Nexus Switch')
79+flags.DEFINE_string('nexus_port', "3/23", 'Port number of the Interface \
80+ connected from the Nexus Switch to UCSM 6120')
81+flags.DEFINE_string('nexus_driver_active', "off", 'Flag to activate Nexus OS\
82+ Driver')
83 flags.DEFINE_string('db_server_ip', "127.0.0.1", 'IP address of nova DB \
84 server')
85 flags.DEFINE_string('nova_host_name', "openstack-0203", 'nova cloud \
86@@ -68,6 +75,9 @@
87
88 # Inventory items
89 UCSM_IP_ADDRESS = FLAGS.ucsm_ip_address
90+NEXUS_IP_ADDRESS = FLAGS.nexus_ip_address
91+NEXUS_DRIVER_ACTIVE = FLAGS.nexus_driver_active
92+NEXUS_PORT = FLAGS.nexus_port
93 DB_SERVER_IP = FLAGS.db_server_ip
94 NOVA_HOST_NAME = FLAGS.nova_host_name
95
96
97=== modified file 'quantum/plugins/cisco/l2network_plugin.py'
98--- quantum/plugins/cisco/l2network_plugin.py 2011-07-31 18:38:26 +0000
99+++ quantum/plugins/cisco/l2network_plugin.py 2011-08-02 04:45:54 +0000
100@@ -15,6 +15,7 @@
101 # under the License.
102 #
103 # @author: Sumit Naiksatam, Cisco Systems, Inc.
104+# @author: Edgar Magana, Cisco Systems, Inc.
105 #
106
107 import logging as LOG
108@@ -65,8 +66,13 @@
109 new_net_id = self._get_unique_net_id(tenant_id)
110 vlan_id = self._get_vlan_for_tenant(tenant_id, net_name)
111 vlan_name = self._get_vlan_name(new_net_id, str(vlan_id))
112- self._nexus_plugin.create_network(tenant_id, net_name, new_net_id,
113+ nexus_driver_flag = conf.NEXUS_DRIVER_ACTIVE
114+ if nexus_driver_flag == 'on':
115+ LOG.debug("Nexus OS Driver called\n")
116+ self._nexus_plugin.create_network(tenant_id, net_name, new_net_id,
117 vlan_name, vlan_id)
118+ else:
119+ LOG.debug("No Nexus OS Driver available\n")
120 self._ucs_plugin.create_network(tenant_id, net_name, new_net_id,
121 vlan_name, vlan_id)
122 new_net_dict = {const.NET_ID: new_net_id,
123@@ -88,12 +94,17 @@
124 """
125 LOG.debug("delete_network() called\n")
126 net = self._networks.get(net_id)
127+ nexus_driver_flag = conf.NEXUS_DRIVER_ACTIVE
128 # TODO (Sumit) : Verify that no attachments are plugged into the
129 # network
130 if net:
131 # TODO (Sumit) : Before deleting the network, make sure all the
132 # ports associated with this network are also deleted
133- self._nexus_plugin.delete_network(tenant_id, net_id)
134+ if nexus_driver_flag == 'on':
135+ LOG.debug("Nexus OS Driver called\n")
136+ self._nexus_plugin.delete_network(tenant_id, net_id)
137+ else:
138+ LOG.debug("No Nexus OS Driver available\n")
139 self._ucs_plugin.delete_network(tenant_id, net_id)
140 self._networks.pop(net_id)
141 tenant = self._get_tenant(tenant_id)
142@@ -118,7 +129,12 @@
143 Virtual Network.
144 """
145 LOG.debug("rename_network() called\n")
146- self._nexus_plugin.rename_network(tenant_id, net_id)
147+ nexus_driver_flag = conf.NEXUS_DRIVER_ACTIVE
148+ if nexus_driver_flag == 'on':
149+ LOG.debug("Nexus OS Driver called\n")
150+ self._nexus_plugin.rename_network(tenant_id, net_id)
151+ else:
152+ LOG.debug("No Nexus OS Driver available\n")
153 self._ucs_plugin.rename_network(tenant_id, net_id)
154 network = self._get_network(tenant_id, net_id)
155 network[const.NET_NAME] = new_name
156
157=== added file 'quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py'
158--- quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py 1970-01-01 00:00:00 +0000
159+++ quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py 2011-08-02 04:45:54 +0000
160@@ -0,0 +1,236 @@
161+# vim: tabstop=4 shiftwidth=4 softtabstop=4
162+#
163+# Copyright 2011 Cisco Systems, Inc. All rights reserved.
164+#
165+# Licensed under the Apache License, Version 2.0 (the "License"); you may
166+# not use this file except in compliance with the License. You may obtain
167+# a copy of the License at
168+#
169+# http://www.apache.org/licenses/LICENSE-2.0
170+#
171+# Unless required by applicable law or agreed to in writing, software
172+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
173+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
174+# License for the specific language governing permissions and limitations
175+# under the License.
176+#
177+# @author: Debojyoti Dutta, Cisco Systems, Inc.
178+# @author: Edgar Magana, Cisco Systems Inc.
179+#
180+"""
181+Implements a Nexus-OS NETCONF over SSHv2 API Client
182+"""
183+
184+import logging as LOG
185+import string
186+import subprocess
187+
188+from quantum.plugins.cisco.common import cisco_configuration as conf
189+from quantum.plugins.cisco.common import cisco_constants as const
190+from quantum.plugins.cisco.common import cisco_exceptions as cexc
191+
192+from ncclient import manager
193+
194+LOG.basicConfig(level=LOG.WARN)
195+LOG.getLogger(const.LOGGER_COMPONENT_NAME)
196+
197+
198+# The following are standard strings, messages used to communicate with Nexus,
199+#only place holder values change for each message
200+exec_conf_prefix = """
201+ <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
202+ <configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli">
203+ <__XML__MODE__exec_configure>
204+"""
205+
206+
207+exec_conf_postfix = """
208+ </__XML__MODE__exec_configure>
209+ </configure>
210+ </config>
211+"""
212+
213+
214+cmd_vlan_conf_snippet = """
215+ <vlan>
216+ <vlan-id-create-delete>
217+ <__XML__PARAM_value>%s</__XML__PARAM_value>
218+ <__XML__MODE_vlan>
219+ <name>
220+ <vlan-name>%s</vlan-name>
221+ </name>
222+ <state>
223+ <vstate>active</vstate>
224+ </state>
225+ <no>
226+ <shutdown/>
227+ </no>
228+ </__XML__MODE_vlan>
229+ </vlan-id-create-delete>
230+ </vlan>
231+"""
232+
233+cmd_no_vlan_conf_snippet = """
234+ <no>
235+ <vlan>
236+ <vlan-id-create-delete>
237+ <__XML__PARAM_value>%s</__XML__PARAM_value>
238+ </vlan-id-create-delete>
239+ </vlan>
240+ </no>
241+"""
242+
243+cmd_vlan_int_snippet = """
244+ <interface>
245+ <ethernet>
246+ <interface>%s</interface>
247+ <__XML__MODE_if-ethernet-switch>
248+ <switchport></switchport>
249+ <switchport>
250+ <trunk>
251+ <allowed>
252+ <vlan>
253+ <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans>
254+ <allow-vlans>%s</allow-vlans>
255+ </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans>
256+ </vlan>
257+ </allowed>
258+ </trunk>
259+ </switchport>
260+ </__XML__MODE_if-ethernet-switch>
261+ </ethernet>
262+ </interface>
263+"""
264+
265+cmd_port_trunk = """
266+ <interface>
267+ <ethernet>
268+ <interface>%s</interface>
269+ <__XML__MODE_if-ethernet-switch>
270+ <switchport></switchport>
271+ <switchport>
272+ <mode>
273+ <trunk>
274+ </trunk>
275+ </mode>
276+ </switchport>
277+ </__XML__MODE_if-ethernet-switch>
278+ </ethernet>
279+ </interface>
280+"""
281+
282+cmd_no_switchport = """
283+ <interface>
284+ <ethernet>
285+ <interface>%s</interface>
286+ <__XML__MODE_if-ethernet-switch>
287+ <no>
288+ <switchport>
289+ </switchport>
290+ </no>
291+ </__XML__MODE_if-ethernet-switch>
292+ </ethernet>
293+ </interface>
294+"""
295+
296+
297+cmd_no_vlan_int_snippet = """
298+ <interface>
299+ <ethernet>
300+ <interface>%s</interface>
301+ <__XML__MODE_if-ethernet-switch>
302+ <switchport></switchport>
303+ <no>
304+ <switchport>
305+ <trunk>
306+ <allowed>
307+ <vlan>
308+ <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans>
309+ <allow-vlans>%s</allow-vlans>
310+ </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans>
311+ </vlan>
312+ </allowed>
313+ </trunk>
314+ </switchport>
315+ </no>
316+ </__XML__MODE_if-ethernet-switch>
317+ </ethernet>
318+ </interface>
319+"""
320+
321+
322+filter_show_vlan_brief_snippet = """
323+ <show xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli">
324+ <vlan>
325+ <brief/>
326+ </vlan>
327+ </show> """
328+
329+
330+class CiscoNEXUSDriver():
331+
332+ def __init__(self):
333+ pass
334+
335+ def nxos_connect(self, nexus_host, port, nexus_user, nexus_password):
336+ m = manager.connect(host=nexus_host, port=22, username=nexus_user,
337+ password=nexus_password)
338+ return m
339+
340+ def enable_vlan(self, mgr, vlanid, vlanname):
341+ confstr = cmd_vlan_conf_snippet % (vlanid, vlanname)
342+ confstr = exec_conf_prefix + confstr + exec_conf_postfix
343+ mgr.edit_config(target='running', config=confstr)
344+
345+ def disable_vlan(self, mgr, vlanid):
346+ confstr = cmd_no_vlan_conf_snippet % vlanid
347+ confstr = exec_conf_prefix + confstr + exec_conf_postfix
348+ mgr.edit_config(target='running', config=confstr)
349+
350+ def enable_port_trunk(self, mgr, interface):
351+ confstr = cmd_port_trunk % (interface)
352+ confstr = exec_conf_prefix + confstr + exec_conf_postfix
353+ print confstr
354+ mgr.edit_config(target='running', config=confstr)
355+
356+ def enable_vlan_on_trunk_int(self, mgr, interface, vlanid):
357+ confstr = cmd_vlan_int_snippet % (interface, vlanid)
358+ confstr = exec_conf_prefix + confstr + exec_conf_postfix
359+ print confstr
360+ mgr.edit_config(target='running', config=confstr)
361+
362+ def disable_vlan_on_trunk_int(self, mgr, interface, vlanid):
363+ confstr = cmd_no_vlan_int_snippet % (interface, vlanid)
364+ confstr = exec_conf_prefix + confstr + exec_conf_postfix
365+ print confstr
366+ mgr.edit_config(target='running', config=confstr)
367+
368+ def test_nxos_api(self, host, user, password):
369+ with self.nxos_connect(host, port=22, user=user,
370+ password=password) as m:
371+ #enable_vlan(m, '100', 'ccn1')
372+ #enable_vlan_on_trunk_int(m, '2/1', '100')
373+ #disable_vlan_on_trunk_int(m, '2/1', '100')
374+ #disable_vlan(m, '100')
375+ result = m.get(("subtree", filter_show_vlan_brief_snippet))
376+ print result
377+
378+ def create_vlan(self, vlan_name, vlan_id, nexus_host, nexus_user,
379+ nexus_password, nexus_interface):
380+ #TODO (Edgar) Move the SSH port to the configuration file
381+ with self.nxos_connect(nexus_host, 22, nexus_user,
382+ nexus_password) as m:
383+ self.enable_vlan(m, vlan_id, vlan_name)
384+ self.enable_port_trunk(m, nexus_interface)
385+
386+ def delete_vlan(self, vlan_id, nexus_host, nexus_user, nexus_password):
387+ with self.nxos_connect(nexus_host, 22, nexus_user,
388+ nexus_password) as m:
389+ self.disable_vlan(m, vlan_id)
390+
391+
392+def main():
393+ client = CiscoNEXUSDriver()
394+
395+if __name__ == '__main__':
396+ main()
397
398=== modified file 'quantum/plugins/cisco/nexus/cisco_nexus_plugin.py'
399--- quantum/plugins/cisco/nexus/cisco_nexus_plugin.py 2011-07-31 18:38:26 +0000
400+++ quantum/plugins/cisco/nexus/cisco_nexus_plugin.py 2011-08-02 04:45:54 +0000
401@@ -15,6 +15,7 @@
402 # under the License.
403 #
404 # @author: Sumit Naiksatam, Cisco Systems, Inc.
405+# @author: Edgar Magana, Cisco Systems, Inc.
406 #
407 import logging as LOG
408
409@@ -25,6 +26,8 @@
410 from quantum.plugins.cisco.common import cisco_exceptions as cexc
411 from quantum.plugins.cisco.common import cisco_utils as cutil
412
413+from quantum.plugins.cisco.nexus import cisco_nexus_network_driver
414+
415 LOG.basicConfig(level=LOG.WARN)
416 LOG.getLogger(const.LOGGER_COMPONENT_NAME)
417
418@@ -33,10 +36,12 @@
419 _networks = {}
420
421 def __init__(self):
422- """
423- Initialize the Nexus driver here
424- """
425- pass
426+ self._client = cisco_nexus_network_driver.CiscoNEXUSDriver()
427+ #TODO (Edgar) Using just one Nexus 7K Switch and Port
428+ self._nexus_ip = conf.NEXUS_IP_ADDRESS
429+ self._nexus_username = cred.Store.getUsername(conf.NEXUS_IP_ADDRESS)
430+ self._nexus_password = cred.Store.getPassword(conf.NEXUS_IP_ADDRESS)
431+ self._nexus_port = conf.NEXUS_PORT
432
433 def get_all_networks(self, tenant_id):
434 """
435@@ -53,8 +58,9 @@
436 for this VLAN
437 """
438 LOG.debug("NexusPlugin:create_network() called\n")
439- # TODO (Sumit): Call the nexus driver here to create the VLAN, and
440- # configure the appropriate interfaces
441+ self._client.create_vlan(vlan_name, str(vlan_id), self._nexus_ip,
442+ self._nexus_username, self._nexus_password, self._nexus_port)
443+
444 new_net_dict = {const.NET_ID: net_id,
445 const.NET_NAME: net_name,
446 const.NET_PORTS: {},
447@@ -70,9 +76,10 @@
448 """
449 LOG.debug("NexusPlugin:delete_network() called\n")
450 net = self._networks.get(net_id)
451+ vlan_id = self._get_vlan_id_for_network(tenant_id, net_id)
452 if net:
453- # TODO (Sumit): Call the nexus driver here to create the VLAN,
454- # and configure the appropriate interfaces
455+ self._client.delete_vlan(str(vlan_id), self._nexus_ip,
456+ self._nexus_username, self._nexus_password)
457 self._networks.pop(net_id)
458 return net
459 # Network not found
460@@ -91,6 +98,7 @@
461 Updates the symbolic name belonging to a particular
462 Virtual Network.
463 """
464+ #TODO (Edgar) We need to add an update method in the Nexus Driver
465 LOG.debug("NexusPlugin:rename_network() called\n")
466 network = self._get_network(tenant_id, net_id)
467 network[const.NET_NAME] = new_name
468@@ -145,6 +153,11 @@
469 """
470 LOG.debug("NexusPlugin:unplug_interface() called\n")
471
472+ def _get_vlan_id_for_network(self, tenant_id, network_id):
473+ net = self._get_network(tenant_id, network_id)
474+ vlan_id = net[const.NET_VLAN_ID]
475+ return vlan_id
476+
477 def _get_network(self, tenant_id, network_id):
478 network = self._networks.get(network_id)
479 if not network:

Subscribers

People subscribed via source and target branches