Merge lp:~snaiksat/neutron/sumit-l2network-plugin-persistence into lp:~cisco-openstack/neutron/l2network-plugin-persistence
- sumit-l2network-plugin-persistence
- Merge into l2network-plugin-persistence
Proposed by
Sumit Naiksatam
Status: | Merged |
---|---|
Merged at revision: | 68 |
Proposed branch: | lp:~snaiksat/neutron/sumit-l2network-plugin-persistence |
Merge into: | lp:~cisco-openstack/neutron/l2network-plugin-persistence |
Diff against target: |
1483 lines (+313/-255) 20 files modified
quantum/plugins/cisco/README (+19/-15) quantum/plugins/cisco/__init__.py (+2/-0) quantum/plugins/cisco/common/__init__.py (+2/-0) quantum/plugins/cisco/common/cisco_configparser.py (+4/-14) quantum/plugins/cisco/common/cisco_constants.py (+2/-0) quantum/plugins/cisco/common/cisco_credentials.py (+11/-9) quantum/plugins/cisco/common/cisco_exceptions.py (+29/-5) quantum/plugins/cisco/common/cisco_nova_configuration.py (+10/-15) quantum/plugins/cisco/common/cisco_utils.py (+10/-4) quantum/plugins/cisco/l2device_plugin_base.py (+9/-1) quantum/plugins/cisco/l2network_model.py (+46/-30) quantum/plugins/cisco/l2network_model_base.py (+10/-1) quantum/plugins/cisco/l2network_plugin.py (+67/-59) quantum/plugins/cisco/l2network_plugin_configuration.py (+36/-36) quantum/plugins/cisco/nexus/cisco_nexus_configuration.py (+0/-10) quantum/plugins/cisco/ucs/__init__.py (+2/-0) quantum/plugins/cisco/ucs/cisco_getvif.py (+4/-6) quantum/plugins/cisco/ucs/cisco_ucs_configuration.py (+12/-17) quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py (+26/-32) quantum/plugins/cisco/ucs/cisco_ucs_plugin.py (+12/-1) |
To merge this branch: | bzr merge lp:~snaiksat/neutron/sumit-l2network-plugin-persistence |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Rohit Agarwalla | code walkthrough | Approve | |
Review via email: mp+71646@code.launchpad.net |
Commit message
Description of the change
Pylint fixes and other changes to incorporate review comments.
To post a comment you must log in.
Revision history for this message
Rohit Agarwalla (rohitagarwalla) wrote : | # |
review:
Approve
(code walkthrough)
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-16 07:08:38 +0000 |
3 | +++ quantum/plugins/cisco/README 2011-08-16 07:50:17 +0000 |
4 | @@ -1,6 +1,6 @@ |
5 | -============================================ |
6 | -README: Quantum L2 Network Plugin Framework |
7 | -============================================ |
8 | +========================================================================================= |
9 | +README: A Quantum Plugin Framework for Supporting L2 Networks Spannning Multiple Switches |
10 | +========================================================================================= |
11 | |
12 | :Author: Sumit Naiksatam, Ram Durairaj, Mark Voelker, Edgar Magana, Shweta Padubidri, Rohit Agarwalla, Ying Liu, Debo Dutta |
13 | :Contact: netstack@lists.launchpad.net |
14 | @@ -15,9 +15,11 @@ |
15 | This plugin implementation provides the following capabilities |
16 | to help you take your Layer 2 network for a Quantum leap: |
17 | |
18 | -* A reference implementation of plugin framework for L2 network |
19 | +* A reference implementation for a Quantum Plugin Framework |
20 | +(For details see: http://wiki.openstack.org/quantum-multi-switch-plugin) |
21 | * Supports multiple switches in the network |
22 | * Supports multiple models of switches concurrently |
23 | +* Supports use of multiple L2 technologies |
24 | * Supports Cisco UCS blade servers with M81KR Virtual Interface Cards |
25 | (aka "Palo adapters") via 802.1Qbh. |
26 | * Supports the Cisco Nexus family of switches. |
27 | @@ -32,6 +34,8 @@ |
28 | |
29 | Pre-requisites |
30 | -------------- |
31 | +(The following are necessary only when using the UCS and/or Nexus devices in your system. |
32 | +If you plan to just leverage the plugin framework, you do not need these.) |
33 | * One or more UCS B200 series blade servers with M81KR VIC (aka |
34 | Palo adapters) installed. |
35 | * UCSM 2.0 (Capitola) Build 230 or above. |
36 | @@ -108,14 +112,6 @@ |
37 | |
38 | 4b. Enter the relevant configuration in the |
39 | quantum/plugins/cisco/conf/nexus.ini file. Example: |
40 | - |
41 | -5. Plugin Persistence framework setup: |
42 | - 5a. Create quantum_l2network database in mysql with the following command - |
43 | - |
44 | -mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network" |
45 | - |
46 | - 5b. Enter the quantum_l2netowrk database configuration info in the |
47 | - quantum/plugins/cisco/conf/db_conn.ini file. |
48 | |
49 | [SWITCH] |
50 | # Change the following to reflect the IP address of the Nexus switch. |
51 | @@ -138,8 +134,16 @@ |
52 | host key changes (e.g. due to replacement of the supervisor or |
53 | clearing of the SSH config on the switch), you may need to repeat |
54 | this step and remove the old hostkey from ~/.ssh/known_hosts. |
55 | - |
56 | -5. Verify that you have the correct credentials for each IP address listed |
57 | + |
58 | +5. Plugin Persistence framework setup: |
59 | + 5a. Create quantum_l2network database in mysql with the following command - |
60 | + |
61 | +mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network" |
62 | + |
63 | + 5b. Enter the quantum_l2netowrk database configuration info in the |
64 | + quantum/plugins/cisco/conf/db_conn.ini file. |
65 | + |
66 | +6. Verify that you have the correct credentials for each IP address listed |
67 | in quantum/plugins/cisco/conf/credentials.ini. Example: |
68 | |
69 | # Provide the UCSM credentials |
70 | @@ -160,7 +164,7 @@ |
71 | username=admin |
72 | password=mySecretPasswordForNexus |
73 | |
74 | -6. Start the Quantum service. If something doesn't work, verify that |
75 | +7. Start the Quantum service. If something doesn't work, verify that |
76 | your configuration of each of the above files hasn't gone a little kaka. |
77 | Once you've put right what once went wrong, leap on. |
78 | |
79 | |
80 | === modified file 'quantum/plugins/cisco/__init__.py' |
81 | --- quantum/plugins/cisco/__init__.py 2011-07-31 19:04:01 +0000 |
82 | +++ quantum/plugins/cisco/__init__.py 2011-08-16 07:50:17 +0000 |
83 | @@ -1,3 +1,4 @@ |
84 | +""" |
85 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
86 | # |
87 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
88 | @@ -16,3 +17,4 @@ |
89 | # |
90 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
91 | # |
92 | +""" |
93 | |
94 | === modified file 'quantum/plugins/cisco/common/__init__.py' |
95 | --- quantum/plugins/cisco/common/__init__.py 2011-07-31 19:04:01 +0000 |
96 | +++ quantum/plugins/cisco/common/__init__.py 2011-08-16 07:50:17 +0000 |
97 | @@ -1,3 +1,4 @@ |
98 | +""" |
99 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
100 | # |
101 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
102 | @@ -16,3 +17,4 @@ |
103 | # |
104 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
105 | # |
106 | +""" |
107 | |
108 | === modified file 'quantum/plugins/cisco/common/cisco_configparser.py' |
109 | --- quantum/plugins/cisco/common/cisco_configparser.py 2011-08-05 09:59:54 +0000 |
110 | +++ quantum/plugins/cisco/common/cisco_configparser.py 2011-08-16 07:50:17 +0000 |
111 | @@ -1,3 +1,4 @@ |
112 | +""" |
113 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
114 | # |
115 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
116 | @@ -16,34 +17,23 @@ |
117 | # |
118 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
119 | # |
120 | +""" |
121 | |
122 | import logging as LOG |
123 | -import os |
124 | - |
125 | from configobj import ConfigObj |
126 | -from validate import Validator |
127 | - |
128 | from quantum.plugins.cisco.common import cisco_constants as const |
129 | -from quantum.plugins.cisco.common import cisco_exceptions as cexc |
130 | |
131 | LOG.basicConfig(level=LOG.WARN) |
132 | LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
133 | |
134 | |
135 | class CiscoConfigParser(ConfigObj): |
136 | + """Config Parser based on the ConfigObj module""" |
137 | |
138 | def __init__(self, filename): |
139 | super(CiscoConfigParser, self).__init__(filename, raise_errors=True, |
140 | file_error=True) |
141 | |
142 | def dummy(self, section, key): |
143 | + """Dummy function to return the same key, used in walk""" |
144 | return section[key] |
145 | - |
146 | - |
147 | -def main(): |
148 | - cp = CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
149 | - + "/" + "test.ini") |
150 | - print ("%s\n") % cp['PLUGIN']['provider'] |
151 | - |
152 | -if __name__ == '__main__': |
153 | - main() |
154 | |
155 | === modified file 'quantum/plugins/cisco/common/cisco_constants.py' |
156 | --- quantum/plugins/cisco/common/cisco_constants.py 2011-08-14 19:33:44 +0000 |
157 | +++ quantum/plugins/cisco/common/cisco_constants.py 2011-08-16 07:50:17 +0000 |
158 | @@ -1,3 +1,4 @@ |
159 | +""" |
160 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
161 | # |
162 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
163 | @@ -16,6 +17,7 @@ |
164 | # |
165 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
166 | # |
167 | +""" |
168 | |
169 | PLUGINS = 'PLUGINS' |
170 | |
171 | |
172 | === modified file 'quantum/plugins/cisco/common/cisco_credentials.py' |
173 | --- quantum/plugins/cisco/common/cisco_credentials.py 2011-08-05 09:59:54 +0000 |
174 | +++ quantum/plugins/cisco/common/cisco_credentials.py 2011-08-16 07:50:17 +0000 |
175 | @@ -1,3 +1,4 @@ |
176 | +""" |
177 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
178 | # |
179 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
180 | @@ -16,6 +17,7 @@ |
181 | # |
182 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
183 | # |
184 | +""" |
185 | |
186 | import logging as LOG |
187 | import os |
188 | @@ -34,35 +36,35 @@ |
189 | |
190 | |
191 | class Store(object): |
192 | + """Credential Store""" |
193 | + |
194 | @staticmethod |
195 | def putCredential(id, username, password): |
196 | + """Set the username and password""" |
197 | _creds_dictionary[id] = {const.USERNAME: username, |
198 | - const.PASSWORD: password} |
199 | + const.PASSWORD: password} |
200 | |
201 | @staticmethod |
202 | def getUsername(id): |
203 | + """Get the username""" |
204 | return _creds_dictionary[id][const.USERNAME] |
205 | |
206 | @staticmethod |
207 | def getPassword(id): |
208 | + """Get the password""" |
209 | return _creds_dictionary[id][const.PASSWORD] |
210 | |
211 | @staticmethod |
212 | def getCredential(id): |
213 | + """Get the username and password""" |
214 | return _creds_dictionary[id] |
215 | |
216 | @staticmethod |
217 | def getCredentials(): |
218 | + """Get all usernames and passwords""" |
219 | return _creds_dictionary |
220 | |
221 | @staticmethod |
222 | def deleteCredential(id): |
223 | + """Delete a credential""" |
224 | return _creds_dictionary.pop(id) |
225 | - |
226 | - |
227 | -def main(): |
228 | - Store.putCredential("10.10.10.10", "foo", "bar") |
229 | - print ("%s\n") % Store.getCredentials() |
230 | - |
231 | -if __name__ == '__main__': |
232 | - main() |
233 | |
234 | === modified file 'quantum/plugins/cisco/common/cisco_exceptions.py' |
235 | --- quantum/plugins/cisco/common/cisco_exceptions.py 2011-08-13 20:37:20 +0000 |
236 | +++ quantum/plugins/cisco/common/cisco_exceptions.py 2011-08-16 07:50:17 +0000 |
237 | @@ -1,3 +1,4 @@ |
238 | +""" |
239 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
240 | # |
241 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
242 | @@ -16,65 +17,88 @@ |
243 | # |
244 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
245 | # @author: Rohit Agarwalla, Cisco Systems, Inc. |
246 | - |
247 | +""" |
248 | """ |
249 | Exceptions used by the Cisco plugin |
250 | """ |
251 | - |
252 | from quantum.common import exceptions |
253 | |
254 | |
255 | class NoMoreNics(exceptions.QuantumException): |
256 | - message = _("Unable to complete operation on port %(port_id)s " \ |
257 | - "for network %(net_id)s. No more dynamic nics are available" \ |
258 | - "in the system.") |
259 | + """No more dynamic nics are available in the system""" |
260 | + message = _("Unable to complete operation. No more dynamic nics are " \ |
261 | + "available in the system.") |
262 | |
263 | |
264 | class PortProfileLimit(exceptions.QuantumException): |
265 | + """Port profile limit has been hit""" |
266 | message = _("Unable to complete operation on port %(port_id)s " \ |
267 | "for network %(net_id)s. The system has reached the maximum" \ |
268 | "limit of allowed port profiles.") |
269 | |
270 | |
271 | class UCSMPortProfileLimit(exceptions.QuantumException): |
272 | + """UCSM Port profile limit has been hit""" |
273 | message = _("Unable to complete operation on port %(port_id)s " \ |
274 | "for network %(net_id)s. The system has reached the maximum" \ |
275 | "limit of allowed UCSM port profiles.") |
276 | |
277 | |
278 | class NetworksLimit(exceptions.QuantumException): |
279 | + """Total number of network objects limit has been hit""" |
280 | message = _("Unable to create new network. Number of networks" \ |
281 | "for the system has exceeded the limit") |
282 | |
283 | |
284 | class PortProfileNotFound(exceptions.QuantumException): |
285 | + """Port profile cannot be found""" |
286 | message = _("Port profile %(portprofile_id)s could not be found " \ |
287 | "for tenant %(tenant_id)s") |
288 | |
289 | |
290 | class PortProfileInvalidDelete(exceptions.QuantumException): |
291 | + """Port profile cannot be deleted since its being used""" |
292 | message = _("Port profile %(profile_id)s could not be deleted " \ |
293 | "for tenant %(tenant_id)s since port associations exist") |
294 | |
295 | |
296 | class NetworkVlanBindingAlreadyExists(exceptions.QuantumException): |
297 | + """Binding cannot be created, since it already exists""" |
298 | message = _("NetworkVlanBinding for %(vlan_id)s and network " \ |
299 | "%(network_id)s already exists") |
300 | |
301 | |
302 | class PortProfileAlreadyExists(exceptions.QuantumException): |
303 | + """Port profile cannot be created since it already exisits""" |
304 | message = _("PortProfile %(pp_name) for %(tenant_id)s " \ |
305 | "already exists") |
306 | |
307 | |
308 | class PortProfileBindingAlreadyExists(exceptions.QuantumException): |
309 | + """Binding cannot be created, since it already exists""" |
310 | message = _("PortProfileBinding for port profile %(pp_id)s to " \ |
311 | "port %(port_id) already exists") |
312 | |
313 | |
314 | class VlanIDNotFound(exceptions.QuantumException): |
315 | + """VLAN ID cannot be found""" |
316 | message = _("Vlan ID %(vlan_id)s not found") |
317 | |
318 | |
319 | class VlanIDNotAvailable(exceptions.QuantumException): |
320 | + """VLAN ID is reserved""" |
321 | message = _("No available Vlan ID found") |
322 | + |
323 | +try: |
324 | + _("test") |
325 | +except NameError: |
326 | + |
327 | + def _(a_string): |
328 | + """ |
329 | + Default implementation of the gettext string |
330 | + translation function: no translation |
331 | + """ |
332 | + return a_string |
333 | +except TypeError: |
334 | + # during doctesting, _ might mean something else |
335 | + pass |
336 | |
337 | === modified file 'quantum/plugins/cisco/common/cisco_nova_configuration.py' |
338 | --- quantum/plugins/cisco/common/cisco_nova_configuration.py 2011-08-05 09:59:54 +0000 |
339 | +++ quantum/plugins/cisco/common/cisco_nova_configuration.py 2011-08-16 07:50:17 +0000 |
340 | @@ -1,3 +1,4 @@ |
341 | +""" |
342 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
343 | # |
344 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
345 | @@ -16,6 +17,7 @@ |
346 | # |
347 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
348 | # |
349 | +""" |
350 | |
351 | import os |
352 | |
353 | @@ -23,20 +25,13 @@ |
354 | |
355 | CONF_FILE = "../conf/nova.ini" |
356 | |
357 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
358 | +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
359 | + "/" + CONF_FILE) |
360 | |
361 | -section = cp['NOVA'] |
362 | -DB_SERVER_IP = section['db_server_ip'] |
363 | -DB_NAME = section['db_name'] |
364 | -DB_USERNAME = section['db_username'] |
365 | -DB_PASSWORD = section['db_password'] |
366 | -NOVA_HOST_NAME = section['nova_host_name'] |
367 | -NOVA_PROJ_NAME = section['nova_proj_name'] |
368 | - |
369 | - |
370 | -def main(): |
371 | - print NOVA_PROJ_NAME |
372 | - |
373 | -if __name__ == '__main__': |
374 | - main() |
375 | +SECTION = CP['NOVA'] |
376 | +DB_SERVER_IP = SECTION['db_server_ip'] |
377 | +DB_NAME = SECTION['db_name'] |
378 | +DB_USERNAME = SECTION['db_username'] |
379 | +DB_PASSWORD = SECTION['db_password'] |
380 | +NOVA_HOST_NAME = SECTION['nova_host_name'] |
381 | +NOVA_PROJ_NAME = SECTION['nova_proj_name'] |
382 | |
383 | === modified file 'quantum/plugins/cisco/common/cisco_utils.py' |
384 | --- quantum/plugins/cisco/common/cisco_utils.py 2011-08-13 06:24:26 +0000 |
385 | +++ quantum/plugins/cisco/common/cisco_utils.py 2011-08-16 07:50:17 +0000 |
386 | @@ -1,3 +1,4 @@ |
387 | +""" |
388 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
389 | # |
390 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
391 | @@ -16,16 +17,14 @@ |
392 | # |
393 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
394 | # |
395 | +""" |
396 | |
397 | import hashlib |
398 | import logging as LOG |
399 | import MySQLdb |
400 | -import sys |
401 | import traceback |
402 | |
403 | -from quantum.common import exceptions as exc |
404 | from quantum.plugins.cisco.common import cisco_constants as const |
405 | -from quantum.plugins.cisco.common import cisco_credentials as cred |
406 | from quantum.plugins.cisco.common import cisco_nova_configuration as conf |
407 | |
408 | LOG.basicConfig(level=LOG.WARN) |
409 | @@ -33,15 +32,21 @@ |
410 | |
411 | |
412 | def get16ByteUUID(uuid): |
413 | + """ |
414 | + Return a 16 byte has of the UUID, used when smaller unique |
415 | + ID is required. |
416 | + """ |
417 | return hashlib.md5(uuid).hexdigest()[:16] |
418 | |
419 | |
420 | class DBUtils(object): |
421 | + """Utilities to use connect to MySQL DB and execute queries""" |
422 | |
423 | def __init__(self): |
424 | pass |
425 | |
426 | def _get_db_connection(self): |
427 | + """Get a connection to the DB""" |
428 | db_ip = conf.DB_SERVER_IP |
429 | db_username = conf.DB_USERNAME |
430 | db_password = conf.DB_PASSWORD |
431 | @@ -50,6 +55,7 @@ |
432 | return self.db |
433 | |
434 | def execute_db_query(self, sql_query): |
435 | + """Execute a DB query""" |
436 | db = self._get_db_connection() |
437 | cursor = db.cursor() |
438 | try: |
439 | @@ -57,7 +63,7 @@ |
440 | results = cursor.fetchall() |
441 | db.commit() |
442 | LOG.debug("DB query execution succeeded: %s" % sql_query) |
443 | - db.close() |
444 | + db.close() |
445 | except: |
446 | db.rollback() |
447 | LOG.debug("DB query execution failed: %s" % sql_query) |
448 | |
449 | === modified file 'quantum/plugins/cisco/l2device_plugin_base.py' |
450 | --- quantum/plugins/cisco/l2device_plugin_base.py 2011-08-07 11:58:50 +0000 |
451 | +++ quantum/plugins/cisco/l2device_plugin_base.py 2011-08-16 07:50:17 +0000 |
452 | @@ -1,3 +1,4 @@ |
453 | +""" |
454 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
455 | # |
456 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
457 | @@ -16,12 +17,19 @@ |
458 | # |
459 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
460 | # |
461 | +""" |
462 | |
463 | import inspect |
464 | from abc import ABCMeta, abstractmethod |
465 | |
466 | |
467 | class L2DevicePluginBase(object): |
468 | + """ |
469 | + Base class for a device-specific plugin. |
470 | + An example of a device-specific plugin is a Nexus switch plugin. |
471 | + The network model relies on device-category-specific plugins to perform |
472 | + the configuration on each device. |
473 | + """ |
474 | |
475 | __metaclass__ = ABCMeta |
476 | |
477 | @@ -133,7 +141,7 @@ |
478 | marked with the abstractmethod decorator is |
479 | provided by the plugin class. |
480 | """ |
481 | - if cls is QuantumPluginBase: |
482 | + if cls is L2DevicePluginBase: |
483 | for method in cls.__abstractmethods__: |
484 | method_ok = False |
485 | for base in klass.__mro__: |
486 | |
487 | === modified file 'quantum/plugins/cisco/l2network_model.py' |
488 | --- quantum/plugins/cisco/l2network_model.py 2011-08-08 18:54:19 +0000 |
489 | +++ quantum/plugins/cisco/l2network_model.py 2011-08-16 07:50:17 +0000 |
490 | @@ -1,3 +1,4 @@ |
491 | +""" |
492 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
493 | # |
494 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
495 | @@ -16,6 +17,7 @@ |
496 | # |
497 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
498 | # |
499 | +""" |
500 | |
501 | import inspect |
502 | import logging as LOG |
503 | @@ -30,78 +32,92 @@ |
504 | |
505 | |
506 | class L2NetworkModel(L2NetworkModelBase): |
507 | + """ |
508 | + Implements the L2NetworkModelBase |
509 | + This implementation works with UCS and Nexus plugin, |
510 | + with one UCS blade, and one Nexus switch. |
511 | + """ |
512 | _plugins = {} |
513 | |
514 | def __init__(self): |
515 | - for key in conf.plugins[const.PLUGINS].keys(): |
516 | + for key in conf.PLUGINS[const.PLUGINS].keys(): |
517 | self._plugins[key] = utils.import_object( |
518 | - conf.plugins[const.PLUGINS][key]) |
519 | + conf.PLUGINS[const.PLUGINS][key]) |
520 | LOG.debug("Loaded device plugin %s\n" % \ |
521 | - conf.plugins[const.PLUGINS][key]) |
522 | + conf.PLUGINS[const.PLUGINS][key]) |
523 | |
524 | - def _funcName(self, offset=0): |
525 | + def _func_name(self, offset=0): |
526 | + """Get the name of the calling function""" |
527 | return inspect.stack()[1 + offset][3] |
528 | |
529 | - def _invokeAllDevicePlugins(self, function_name, args, kwargs): |
530 | - for pluginObjRef in self._plugins.values(): |
531 | - getattr(pluginObjRef, function_name)(*args, **kwargs) |
532 | + def _invoke_all_device_plugins(self, function_name, args, kwargs): |
533 | + """Invoke all device plugins for this model implementation""" |
534 | + for plugin_obj_ref in self._plugins.values(): |
535 | + getattr(plugin_obj_ref, function_name)(*args, **kwargs) |
536 | |
537 | - def _invokeUCSPlugin(self, function_name, args, kwargs): |
538 | + def _invoke_ucs_plugin(self, function_name, args, kwargs): |
539 | + """Invoke only the UCS plugin""" |
540 | if const.UCS_PLUGIN in self._plugins.keys(): |
541 | getattr(self._plugins[const.UCS_PLUGIN], |
542 | function_name)(*args, **kwargs) |
543 | |
544 | - def _invokeNexusPlugin(self, function_name, args, kwargs): |
545 | + def _invoke_nexus_plugin(self, function_name, args, kwargs): |
546 | + """Invoke only the Nexus plugin""" |
547 | if const.NEXUS_PLUGIN in self._plugins.keys(): |
548 | getattr(self._plugins[const.NEXUS_PLUGIN], |
549 | function_name)(*args, **kwargs) |
550 | |
551 | def get_all_networks(self, args): |
552 | + """Not implemented for this model""" |
553 | pass |
554 | |
555 | def create_network(self, args): |
556 | - deviceParams = {const.DEVICE_IP: ""} |
557 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
558 | + """Support for the Quantum core API call""" |
559 | + device_params = {const.DEVICE_IP: ""} |
560 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
561 | |
562 | def delete_network(self, args): |
563 | - deviceParams = {const.DEVICE_IP: ""} |
564 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
565 | + """Support for the Quantum core API call""" |
566 | + device_params = {const.DEVICE_IP: ""} |
567 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
568 | |
569 | def get_network_details(self, args): |
570 | + """Not implemented for this model""" |
571 | pass |
572 | |
573 | def rename_network(self, args): |
574 | - deviceParams = {const.DEVICE_IP: ""} |
575 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
576 | + """Support for the Quantum core API call""" |
577 | + device_params = {const.DEVICE_IP: ""} |
578 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
579 | |
580 | def get_all_ports(self, args): |
581 | + """Not implemented for this model""" |
582 | pass |
583 | |
584 | def create_port(self, args): |
585 | - deviceParams = {const.DEVICE_IP: ""} |
586 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
587 | + """Support for the Quantum core API call""" |
588 | + device_params = {const.DEVICE_IP: ""} |
589 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
590 | |
591 | def delete_port(self, args): |
592 | - deviceParams = {const.DEVICE_IP: ""} |
593 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
594 | + """Support for the Quantum core API call""" |
595 | + device_params = {const.DEVICE_IP: ""} |
596 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
597 | |
598 | def update_port(self, args): |
599 | + """Not implemented for this model""" |
600 | pass |
601 | |
602 | def get_port_details(self, args): |
603 | + """Not implemented for this model""" |
604 | pass |
605 | |
606 | def plug_interface(self, args): |
607 | - deviceParams = {const.DEVICE_IP: ""} |
608 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
609 | + """Support for the Quantum core API call""" |
610 | + device_params = {const.DEVICE_IP: ""} |
611 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
612 | |
613 | def unplug_interface(self, args): |
614 | - deviceParams = {const.DEVICE_IP: ""} |
615 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
616 | - |
617 | - |
618 | -def main(): |
619 | - client = L2NetworkModel() |
620 | - |
621 | -if __name__ == '__main__': |
622 | - main() |
623 | + """Support for the Quantum core API call""" |
624 | + device_params = {const.DEVICE_IP: ""} |
625 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
626 | |
627 | === modified file 'quantum/plugins/cisco/l2network_model_base.py' |
628 | --- quantum/plugins/cisco/l2network_model_base.py 2011-08-07 11:58:50 +0000 |
629 | +++ quantum/plugins/cisco/l2network_model_base.py 2011-08-16 07:50:17 +0000 |
630 | @@ -1,3 +1,4 @@ |
631 | +""" |
632 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
633 | # |
634 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
635 | @@ -16,12 +17,20 @@ |
636 | # |
637 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
638 | # |
639 | +""" |
640 | |
641 | import inspect |
642 | from abc import ABCMeta, abstractmethod |
643 | |
644 | |
645 | class L2NetworkModelBase(object): |
646 | + """ |
647 | + Base class for L2 Network Model |
648 | + It relies on a pluggable network configuration module to gather |
649 | + knowledge of the system, but knows which device-specific plugins |
650 | + to invoke for a corresponding core API call, and what parameters to pass |
651 | + to that plugin. |
652 | + """ |
653 | |
654 | __metaclass__ = ABCMeta |
655 | |
656 | @@ -131,7 +140,7 @@ |
657 | marked with the abstractmethod decorator is |
658 | provided by the plugin class. |
659 | """ |
660 | - if cls is QuantumPluginBase: |
661 | + if cls is L2NetworkModelBase: |
662 | for method in cls.__abstractmethods__: |
663 | method_ok = False |
664 | for base in klass.__mro__: |
665 | |
666 | === modified file 'quantum/plugins/cisco/l2network_plugin.py' |
667 | --- quantum/plugins/cisco/l2network_plugin.py 2011-08-14 19:33:44 +0000 |
668 | +++ quantum/plugins/cisco/l2network_plugin.py 2011-08-16 07:50:17 +0000 |
669 | @@ -1,3 +1,4 @@ |
670 | +""" |
671 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
672 | # |
673 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
674 | @@ -16,6 +17,7 @@ |
675 | # |
676 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
677 | # |
678 | +""" |
679 | |
680 | import inspect |
681 | import logging as LOG |
682 | @@ -34,6 +36,7 @@ |
683 | |
684 | |
685 | class L2Network(QuantumPluginBase): |
686 | + """ L2 Network Framework Plugin """ |
687 | |
688 | def __init__(self): |
689 | self._vlan_counter = int(conf.VLAN_START) - 1 |
690 | @@ -52,7 +55,7 @@ |
691 | the specified tenant. |
692 | """ |
693 | LOG.debug("get_all_networks() called\n") |
694 | - self._invokeDevicePlugins(self._funcName(), [tenant_id]) |
695 | + self._invoke_device_plugins(self._func_name(), [tenant_id]) |
696 | networks_list = db.network_list(tenant_id) |
697 | new_networks_list = [] |
698 | for network in networks_list: |
699 | @@ -73,7 +76,7 @@ |
700 | new_net_id = new_network[const.UUID] |
701 | vlan_id = self._get_vlan_for_tenant(tenant_id, net_name) |
702 | vlan_name = self._get_vlan_name(new_net_id, str(vlan_id)) |
703 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_name, |
704 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_name, |
705 | new_net_id, vlan_name, |
706 | vlan_id]) |
707 | cdb.add_vlan_binding(vlan_id, vlan_name, new_net_id) |
708 | @@ -98,7 +101,7 @@ |
709 | for port in ports_on_net: |
710 | self.delete_port(tenant_id, net_id, port[const.PORTID]) |
711 | |
712 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
713 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
714 | net_dict = self._make_net_dict(net[const.UUID], |
715 | net[const.NETWORKNAME], |
716 | []) |
717 | @@ -114,7 +117,7 @@ |
718 | Gets the details of a particular network |
719 | """ |
720 | LOG.debug("get_network_details() called\n") |
721 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
722 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
723 | network = db.network_get(net_id) |
724 | ports_list = network[const.NETWORKPORTS] |
725 | ports_on_net = [] |
726 | @@ -137,7 +140,7 @@ |
727 | Virtual Network. |
728 | """ |
729 | LOG.debug("rename_network() called\n") |
730 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
731 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
732 | new_name]) |
733 | network = db.network_rename(tenant_id, net_id, new_name) |
734 | net_dict = self._make_net_dict(network[const.UUID], |
735 | @@ -151,7 +154,7 @@ |
736 | specified Virtual Network. |
737 | """ |
738 | LOG.debug("get_all_ports() called\n") |
739 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
740 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
741 | network = db.network_get(net_id) |
742 | ports_list = network[const.NETWORKPORTS] |
743 | ports_on_net = [] |
744 | @@ -171,7 +174,7 @@ |
745 | LOG.debug("create_port() called\n") |
746 | port = db.port_create(net_id, port_state) |
747 | unique_port_id_string = port[const.UUID] |
748 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
749 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
750 | port_state, |
751 | unique_port_id_string]) |
752 | new_port_dict = self._make_port_dict(port[const.UUID], |
753 | @@ -188,7 +191,7 @@ |
754 | then the port can be deleted. |
755 | """ |
756 | LOG.debug("delete_port() called\n") |
757 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
758 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
759 | port_id]) |
760 | db.port_destroy(net_id, port_id) |
761 | new_port_dict = self._make_port_dict(port_id, None, None, None) |
762 | @@ -199,7 +202,7 @@ |
763 | Updates the state of a port on the specified Virtual Network. |
764 | """ |
765 | LOG.debug("update_port() called\n") |
766 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
767 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
768 | port_id, port_state]) |
769 | self._validate_port_state(port_state) |
770 | db.port_set_state(net_id, port_id, port_state) |
771 | @@ -213,7 +216,7 @@ |
772 | that is attached to this particular port. |
773 | """ |
774 | LOG.debug("get_port_details() called\n") |
775 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
776 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
777 | port_id]) |
778 | port = db.port_get(net_id, port_id) |
779 | new_port_dict = self._make_port_dict(port[const.UUID], |
780 | @@ -229,7 +232,7 @@ |
781 | specified Virtual Network. |
782 | """ |
783 | LOG.debug("plug_interface() called\n") |
784 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
785 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
786 | port_id, |
787 | remote_interface_id]) |
788 | db.port_set_attachment(net_id, port_id, remote_interface_id) |
789 | @@ -240,7 +243,7 @@ |
790 | specified Virtual Network. |
791 | """ |
792 | LOG.debug("unplug_interface() called\n") |
793 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
794 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
795 | port_id]) |
796 | db.port_unset_attachment(net_id, port_id) |
797 | |
798 | @@ -248,40 +251,42 @@ |
799 | Extension API implementation |
800 | """ |
801 | def get_all_portprofiles(self, tenant_id): |
802 | - #return self._portprofiles.values() |
803 | + """Get all port profiles""" |
804 | pplist = cdb.get_all_portprofiles() |
805 | new_pplist = [] |
806 | - for pp in pplist: |
807 | + for portprofile in pplist: |
808 | new_pp = self._make_portprofile_dict(tenant_id, |
809 | - pp[const.UUID], |
810 | - pp[const.PPNAME], |
811 | - pp[const.PPQOS]) |
812 | + portprofile[const.UUID], |
813 | + portprofile[const.PPNAME], |
814 | + portprofile[const.PPQOS]) |
815 | new_pplist.append(new_pp) |
816 | |
817 | return new_pplist |
818 | |
819 | def get_portprofile_details(self, tenant_id, profile_id): |
820 | - #return self._get_portprofile(tenant_id, profile_id) |
821 | - pp = cdb.get_portprofile(tenant_id, profile_id) |
822 | + """Get port profile details""" |
823 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
824 | new_pp = self._make_portprofile_dict(tenant_id, |
825 | - pp[const.UUID], |
826 | - pp[const.PPNAME], |
827 | - pp[const.PPQOS]) |
828 | + portprofile[const.UUID], |
829 | + portprofile[const.PPNAME], |
830 | + portprofile[const.PPQOS]) |
831 | return new_pp |
832 | |
833 | def create_portprofile(self, tenant_id, profile_name, qos): |
834 | - pp = cdb.add_portprofile(tenant_id, profile_name, |
835 | + """Create port profile""" |
836 | + portprofile = cdb.add_portprofile(tenant_id, profile_name, |
837 | const.NO_VLAN_ID, qos) |
838 | new_pp = self._make_portprofile_dict(tenant_id, |
839 | - pp[const.UUID], |
840 | - pp[const.PPNAME], |
841 | - pp[const.PPQOS]) |
842 | + portprofile[const.UUID], |
843 | + portprofile[const.PPNAME], |
844 | + portprofile[const.PPQOS]) |
845 | return new_pp |
846 | |
847 | def delete_portprofile(self, tenant_id, profile_id): |
848 | + """Delete portprofile""" |
849 | try: |
850 | - pp = cdb.get_portprofile(tenant_id, profile_id) |
851 | - except Exception, e: |
852 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
853 | + except Exception, exc: |
854 | raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
855 | portprofile_id=profile_id) |
856 | |
857 | @@ -293,23 +298,25 @@ |
858 | cdb.remove_portprofile(tenant_id, profile_id) |
859 | |
860 | def rename_portprofile(self, tenant_id, profile_id, new_name): |
861 | + """Rename port profile""" |
862 | try: |
863 | - pp = cdb.get_portprofile(tenant_id, profile_id) |
864 | - except Exception, e: |
865 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
866 | + except Exception, exc: |
867 | raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
868 | portprofile_id=profile_id) |
869 | - pp = cdb.update_portprofile(tenant_id, profile_id, new_name) |
870 | + portprofile = cdb.update_portprofile(tenant_id, profile_id, new_name) |
871 | new_pp = self._make_portprofile_dict(tenant_id, |
872 | - pp[const.UUID], |
873 | - pp[const.PPNAME], |
874 | - pp[const.PPQOS]) |
875 | + portprofile[const.UUID], |
876 | + portprofile[const.PPNAME], |
877 | + portprofile[const.PPQOS]) |
878 | return new_pp |
879 | |
880 | def associate_portprofile(self, tenant_id, net_id, |
881 | port_id, portprofile_id): |
882 | + """Associate port profile""" |
883 | try: |
884 | - pp = cdb.get_portprofile(tenant_id, portprofile_id) |
885 | - except Exception, e: |
886 | + portprofile = cdb.get_portprofile(tenant_id, portprofile_id) |
887 | + except Exception, exc: |
888 | raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
889 | portprofile_id=portprofile_id) |
890 | |
891 | @@ -317,35 +324,40 @@ |
892 | |
893 | def disassociate_portprofile(self, tenant_id, net_id, |
894 | port_id, portprofile_id): |
895 | + """Disassociate port profile""" |
896 | try: |
897 | - pp = cdb.get_portprofile(tenant_id, portprofile_id) |
898 | - except Exception, e: |
899 | + portprofile = cdb.get_portprofile(tenant_id, portprofile_id) |
900 | + except Exception, exc: |
901 | raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
902 | portprofile_id=portprofile_id) |
903 | |
904 | cdb.remove_pp_binding(tenant_id, port_id, portprofile_id) |
905 | |
906 | - def create_defaultPProfile(self, tenant_id, network_id, profile_name, |
907 | - qos): |
908 | - pp = cdb.add_portprofile(tenant_id, profile_name, |
909 | + def create_default_port_profile(self, tenant_id, network_id, profile_name, |
910 | + qos): |
911 | + "Create default port profile""" |
912 | + portprofile = cdb.add_portprofile(tenant_id, profile_name, |
913 | const.NO_VLAN_ID, qos) |
914 | new_pp = self._make_portprofile_dict(tenant_id, |
915 | - pp[const.UUID], |
916 | - pp[const.PPNAME], |
917 | - pp[const.PPQOS]) |
918 | - cdb.add_pp_binding(tenant_id, port_id, portprofile_id, True) |
919 | + portprofile[const.UUID], |
920 | + portprofile[const.PPNAME], |
921 | + portprofile[const.PPQOS]) |
922 | + # TODO (Sumit): Need to check the following |
923 | + port_id = None |
924 | + cdb.add_pp_binding(tenant_id, port_id, portprofile[const.UUID], True) |
925 | return new_pp |
926 | |
927 | """ |
928 | Private functions |
929 | """ |
930 | - def _invokeDevicePlugins(self, function_name, args): |
931 | + def _invoke_device_plugins(self, function_name, args): |
932 | """ |
933 | All device-specific calls are delegate to the model |
934 | """ |
935 | getattr(self._model, function_name)(args) |
936 | |
937 | def _get_vlan_for_tenant(self, tenant_id, net_name): |
938 | + """Get vlan ID""" |
939 | # TODO (Sumit): |
940 | # The VLAN ID for a tenant might need to be obtained from |
941 | # somewhere (from Donabe/Melange?) |
942 | @@ -355,27 +367,33 @@ |
943 | return cdb.reserve_vlanid() |
944 | |
945 | def _release_vlan_for_tenant(self, tenant_id, net_id): |
946 | + """Relase VLAN""" |
947 | vlan_binding = cdb.get_vlan_binding(net_id) |
948 | return cdb.release_vlanid(vlan_binding[const.VLANID]) |
949 | |
950 | def _get_vlan_name(self, net_id, vlan): |
951 | + """Getting the vlan name from the tenant and vlan""" |
952 | vlan_name = conf.VLAN_NAME_PREFIX + vlan |
953 | return vlan_name |
954 | |
955 | def _validate_port_state(self, port_state): |
956 | + """Checking the port state""" |
957 | if port_state.upper() not in (const.PORT_UP, const.PORT_DOWN): |
958 | raise exc.StateInvalid(port_state=port_state) |
959 | return True |
960 | |
961 | - def _funcName(self, offset=0): |
962 | + def _func_name(self, offset=0): |
963 | + """Getting the name of the calling funciton""" |
964 | return inspect.stack()[1 + offset][3] |
965 | |
966 | def _make_net_dict(self, net_id, net_name, ports): |
967 | + """Helper funciton""" |
968 | res = {const.NET_ID: net_id, const.NET_NAME: net_name} |
969 | res[const.NET_PORTS] = ports |
970 | return res |
971 | |
972 | def _make_port_dict(self, port_id, port_state, net_id, attachment): |
973 | + """Helper funciton""" |
974 | res = {const.PORT_ID: port_id, const.PORT_STATE: port_state} |
975 | res[const.NET_ID] = net_id |
976 | res[const.ATTACHMENT] = attachment |
977 | @@ -383,6 +401,7 @@ |
978 | |
979 | def _make_portprofile_dict(self, tenant_id, profile_id, profile_name, |
980 | qos): |
981 | + """Helper funciton""" |
982 | profile_associations = self._make_portprofile_assc_list(tenant_id, |
983 | profile_id) |
984 | res = {const.PROFILE_ID: str(profile_id), |
985 | @@ -393,21 +412,10 @@ |
986 | return res |
987 | |
988 | def _make_portprofile_assc_list(self, tenant_id, profile_id): |
989 | + """Helper function to create port profile association list""" |
990 | plist = cdb.get_pp_binding(tenant_id, profile_id) |
991 | assc_list = [] |
992 | for port in plist: |
993 | assc_list.append(port[const.PORTID]) |
994 | |
995 | return assc_list |
996 | - |
997 | - |
998 | -def main(): |
999 | - client = L2Network() |
1000 | - """ |
1001 | - client.create_portprofile("12345", "tpp1", "2") |
1002 | - client.create_portprofile("12345", "tpp2", "3") |
1003 | - print ("%s\n") % client.get_all_portprofiles("12345") |
1004 | - """ |
1005 | - |
1006 | -if __name__ == '__main__': |
1007 | - main() |
1008 | |
1009 | === modified file 'quantum/plugins/cisco/l2network_plugin_configuration.py' |
1010 | --- quantum/plugins/cisco/l2network_plugin_configuration.py 2011-08-13 20:37:20 +0000 |
1011 | +++ quantum/plugins/cisco/l2network_plugin_configuration.py 2011-08-16 07:50:17 +0000 |
1012 | @@ -1,3 +1,4 @@ |
1013 | +""" |
1014 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1015 | # |
1016 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1017 | @@ -16,6 +17,7 @@ |
1018 | # |
1019 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1020 | # @author: Rohit Agarwalla, Cisco Systems, Inc. |
1021 | +""" |
1022 | |
1023 | import os |
1024 | |
1025 | @@ -23,45 +25,43 @@ |
1026 | |
1027 | CONF_FILE = "conf/l2network_plugin.ini" |
1028 | |
1029 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
1030 | - + "/" + CONF_FILE) |
1031 | - |
1032 | -section = cp['VLANS'] |
1033 | -VLAN_NAME_PREFIX = section['vlan_name_prefix'] |
1034 | -VLAN_START = section['vlan_start'] |
1035 | -VLAN_END = section['vlan_end'] |
1036 | - |
1037 | -section = cp['PORTS'] |
1038 | -MAX_PORTS = section['max_ports'] |
1039 | - |
1040 | -section = cp['PORTPROFILES'] |
1041 | -MAX_PORT_PROFILES = section['max_port_profiles'] |
1042 | - |
1043 | -section = cp['NETWORKS'] |
1044 | -MAX_NETWORKS = section['max_networks'] |
1045 | - |
1046 | -section = cp['MODEL'] |
1047 | -MODEL_CLASS = section['model_class'] |
1048 | +CONF_PARSER_OBJ = confp.\ |
1049 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
1050 | +"/" + CONF_FILE) |
1051 | + |
1052 | +SECTION_CONF = CONF_PARSER_OBJ['VLANS'] |
1053 | +VLAN_NAME_PREFIX = SECTION_CONF['vlan_name_prefix'] |
1054 | +VLAN_START = SECTION_CONF['vlan_start'] |
1055 | +VLAN_END = SECTION_CONF['vlan_end'] |
1056 | + |
1057 | +SECTION_CONF = CONF_PARSER_OBJ['PORTS'] |
1058 | +MAX_PORTS = SECTION_CONF['max_ports'] |
1059 | + |
1060 | +SECTION_CONF = CONF_PARSER_OBJ['PORTPROFILES'] |
1061 | +MAX_PORT_PROFILES = SECTION_CONF['max_port_profiles'] |
1062 | + |
1063 | +SECTION_CONF = CONF_PARSER_OBJ['NETWORKS'] |
1064 | +MAX_NETWORKS = SECTION_CONF['max_networks'] |
1065 | + |
1066 | +SECTION_CONF = CONF_PARSER_OBJ['MODEL'] |
1067 | +MODEL_CLASS = SECTION_CONF['model_class'] |
1068 | |
1069 | CONF_FILE = "conf/plugins.ini" |
1070 | |
1071 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
1072 | - + "/" + CONF_FILE) |
1073 | -plugins = cp.walk(cp.dummy) |
1074 | +CONF_PARSER_OBJ = confp.\ |
1075 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
1076 | +"/" + CONF_FILE) |
1077 | + |
1078 | +PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy) |
1079 | |
1080 | CONF_FILE = "conf/db_conn.ini" |
1081 | |
1082 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
1083 | - + "/" + CONF_FILE) |
1084 | - |
1085 | -section = cp['DATABASE'] |
1086 | -DB_NAME = section['name'] |
1087 | -DB_USER = section['user'] |
1088 | -DB_PASS = section['pass'] |
1089 | -DB_HOST = section['host'] |
1090 | - |
1091 | -def main(): |
1092 | - print plugins['PLUGINS'] |
1093 | - |
1094 | -if __name__ == '__main__': |
1095 | - main() |
1096 | +CONF_PARSER_OBJ = confp.\ |
1097 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
1098 | +"/" + CONF_FILE) |
1099 | + |
1100 | +SECTION_CONF = CONF_PARSER_OBJ['DATABASE'] |
1101 | +DB_NAME = SECTION_CONF['name'] |
1102 | +DB_USER = SECTION_CONF['user'] |
1103 | +DB_PASS = SECTION_CONF['pass'] |
1104 | +DB_HOST = SECTION_CONF['host'] |
1105 | |
1106 | === modified file 'quantum/plugins/cisco/nexus/cisco_nexus_configuration.py' |
1107 | --- quantum/plugins/cisco/nexus/cisco_nexus_configuration.py 2011-08-16 00:17:20 +0000 |
1108 | +++ quantum/plugins/cisco/nexus/cisco_nexus_configuration.py 2011-08-16 07:50:17 +0000 |
1109 | @@ -38,13 +38,3 @@ |
1110 | |
1111 | SECTION = CP['DRIVER'] |
1112 | NEXUS_DRIVER = SECTION['name'] |
1113 | - |
1114 | - |
1115 | -def main(): |
1116 | - """ |
1117 | - Indicates the value of the Nexus Port |
1118 | - """ |
1119 | - print NEXUS_PORT |
1120 | - |
1121 | -if __name__ == '__main__': |
1122 | - main() |
1123 | |
1124 | === modified file 'quantum/plugins/cisco/ucs/__init__.py' |
1125 | --- quantum/plugins/cisco/ucs/__init__.py 2011-07-31 19:04:01 +0000 |
1126 | +++ quantum/plugins/cisco/ucs/__init__.py 2011-08-16 07:50:17 +0000 |
1127 | @@ -1,3 +1,4 @@ |
1128 | +""" |
1129 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1130 | # |
1131 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1132 | @@ -16,3 +17,4 @@ |
1133 | # |
1134 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1135 | # |
1136 | +""" |
1137 | |
1138 | === modified file 'quantum/plugins/cisco/ucs/cisco_getvif.py' |
1139 | --- quantum/plugins/cisco/ucs/cisco_getvif.py 2011-08-05 09:59:54 +0000 |
1140 | +++ quantum/plugins/cisco/ucs/cisco_getvif.py 2011-08-16 07:50:17 +0000 |
1141 | @@ -1,3 +1,4 @@ |
1142 | +""" |
1143 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1144 | # |
1145 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1146 | @@ -16,11 +17,13 @@ |
1147 | # |
1148 | # @author: Rohit Agarwalla, Cisco Systems Inc. |
1149 | # |
1150 | -import sys |
1151 | +""" |
1152 | + |
1153 | import subprocess |
1154 | |
1155 | |
1156 | def get_next_dynic(argv=[]): |
1157 | + """Get the next available dynamic nic on this host""" |
1158 | cmd = ["ifconfig", "-a"] |
1159 | f_cmd_output = subprocess.Popen(cmd, stdout=subprocess.PIPE).\ |
1160 | communicate()[0] |
1161 | @@ -49,8 +52,3 @@ |
1162 | if not used: |
1163 | break |
1164 | return eth |
1165 | - |
1166 | -if __name__ == '__main__': |
1167 | - #nic = get_next_dynic(sys.argv) |
1168 | - nic = get_next_dynic() |
1169 | - print nic |
1170 | |
1171 | === modified file 'quantum/plugins/cisco/ucs/cisco_ucs_configuration.py' |
1172 | --- quantum/plugins/cisco/ucs/cisco_ucs_configuration.py 2011-08-05 09:59:54 +0000 |
1173 | +++ quantum/plugins/cisco/ucs/cisco_ucs_configuration.py 2011-08-16 07:50:17 +0000 |
1174 | @@ -1,3 +1,4 @@ |
1175 | +""" |
1176 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1177 | # |
1178 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1179 | @@ -16,6 +17,7 @@ |
1180 | # |
1181 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1182 | # |
1183 | +""" |
1184 | |
1185 | import os |
1186 | |
1187 | @@ -23,22 +25,15 @@ |
1188 | |
1189 | CONF_FILE = "../conf/ucs.ini" |
1190 | |
1191 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
1192 | +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
1193 | + "/" + CONF_FILE) |
1194 | |
1195 | -section = cp['UCSM'] |
1196 | -UCSM_IP_ADDRESS = section['ip_address'] |
1197 | -DEFAULT_VLAN_NAME = section['default_vlan_name'] |
1198 | -DEFAULT_VLAN_ID = section['default_vlan_id'] |
1199 | -MAX_UCSM_PORT_PROFILES = section['max_ucsm_port_profiles'] |
1200 | -PROFILE_NAME_PREFIX = section['profile_name_prefix'] |
1201 | - |
1202 | -section = cp['DRIVER'] |
1203 | -UCSM_DRIVER = section['name'] |
1204 | - |
1205 | - |
1206 | -def main(): |
1207 | - print MAX_UCSM_PORT_PROFILES |
1208 | - |
1209 | -if __name__ == '__main__': |
1210 | - main() |
1211 | +SECTION = CP['UCSM'] |
1212 | +UCSM_IP_ADDRESS = SECTION['ip_address'] |
1213 | +DEFAULT_VLAN_NAME = SECTION['default_vlan_name'] |
1214 | +DEFAULT_VLAN_ID = SECTION['default_vlan_id'] |
1215 | +MAX_UCSM_PORT_PROFILES = SECTION['max_ucsm_port_profiles'] |
1216 | +PROFILE_NAME_PREFIX = SECTION['profile_name_prefix'] |
1217 | + |
1218 | +SECTION = CP['DRIVER'] |
1219 | +UCSM_DRIVER = SECTION['name'] |
1220 | |
1221 | === modified file 'quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py' |
1222 | --- quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py 2011-08-05 09:59:54 +0000 |
1223 | +++ quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py 2011-08-16 07:50:17 +0000 |
1224 | @@ -1,3 +1,4 @@ |
1225 | +""" |
1226 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1227 | # |
1228 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1229 | @@ -17,15 +18,14 @@ |
1230 | # @author: Sumit Naiksatam, Cisco Systems Inc. |
1231 | # |
1232 | """ |
1233 | + |
1234 | +""" |
1235 | Implements a UCSM XML API Client |
1236 | """ |
1237 | |
1238 | import httplib |
1239 | import logging as LOG |
1240 | -import string |
1241 | -import subprocess |
1242 | from xml.etree import ElementTree as et |
1243 | -import urllib |
1244 | |
1245 | from quantum.plugins.cisco.common import cisco_constants as const |
1246 | from quantum.plugins.cisco.common import cisco_exceptions as cexc |
1247 | @@ -114,11 +114,13 @@ |
1248 | |
1249 | |
1250 | class CiscoUCSMDriver(): |
1251 | + """UCSM Driver""" |
1252 | |
1253 | def __init__(self): |
1254 | pass |
1255 | |
1256 | def _post_data(self, ucsm_ip, ucsm_username, ucsm_password, data): |
1257 | + """Send command to UCSM in http request""" |
1258 | conn = httplib.HTTPConnection(ucsm_ip) |
1259 | login_data = "<aaaLogin inName=\"" + ucsm_username + \ |
1260 | "\" inPassword=\"" + ucsm_password + "\" />" |
1261 | @@ -129,8 +131,8 @@ |
1262 | LOG.debug(response.reason) |
1263 | LOG.debug(response_data) |
1264 | # TODO (Sumit): If login is not successful, throw exception |
1265 | - xmlTree = et.XML(response_data) |
1266 | - cookie = xmlTree.attrib["outCookie"] |
1267 | + xml_tree = et.XML(response_data) |
1268 | + cookie = xml_tree.attrib["outCookie"] |
1269 | |
1270 | data = data.replace(COOKIE_VALUE, cookie) |
1271 | LOG.debug("POST: %s" % data) |
1272 | @@ -150,65 +152,76 @@ |
1273 | LOG.debug(response_data) |
1274 | |
1275 | def _create_vlan_post_data(self, vlan_name, vlan_id): |
1276 | + """Create command""" |
1277 | data = CREATE_VLAN.replace(VLAN_NAME, vlan_name) |
1278 | data = data.replace(VLAN_ID, vlan_id) |
1279 | return data |
1280 | |
1281 | def _create_profile_post_data(self, profile_name, vlan_name): |
1282 | + """Create command""" |
1283 | data = CREATE_PROFILE.replace(PROFILE_NAME, profile_name) |
1284 | data = data.replace(VLAN_NAME, vlan_name) |
1285 | return data |
1286 | |
1287 | - def _create_profile_client_post_data(self, profile_name, |
1288 | + def _create_pclient_post_data(self, profile_name, |
1289 | profile_client_name): |
1290 | + """Create command""" |
1291 | data = ASSOCIATE_PROFILE.replace(PROFILE_NAME, profile_name) |
1292 | data = data.replace(PROFILE_CLIENT, profile_client_name) |
1293 | return data |
1294 | |
1295 | - def _change_vlan_in_profile_post_data(self, profile_name, old_vlan_name, |
1296 | + def _change_vlaninprof_post_data(self, profile_name, old_vlan_name, |
1297 | new_vlan_name): |
1298 | + """Create command""" |
1299 | data = CHANGE_VLAN_IN_PROFILE.replace(PROFILE_NAME, profile_name) |
1300 | data = data.replace(OLD_VLAN_NAME, old_vlan_name) |
1301 | data = data.replace(VLAN_NAME, new_vlan_name) |
1302 | return data |
1303 | |
1304 | def _delete_vlan_post_data(self, vlan_name): |
1305 | + """Create command""" |
1306 | data = DELETE_VLAN.replace(VLAN_NAME, vlan_name) |
1307 | return data |
1308 | |
1309 | def _delete_profile_post_data(self, profile_name): |
1310 | + """Create command""" |
1311 | data = DELETE_PROFILE.replace(PROFILE_NAME, profile_name) |
1312 | return data |
1313 | |
1314 | def _get_next_dynamic_nic(self): |
1315 | + """Get an avaialble dynamic nic on the host""" |
1316 | dynamic_nic_id = gvif.get_next_dynic() |
1317 | if len(dynamic_nic_id) > 0: |
1318 | return dynamic_nic_id |
1319 | else: |
1320 | - raise cisco_exceptions.NoMoreNics(net_id=net_id, port_id=port_id) |
1321 | + raise cexc.NoMoreNics() |
1322 | |
1323 | def create_vlan(self, vlan_name, vlan_id, ucsm_ip, ucsm_username, |
1324 | ucsm_password): |
1325 | + """Create request for UCSM""" |
1326 | data = self._create_vlan_post_data(vlan_name, vlan_id) |
1327 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1328 | |
1329 | def create_profile(self, profile_name, vlan_name, ucsm_ip, ucsm_username, |
1330 | ucsm_password): |
1331 | + """Create request for UCSM""" |
1332 | data = self._create_profile_post_data(profile_name, vlan_name) |
1333 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1334 | - data = self._create_profile_client_post_data(profile_name, |
1335 | + data = self._create_pclient_post_data(profile_name, |
1336 | profile_name[-16:]) |
1337 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1338 | |
1339 | def change_vlan_in_profile(self, profile_name, old_vlan_name, |
1340 | new_vlan_name, ucsm_ip, ucsm_username, |
1341 | ucsm_password): |
1342 | - data = self._change_vlan_in_profile_post_data(profile_name, |
1343 | + """Create request for UCSM""" |
1344 | + data = self._change_vlaninprof_post_data(profile_name, |
1345 | old_vlan_name, |
1346 | new_vlan_name) |
1347 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1348 | |
1349 | def get_dynamic_nic(self, host): |
1350 | + """Get an avaialble dynamic nic on the host""" |
1351 | # TODO (Sumit): Check availability per host |
1352 | # TODO (Sumit): If not available raise exception |
1353 | # TODO (Sumit): This simple logic assumes that create-port and |
1354 | @@ -222,36 +235,17 @@ |
1355 | return dynamic_nic_name |
1356 | |
1357 | def delete_vlan(self, vlan_name, ucsm_ip, ucsm_username, ucsm_password): |
1358 | + """Create request for UCSM""" |
1359 | data = self._delete_vlan_post_data(vlan_name) |
1360 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1361 | |
1362 | def delete_profile(self, profile_name, ucsm_ip, ucsm_username, |
1363 | ucsm_password): |
1364 | + """Create request for UCSM""" |
1365 | data = self._delete_profile_post_data(profile_name) |
1366 | self._post_data(ucsm_ip, ucsm_username, ucsm_password, data) |
1367 | |
1368 | def release_dynamic_nic(self, host): |
1369 | + """Release a reserved dynamic nic on the host""" |
1370 | # TODO (Sumit): Release on a specific host |
1371 | pass |
1372 | - |
1373 | - |
1374 | -def main(): |
1375 | - client = CiscoUCSMDriver() |
1376 | - #client.create_vlan("quantum-vlan-3", "3","172.20.231.27","admin", |
1377 | - # "c3l12345") |
1378 | - #client.create_profile("q-prof-3", "quantum-vlan-3","172.20.231.27", |
1379 | - # "admin", "c3l12345") |
1380 | - #client.get_dynamic_nic("dummy") |
1381 | - #client.get_dynamic_nic("dummy") |
1382 | - #client.release_dynamic_nic("dummy") |
1383 | - print client.get_dynamic_nic("dummy") |
1384 | - """ |
1385 | - client.change_vlan_in_profile("br100", "default", "test-2", |
1386 | - "172.20.231.27","admin", |
1387 | - "c3l12345") |
1388 | - client.change_vlan_in_profile("br100", "test-2", "default", |
1389 | - "172.20.231.27", "admin", "c3l12345") |
1390 | - """ |
1391 | - |
1392 | -if __name__ == '__main__': |
1393 | - main() |
1394 | |
1395 | === modified file 'quantum/plugins/cisco/ucs/cisco_ucs_plugin.py' |
1396 | --- quantum/plugins/cisco/ucs/cisco_ucs_plugin.py 2011-08-14 19:33:44 +0000 |
1397 | +++ quantum/plugins/cisco/ucs/cisco_ucs_plugin.py 2011-08-16 07:50:17 +0000 |
1398 | @@ -1,3 +1,4 @@ |
1399 | +""" |
1400 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1401 | # |
1402 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1403 | @@ -16,6 +17,7 @@ |
1404 | # |
1405 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1406 | # |
1407 | +""" |
1408 | |
1409 | import logging as LOG |
1410 | |
1411 | @@ -33,6 +35,7 @@ |
1412 | |
1413 | |
1414 | class UCSVICPlugin(L2DevicePluginBase): |
1415 | + """UCS Device Plugin""" |
1416 | _networks = {} |
1417 | |
1418 | def __init__(self): |
1419 | @@ -238,18 +241,20 @@ |
1420 | port_profile[const.PROFILE_VLAN_ID] = conf.DEFAULT_VLAN_ID |
1421 | |
1422 | def _get_profile_name(self, port_id): |
1423 | - #profile_name = conf.PROFILE_NAME_PREFIX + port_id |
1424 | + """Returns the port profile name based on the port UUID""" |
1425 | profile_name = conf.PROFILE_NAME_PREFIX \ |
1426 | + cutil.get16ByteUUID(port_id) |
1427 | return profile_name |
1428 | |
1429 | def _validate_port_state(self, port_state): |
1430 | + """Check the port state""" |
1431 | if port_state.upper() not in (const.PORT_UP, const.PORT_DOWN): |
1432 | raise exc.StateInvalid(port_state=port_state) |
1433 | return True |
1434 | |
1435 | def _validate_attachment(self, tenant_id, network_id, port_id, |
1436 | remote_interface_id): |
1437 | + """Check if the VIF can be attached""" |
1438 | network = self._get_network(tenant_id, network_id) |
1439 | for port in network[const.NET_PORTS].values(): |
1440 | if port[const.ATTACHMENT] == remote_interface_id: |
1441 | @@ -258,22 +263,26 @@ |
1442 | att_id=port[const.ATTACHMENT]) |
1443 | |
1444 | def _get_network(self, tenant_id, network_id): |
1445 | + """Get the network object ref""" |
1446 | network = self._networks.get(network_id) |
1447 | if not network: |
1448 | raise exc.NetworkNotFound(net_id=network_id) |
1449 | return network |
1450 | |
1451 | def _get_vlan_name_for_network(self, tenant_id, network_id): |
1452 | + """Return the VLAN name as set by the L2 network plugin""" |
1453 | net = self._get_network(tenant_id, network_id) |
1454 | vlan_name = net[const.NET_VLAN_NAME] |
1455 | return vlan_name |
1456 | |
1457 | def _get_vlan_id_for_network(self, tenant_id, network_id): |
1458 | + """Return the VLAN id as set by the L2 network plugin""" |
1459 | net = self._get_network(tenant_id, network_id) |
1460 | vlan_id = net[const.NET_VLAN_ID] |
1461 | return vlan_id |
1462 | |
1463 | def _get_port(self, tenant_id, network_id, port_id): |
1464 | + """Get the port object ref""" |
1465 | net = self._get_network(tenant_id, network_id) |
1466 | port = net[const.NET_PORTS].get(port_id) |
1467 | if not port: |
1468 | @@ -282,6 +291,7 @@ |
1469 | |
1470 | def _create_port_profile(self, tenant_id, net_id, port_id, vlan_name, |
1471 | vlan_id): |
1472 | + """Create port profile in UCSM""" |
1473 | if self._port_profile_counter >= int(conf.MAX_UCSM_PORT_PROFILES): |
1474 | raise cexc.UCSMPortProfileLimit(net_id=net_id, port_id=port_id) |
1475 | profile_name = self._get_profile_name(port_id) |
1476 | @@ -294,6 +304,7 @@ |
1477 | return new_port_profile |
1478 | |
1479 | def _delete_port_profile(self, port_id, profile_name): |
1480 | + """Delete port profile in UCSM""" |
1481 | self._client.delete_profile(profile_name, self._ucsm_ip, |
1482 | self._ucsm_username, self._ucsm_password) |
1483 | self._port_profile_counter -= 1 |
looks good.