Merge lp:~cisco-openstack/neutron/l2network-plugin-persistence into lp:neutron/diablo
- l2network-plugin-persistence
- Merge into diablo
Status: | Merged |
---|---|
Approved by: | Salvatore Orlando |
Approved revision: | 76 |
Merged at revision: | 48 |
Proposed branch: | lp:~cisco-openstack/neutron/l2network-plugin-persistence |
Merge into: | lp:neutron/diablo |
Diff against target: |
5302 lines (+2779/-936) 37 files modified
quantum/plugins/cisco/README (+57/-14) quantum/plugins/cisco/__init__.py (+2/-0) quantum/plugins/cisco/common/__init__.py (+2/-0) quantum/plugins/cisco/common/cisco_configparser.py (+4/-5) quantum/plugins/cisco/common/cisco_constants.py (+20/-1) quantum/plugins/cisco/common/cisco_credentials.py (+11/-1) quantum/plugins/cisco/common/cisco_exceptions.py (+53/-6) quantum/plugins/cisco/common/cisco_nova_configuration.py (+10/-8) quantum/plugins/cisco/common/cisco_utils.py (+16/-4) quantum/plugins/cisco/conf/db_conn.ini (+5/-0) quantum/plugins/cisco/conf/nexus.ini (+2/-0) quantum/plugins/cisco/db/api.py (+254/-0) quantum/plugins/cisco/db/l2network_db.py (+346/-0) quantum/plugins/cisco/db/l2network_models.py (+147/-0) quantum/plugins/cisco/db/models.py (+102/-0) quantum/plugins/cisco/l2device_plugin_base.py (+9/-1) quantum/plugins/cisco/l2network_model.py (+47/-24) quantum/plugins/cisco/l2network_model_base.py (+10/-1) quantum/plugins/cisco/l2network_plugin.py (+208/-195) quantum/plugins/cisco/l2network_plugin_configuration.py (+40/-23) quantum/plugins/cisco/nexus/__init__.py (+4/-1) quantum/plugins/cisco/nexus/cisco_nexus_configuration.py (+12/-7) quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py (+73/-167) quantum/plugins/cisco/nexus/cisco_nexus_plugin.py (+20/-6) quantum/plugins/cisco/nexus/cisco_nexus_snippets.py (+156/-0) quantum/plugins/cisco/run_tests.py (+40/-252) quantum/plugins/cisco/tests/unit/test_database.py (+840/-0) quantum/plugins/cisco/tests/unit/test_l2networkApi.py (+180/-110) quantum/plugins/cisco/tests/unit/test_nexus_plugin.py (+3/-4) quantum/plugins/cisco/tests/unit/test_ucs_driver.py (+29/-26) quantum/plugins/cisco/tests/unit/test_ucs_plugin.py (+16/-18) quantum/plugins/cisco/ucs/__init__.py (+2/-0) quantum/plugins/cisco/ucs/cisco_getvif.py (+4/-1) quantum/plugins/cisco/ucs/cisco_ucs_configuration.py (+11/-9) quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py (+26/-10) quantum/plugins/cisco/ucs/cisco_ucs_plugin.py (+17/-5) tests/unit/test_api.py (+1/-37) |
To merge this branch: | bzr merge lp:~cisco-openstack/neutron/l2network-plugin-persistence |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Salvatore Orlando | Approve | ||
Brad Hall (community) | Approve | ||
Review via email: mp+71779@code.launchpad.net |
Commit message
Description of the change
This branch has two main changes over the earlier approved branch (lp:~cisco-openstack/quantum/l2network-plugin):
• Addition of persistence support and framework
• Enhancements/fixes to increase the pylint score. (The pylint score for the modules checked under quantum/
The changes proposed in this branch are again contained within the quantum/
We have also made changes to address the review comments provided for the earlier branch, most notably,
• We address the ID generation issue, as suggested by Salvatore
• We have cleaned up the XML snippets in the nexus driver, as recommended by Dan (we still use them in the ucs driver since it's more convenient to that right now, but we will move them in the future)
• We have moved ssh port-specific details to the conf files
• We have added more descriptive comments so that the network model and device plugin base classes can be better understood. We have also enhanced the README file.
• We still have a single logging component, and we will change that in an upcoming merge.
More specifically on the persistence support in this branch - We would hope that some of the practices we have followed can be promoted to the core Quantum framework. For instance, we found it useful to use the "InnoDB" engine to enforce foreign key constraints. This and other such details related to the persistence framework are highlighted below:
- persistence framework for quantum/
- implementation - mysql as the database and sqlalchmey as the ORM
- quantum/
- l2network_plugin specific new models and db methods have been defined
- vlan_id management implementation using the db has been implemented
- quantum core models and api (for network & port) have been reused within the plugin with the following changes -
- README contains instructions on how to perform the database configurations
- plugin specific changes -
- refactored plugins/
- tests specific changes -
- refactored plugins/
- independent database tests added in plugins/
Thanks
Sumit, Shweta, Rohit
Salvatore Orlando (salvatore-orlando) wrote : | # |
- 70. By Sumit Naiksatam
-
Pulling in changes from lp:quantum.
Sumit Naiksatam (snaiksat) wrote : | # |
> Hi Sumit/Rohit,
>
> I apologise for the "needs fixing" without a proper review, but it seems your
> branch has several conflict with trunk!
Our apologies as well, the conflicts have been fixed.
Brad Hall (bgh) wrote : | # |
1171 + return vlanid
1172 + except exc.NoResultFound:
1173 + pass
Indentation is off there
1244 + except exc.NoResultFound:
1245 + pass
Same here
1315 + return pp
1316 + except exc.NoResultFound:
1317 + pass
And here
1320 +def update_
1321 + newqos=None):
You don't need the "\" there
2454 + res[const.
I think you want const.NETWORKPORTS there?
1975 + const.NET_PORTS: []}
(and here)
4911 + def _make_net_
4912 + res = {const.NET_ID: net_id, const.NET_NAME: net_name}
4913 + res[const.
4914 + return res
(and here)
2460 + res[const.NET_ID] = net_id
There is const.NET_ID used in a lot of places when I think it should be
const.NETWORKID .. but I could be missing something here. Maybe const.NET_ID
is still defined somewher else.
3182 +"""Unittest runner for quantum OVS plugin
Might want to change that to Cisco plugin ;)
3438 +#from quantum.
Might as well nuke that line.. don't think its ever going to be used in this
file.
3740 +class QuantumDB(object):
3741 + """Class conisting of methods to call Quantum db methods"""
3742 + def get_all_
We should probably move this type of stuff into a library since other plugins
will want to use it. Not an issue for this merge though.
- 71. By Rohit Agarwalla
-
Fixed indentation and changed file comments
Rohit Agarwalla (rohitagarwalla) wrote : | # |
Thanks for the review and comments Brad.
> 1171 + return vlanid
> 1172 + except exc.NoResultFound:
> 1173 + pass
>
> Indentation is off there
>
> 1244 + except exc.NoResultFound:
> 1245 + pass
>
> Same here
>
> 1315 + return pp
> 1316 + except exc.NoResultFound:
> 1317 + pass
>
> And here
>
> 1320 +def update_
> newvlanid=None, \
> 1321 + newqos=None):
>
> You don't need the "\" there
>
Fixed.
> 2454 + res[const.
>
> I think you want const.NETWORKPORTS there?
>
> 1975 + const.NET_PORTS: []}
>
> (and here)
>
> 4911 + def _make_net_
> 4912 + res = {const.NET_ID: net_id, const.NET_NAME: net_name}
> 4913 + res[const.
> 4914 + return res
>
> (and here)
>
> 2460 + res[const.NET_ID] = net_id
>
> There is const.NET_ID used in a lot of places when I think it should be
> const.NETWORKID .. but I could be missing something here. Maybe const.NET_ID
> is still defined somewher else.
>
NETWORKPORTS = 'ports'
NET_PORTS = 'net-ports'
NETWORKID = 'network_id'
NET_ID = 'net-id'
There are two different constants defined in cisco/common/
As you would have seen, the make_dict methods create a dictionary with keys as excepted by the api (net-id in this case)
We couldn't define net-id (and others containing '-' ) as variables for the database models and therefore had to use different variables.
> 3182 +"""Unittest runner for quantum OVS plugin
>
> Might want to change that to Cisco plugin ;)
>
> 3438 +#from quantum.
> VlanMapTest
>
> Might as well nuke that line.. don't think its ever going to be used in this
> file.
>
> 3740 +class QuantumDB(object):
> 3741 + """Class conisting of methods to call Quantum db methods"""
> 3742 + def get_all_
>
> We should probably move this type of stuff into a library since other plugins
> will want to use it. Not an issue for this merge though.
Sure, we'll take this an action item.
Brad Hall (bgh) wrote : | # |
> Thanks for the review and comments Brad.
>
> > 1171 + return vlanid
> > 1172 + except exc.NoResultFound:
> > 1173 + pass
> >
> > Indentation is off there
> >
> > 1244 + except exc.NoResultFound:
> > 1245 + pass
> >
> > Same here
> >
> > 1315 + return pp
> > 1316 + except exc.NoResultFound:
> > 1317 + pass
> >
> > And here
> >
> > 1320 +def update_
> > newvlanid=None, \
> > 1321 + newqos=None):
> >
> > You don't need the "\" there
> >
>
> Fixed.
Great, thanks!
>
> > 2454 + res[const.
> >
> > I think you want const.NETWORKPORTS there?
> >
> > 1975 + const.NET_PORTS: []}
> >
> > (and here)
> >
> > 4911 + def _make_net_
> > 4912 + res = {const.NET_ID: net_id, const.NET_NAME: net_name}
> > 4913 + res[const.
> > 4914 + return res
> >
> > (and here)
> >
> > 2460 + res[const.NET_ID] = net_id
> >
> > There is const.NET_ID used in a lot of places when I think it should be
> > const.NETWORKID .. but I could be missing something here. Maybe
> const.NET_ID
> > is still defined somewher else.
> >
>
> NETWORKPORTS = 'ports'
> NET_PORTS = 'net-ports'
>
> NETWORKID = 'network_id'
> NET_ID = 'net-id'
>
> There are two different constants defined in cisco/common/
> As you would have seen, the make_dict methods create a dictionary with keys as
> excepted by the api (net-id in this case)
> We couldn't define net-id (and others containing '-' ) as variables for the
> database models and therefore had to use different variables.
OK, I understand now.. I just didn't see NET_ID in the diff.
> > 3182 +"""Unittest runner for quantum OVS plugin
> >
> > Might want to change that to Cisco plugin ;)
> >
> > 3438 +#from quantum.
> > VlanMapTest
> >
> > Might as well nuke that line.. don't think its ever going to be used in this
> > file.
> >
> > 3740 +class QuantumDB(object):
> > 3741 + """Class conisting of methods to call Quantum db methods"""
> > 3742 + def get_all_
> >
> > We should probably move this type of stuff into a library since other
> plugins
> > will want to use it. Not an issue for this merge though.
>
> Sure, we'll take this an action item.
Awesome, thanks.
- 72. By Rohit Agarwalla
-
pep8 error fixed for l2network_db.py
Salvatore Orlando (salvatore-orlando) wrote : | # |
Hi Rohit,
thanks a lot for proposing this significant improvement on the Cisco plugin.
The code looks good, and, as usual, it is very well written and easy to understand.
I have a few comments below aimed at improving it or understanding whether some bits of it can be "promoted" to quantum core. Please let me know if you have any question.
(Relatively) Major comments:
1 === added file 'quantum/
2 --- quantum/
3 +++ quantum/
This is strange. quantum/
1104 +def create_vlanids():
1105 + """Prepopulates the vlan_bindings table"""
1106 + session = db.get_session()
1107 + try:
1108 + vlanid = session.
1109 + one()
1110 + except exc.MultipleRes
1111 + pass
1112 + except exc.NoResultFound:
1113 + start = int(conf.
1114 + end = int(conf.VLAN_END)
1115 + while start <= end:
1116 + vlanid = l2network_
1117 + session.add(vlanid)
1118 + start += 1
1119 + session.flush()
1120 + return
IMHO this routine could be improved. Pre-population is skipped if a single record is found in the DB. This means that if I change VLAN_START or VLAN_END and I do not destroy the DB, the DB will not be updated.
4168 -4323: These are unit tests specific for quantum.db. I'd propose to have them in a separate file in /tests/unit. Thank you very much for implementing these much-needed unit tests!!!
Minor comments:
335 + 5b. Enter the quantum_l2netowrk database configuration info in the
336 + quantum/
There's a typo in the first line (should be quantum_l2network)
348 your configuration of each of the above files hasn't gone a little kaka
'kaka'? Are you referring to the Real Madrid's Brazilian player :) ? I guess it means something like "screwed". No need to change it, it is just that this term is totally new to me.
1093 +import l2network_models
Please avoid relative imports
1180 + vlanids = session.
1181 + filter_
1182 + all()
1183 + rvlan = vlanids[0]
IMHO using first() instead of all() will improve the efficiency of this routine.
1747 + LOG.debug("Loaded device plugin %s\n" % \
Python logging already adds newline at the end of line. This newline is therefore redundant, unless we need it for other reasons.
2788 -2789 : Indentation can be improved here
2798 + confstr = snipp.CMD_
2799 + confstr = snipp.EXEC_
Consider merging EXEC_CONF_PREFIX and POSTIFIX into a EXEC_CONF_SNIPPET.
Also, since line 2799 is repeated several times, consider moving it into a subroutine.
3144 +FILTER_
3145 + <show xmlns="http://
3146 + <vlan>
3147 + <brief/>
3148 + </vlan>
3149 + </show> """
End delimiter for a docstring is usually in a new line, as you did for other docstrings in the same module.
3517 - 3905: L2NetworkDB and QuantumDB are wrappers around database apis...
- 73. By Rohit Agarwalla
-
Fixes based on review comments
Rohit Agarwalla (rohitagarwalla) wrote : | # |
Hi Salvatore,
Thank you very much for the meticulous review. Appreciate all of your comments. Please find responses in line.
> Hi Rohit,
>
> thanks a lot for proposing this significant improvement on the Cisco plugin.
> The code looks good, and, as usual, it is very well written and easy to
> understand.
>
Thank you !
> I have a few comments below aimed at improving it or understanding whether
> some bits of it can be "promoted" to quantum core. Please let me know if you
> have any question.
>
> (Relatively) Major comments:
>
> 1 === added file 'quantum/
> 2 --- quantum/
> 3 +++ quantum/
>
> This is strange. quantum/
> it is identical to the one in this branch.
>
This file wasn't touched at all in this branch. I have made a checkin based on some of the changes proposed below. I'll try to sync this branch with top of quantum and see if this diff file goes away.
> 1104 +def create_vlanids():
> 1105 + """Prepopulates the vlan_bindings table"""
> 1106 + session = db.get_session()
> 1107 + try:
> 1108 + vlanid = session.
> 1109 + one()
> 1110 + except exc.MultipleRes
> 1111 + pass
> 1112 + except exc.NoResultFound:
> 1113 + start = int(conf.
> 1114 + end = int(conf.VLAN_END)
> 1115 + while start <= end:
> 1116 + vlanid = l2network_
> 1117 + session.add(vlanid)
> 1118 + start += 1
> 1119 + session.flush()
> 1120 + return
>
> IMHO this routine could be improved. Pre-population is skipped if a single
> record is found in the DB. This means that if I change VLAN_START or VLAN_END
> and I do not destroy the DB, the DB will not be updated.
>
Fine observation. Currently, a changed config would require to start on a clean slate as the cleanup of the old config needs to happen at other levels as well. We realize this limitation and have made a note in the cisco plugins README file.
> 4168 -4323: These are unit tests specific for quantum.db. I'd propose to have
> them in a separate file in /tests/unit. Thank you very much for implementing
> these much-needed unit tests!!!
>
Thank you. I'd be very motivated to place them in the quantum framework structure. To begin with, we didn't want to propose directly and wanted to get comments if such tests could be useful (which seems like they are). Also, currently, at the quantum layer we dont have a mysql database that these tests need. I'm thinking of using in-memory database for these tests to run at the quantum level. I also have some extra tests within this class that needs changes at the db/api module (mentioned below). If you think the way it is currently is ok, then I already have this as an action item to followup/work on this as a separate activity.
>
> Minor comments:
>
> 335 + 5b. Enter the quantum_l2netowrk database configuration info in the
> 336 + quantum/
>
> There's a typo in the first line (should be quantum_l2network)
>
> 348 your conf...
- 74. By Rohit Agarwalla
-
merging from lp:quantum
- 75. By Rohit Agarwalla
-
merging with lp:quantum
- 76. By Edgar Magana
-
Code changed base on Reviews
pep8 passed
pylint 9.10
Edgar Magana (emagana) wrote : | # |
Salvatore and Brad,
Thank you so much for your review. Regarding the reviews on the Nexus these are my changes:
> 2788 -2789 : Indentation can be improved here
>
> 2798 + confstr = snipp.CMD_
> 2799 + confstr = snipp.EXEC_
>
> Consider merging EXEC_CONF_PREFIX and POSTIFIX into a EXEC_CONF_SNIPPET.
> Also, since line 2799 is repeated several times, consider moving it into a
> subroutine.
<Edgar> I did both, merged post and pre-fixs and also moved it to a subroutine.
>
> 3144 +FILTER_
> 3145 + <show xmlns="http://
> 3146 + <vlan>
> 3147 + <brief/>
> 3148 + </vlan>
> 3149 + </show> """
> End delimiter for a docstring is usually in a new line, as you did for other
> docstrings in the same module.
>
<Edgar> I did add an extra line after "show" as salvatore suggested.
Thanks!
Salvatore Orlando (salvatore-orlando) wrote : | # |
> Hi Salvatore,
>
> Thank you very much for the meticulous review. Appreciate all of your
> comments. Please find responses in line.
>
> > Hi Rohit,
> >
> > thanks a lot for proposing this significant improvement on the Cisco plugin.
> > The code looks good, and, as usual, it is very well written and easy to
> > understand.
> >
> Thank you !
>
> > I have a few comments below aimed at improving it or understanding whether
> > some bits of it can be "promoted" to quantum core. Please let me know if you
> > have any question.
> >
> > (Relatively) Major comments:
> >
> > 1 === added file 'quantum/
> > 2 --- quantum/
> > 3 +++ quantum/
> >
> > This is strange. quantum/
> seems
> > it is identical to the one in this branch.
> >
> This file wasn't touched at all in this branch. I have made a checkin based on
> some of the changes proposed below. I'll try to sync this branch with top of
> quantum and see if this diff file goes away.
It seems the problem disappeared with your latest push.
>
> > 1104 +def create_vlanids():
> > 1105 + """Prepopulates the vlan_bindings table"""
> > 1106 + session = db.get_session()
> > 1107 + try:
> > 1108 + vlanid = session.
> > 1109 + one()
> > 1110 + except exc.MultipleRes
> > 1111 + pass
> > 1112 + except exc.NoResultFound:
> > 1113 + start = int(conf.
> > 1114 + end = int(conf.VLAN_END)
> > 1115 + while start <= end:
> > 1116 + vlanid = l2network_
> > 1117 + session.add(vlanid)
> > 1118 + start += 1
> > 1119 + session.flush()
> > 1120 + return
> >
> > IMHO this routine could be improved. Pre-population is skipped if a single
> > record is found in the DB. This means that if I change VLAN_START or
> VLAN_END
> > and I do not destroy the DB, the DB will not be updated.
> >
>
> Fine observation. Currently, a changed config would require to start on a
> clean slate as the cleanup of the old config needs to happen at other levels
> as well. We realize this limitation and have made a note in the cisco plugins
> README file.
Fine.
>
> > 4168 -4323: These are unit tests specific for quantum.db. I'd propose to
> have
> > them in a separate file in /tests/unit. Thank you very much for implementing
> > these much-needed unit tests!!!
> >
>
> Thank you. I'd be very motivated to place them in the quantum framework
> structure. To begin with, we didn't want to propose directly and wanted to get
> comments if such tests could be useful (which seems like they are). Also,
> currently, at the quantum layer we dont have a mysql database that these tests
> need. I'm thinking of using in-memory database for these tests to run at the
> quantum level. I also have some extra tests within this class that needs
> changes at the db/api module (mentioned below). If you think the way it is
> currently is ok, then I already have this as an action item to followup/work
> on this as a separate activity.
>
I think they can stay in the cisco dir...
Rohit Agarwalla (rohitagarwalla) wrote : | # |
> > (Relatively) Major comments:
> >
> > 1 === added file 'quantum/
> > 2 --- quantum/
> > 3 +++ quantum/
> >
> > This is strange. quantum/
> seems
> > it is identical to the one in this branch.
> >
> This file wasn't touched at all in this branch. I have made a checkin based on
> some of the changes proposed below. I'll try to sync this branch with top of
> quantum and see if this diff file goes away.
It seems the problem disappeared with your latest push.
Rohit: Yes, a new test_lib.py seems to have been added in one of the revisions on lp:quantum. So, we had to ensure that the cisco branch had that new file to avoid the conflict.
>
> > 4168 -4323: These are unit tests specific for quantum.db. I'd propose to
> have
> > them in a separate file in /tests/unit. Thank you very much for implementing
> > these much-needed unit tests!!!
> >
>
> Thank you. I'd be very motivated to place them in the quantum framework
> structure. To begin with, we didn't want to propose directly and wanted to get
> comments if such tests could be useful (which seems like they are). Also,
> currently, at the quantum layer we dont have a mysql database that these tests
> need. I'm thinking of using in-memory database for these tests to run at the
> quantum level. I also have some extra tests within this class that needs
> changes at the db/api module (mentioned below). If you think the way it is
> currently is ok, then I already have this as an action item to followup/work
> on this as a separate activity.
>
I think they can stay in the cisco directory at the moment. I think we should move them into the main "tests" folder before diablo release though. I will post to the mailing list in order to decide together the best course of action.
Rohit: Sounds like a plan.
>
> > 3517 - 3905: L2NetworkDB and QuantumDB are wrappers around database apis
> uses
> > by test cases. For improve code readability, these classes are typycally put
> > in a separate module. (see /tests/
> >
>
> Absolutely, I'd make this activity as part of moving the reusable tests to the
> quantum level (mentioned in the above comment)
>
No problem.
Rohit: Thanks.
> > Curiosities:
> >
> > 807 === added file 'quantum/
> >
> > Have you considered re-using the code in quantum/db/api.py? If yes, why
> wasn't
> > this code suitable for your needs? I'm asking because it seems this module
> > seems very similar to the db api in quantum.
> >
> > Similar comment for the module quantum/
> > If the reason is the InnoDB engine then we can try and improve modules in
> > quantum/db, thus avoiding code duplication.
> >
>
> Yes, we have indeed considered to reuse this code. We have also preserved the
> credits/authors so that the reviewers are aware of it. Like its mentioned in
> the merge proposal, we made couple of changes in these modules -
> * specify mysql engine for models (InnoDB) - this engine imposes foreign key
> constraints
> * early loading of tables...
Preview Diff
1 | === modified file 'quantum/plugins/cisco/README' |
2 | --- quantum/plugins/cisco/README 2011-08-15 17:13:08 +0000 |
3 | +++ quantum/plugins/cisco/README 2011-08-23 20:09:26 +0000 |
4 | @@ -1,8 +1,8 @@ |
5 | -===================================================================== |
6 | -README: A Framework for a Quantum Plugin Supporting Multiple Switches |
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 |
13 | +:Author: Sumit Naiksatam, Ram Durairaj, Mark Voelker, Edgar Magana, Shweta Padubidri, Rohit Agarwalla, Ying Liu, Debo Dutta |
14 | :Contact: netstack@lists.launchpad.net |
15 | :Web site: https://launchpad.net/~cisco-openstack |
16 | :Copyright: 2011 Cisco Systems, Inc. |
17 | @@ -15,9 +15,11 @@ |
18 | This plugin implementation provides the following capabilities |
19 | to help you take your Layer 2 network for a Quantum leap: |
20 | |
21 | -* A reference implementation a framework for a Quantum Plugin |
22 | -to use multiple devices/switches in a L2 network |
23 | +* A reference implementation for a Quantum Plugin Framework |
24 | +(For details see: http://wiki.openstack.org/quantum-multi-switch-plugin) |
25 | +* Supports multiple switches in the network |
26 | * Supports multiple models of switches concurrently |
27 | +* Supports use of multiple L2 technologies |
28 | * Supports Cisco UCS blade servers with M81KR Virtual Interface Cards |
29 | (aka "Palo adapters") via 802.1Qbh. |
30 | * Supports the Cisco Nexus family of switches. |
31 | @@ -119,6 +121,8 @@ |
32 | # Port number on the Nexus switch to which the UCSM 6120 is connected |
33 | # Use shortened interface syntax, e.g. "3/23" not "Ethernet3/23". |
34 | nexus_port=3/23 |
35 | +#Port number where the SSH will be running at Nexus Switch, e.g.: 22 (Default) |
36 | +nexus_ssh_port=22 |
37 | |
38 | [DRIVER] |
39 | name=quantum.plugins.cisco.nexus.cisco_nexus_network_driver.CiscoNEXUSDriver |
40 | @@ -130,8 +134,23 @@ |
41 | host key changes (e.g. due to replacement of the supervisor or |
42 | clearing of the SSH config on the switch), you may need to repeat |
43 | this step and remove the old hostkey from ~/.ssh/known_hosts. |
44 | - |
45 | -5. Verify that you have the correct credentials for each IP address listed |
46 | + |
47 | +5. Plugin Persistence framework setup: |
48 | + 5a. Create quantum_l2network database in mysql with the following command - |
49 | + |
50 | +mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network" |
51 | + |
52 | + 5b. Enter the quantum_l2network database configuration info in the |
53 | + quantum/plugins/cisco/conf/db_conn.ini file. |
54 | + |
55 | + 5c. If there is a change in the plugin configuration, service would need |
56 | + to be restarted after dropping and re-creating the database using |
57 | + the following commands - |
58 | + |
59 | +mysql -u<mysqlusername> -p<mysqlpassword> -e "drop database quantum_l2network" |
60 | +mysql -u<mysqlusername> -p<mysqlpassword> -e "create database quantum_l2network" |
61 | + |
62 | +6. Verify that you have the correct credentials for each IP address listed |
63 | in quantum/plugins/cisco/conf/credentials.ini. Example: |
64 | |
65 | # Provide the UCSM credentials |
66 | @@ -152,7 +171,7 @@ |
67 | username=admin |
68 | password=mySecretPasswordForNexus |
69 | |
70 | -6. Start the Quantum service. If something doesn't work, verify that |
71 | +7. Start the Quantum service. If something doesn't work, verify that |
72 | your configuration of each of the above files hasn't gone a little kaka. |
73 | Once you've put right what once went wrong, leap on. |
74 | |
75 | @@ -160,7 +179,8 @@ |
76 | How to test the installation |
77 | ---------------------------- |
78 | The unit tests are located at quantum/plugins/cisco/tests/unit. They can be |
79 | -executed from quantum/plugins/cisco/ using the run_tests.py script. |
80 | +executed from the main folder using the run_tests.sh or to get a more detailed |
81 | +result the quantum/plugins/cisco/run_tests.py script. |
82 | |
83 | 1. Testing the core API (without UCS/Nexus/RHEL hardware, and can be run on |
84 | Ubuntu): |
85 | @@ -168,18 +188,41 @@ |
86 | quantum/plugins/cisco/conf/plugins.ini |
87 | Then run the test script: |
88 | |
89 | -python run_tests.py unit.test_l2networkApi |
90 | + Set the environment variable PLUGIN_DIR to the location of the plugin |
91 | + directory. This is manadatory if the run_tests.sh script is used. |
92 | + |
93 | + export PLUGIN_DIR=quantum/plugins/cisco |
94 | + ./run_tests.sh quantum.plugins.cisco.tests.unit.test_l2networkApi |
95 | + |
96 | + or |
97 | + |
98 | + python quantum/plugins/cisco/run_tests.py |
99 | + quantum.plugins.cisco.tests.unit.test_l2networkApi |
100 | |
101 | 2. Specific Plugin unit test (needs environment setup as indicated in the |
102 | pre-requisites): |
103 | - python run_tests.py unit.<name_of_the file> |
104 | + |
105 | + export PLUGIN_DIR=quantum/plugins/cisco |
106 | + ./run_tests.sh quantum.plugins.cisco.tests.unit.<name_of_the file> |
107 | + |
108 | + or |
109 | + |
110 | + python <path to the plugin directory>/run_tests.py |
111 | + quantum.plugins.cisco.tests.unit.<name_of_the file> |
112 | E.g.: |
113 | |
114 | -python run_tests.py unit.test_ucs_plugin.py |
115 | + python quantum/plugins/cisco/run_tests.py |
116 | + quantum.plugins.cisco.tests.unit.test_ucs_plugin.py |
117 | |
118 | 3. All unit tests (needs environment setup as indicated in the pre-requisites): |
119 | |
120 | -python run_tests.py unit |
121 | + export PLUGIN_DIR=quantum/plugins/cisco |
122 | + ./run_tests.sh quantum.plugins.cisco.tests.unit |
123 | + |
124 | + or |
125 | + |
126 | + python quantum/plugins/cisco/run_tests.py quantum.plugins.cisco.tests.unit |
127 | + |
128 | |
129 | |
130 | Additional installation required on Nova Compute |
131 | |
132 | === modified file 'quantum/plugins/cisco/__init__.py' |
133 | --- quantum/plugins/cisco/__init__.py 2011-07-31 19:04:01 +0000 |
134 | +++ quantum/plugins/cisco/__init__.py 2011-08-23 20:09:26 +0000 |
135 | @@ -1,3 +1,4 @@ |
136 | +""" |
137 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
138 | # |
139 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
140 | @@ -16,3 +17,4 @@ |
141 | # |
142 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
143 | # |
144 | +""" |
145 | |
146 | === modified file 'quantum/plugins/cisco/common/__init__.py' |
147 | --- quantum/plugins/cisco/common/__init__.py 2011-07-31 19:04:01 +0000 |
148 | +++ quantum/plugins/cisco/common/__init__.py 2011-08-23 20:09:26 +0000 |
149 | @@ -1,3 +1,4 @@ |
150 | +""" |
151 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
152 | # |
153 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
154 | @@ -16,3 +17,4 @@ |
155 | # |
156 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
157 | # |
158 | +""" |
159 | |
160 | === modified file 'quantum/plugins/cisco/common/cisco_configparser.py' |
161 | --- quantum/plugins/cisco/common/cisco_configparser.py 2011-08-14 01:28:02 +0000 |
162 | +++ quantum/plugins/cisco/common/cisco_configparser.py 2011-08-23 20:09:26 +0000 |
163 | @@ -1,3 +1,4 @@ |
164 | +""" |
165 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
166 | # |
167 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
168 | @@ -16,25 +17,23 @@ |
169 | # |
170 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
171 | # |
172 | +""" |
173 | |
174 | import logging as LOG |
175 | -import os |
176 | - |
177 | from configobj import ConfigObj |
178 | -from validate import Validator |
179 | - |
180 | from quantum.plugins.cisco.common import cisco_constants as const |
181 | -from quantum.plugins.cisco.common import cisco_exceptions as cexc |
182 | |
183 | LOG.basicConfig(level=LOG.WARN) |
184 | LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
185 | |
186 | |
187 | class CiscoConfigParser(ConfigObj): |
188 | + """Config Parser based on the ConfigObj module""" |
189 | |
190 | def __init__(self, filename): |
191 | super(CiscoConfigParser, self).__init__(filename, raise_errors=True, |
192 | file_error=True) |
193 | |
194 | def dummy(self, section, key): |
195 | + """Dummy function to return the same key, used in walk""" |
196 | return section[key] |
197 | |
198 | === modified file 'quantum/plugins/cisco/common/cisco_constants.py' |
199 | --- quantum/plugins/cisco/common/cisco_constants.py 2011-08-07 11:58:50 +0000 |
200 | +++ quantum/plugins/cisco/common/cisco_constants.py 2011-08-23 20:09:26 +0000 |
201 | @@ -1,3 +1,4 @@ |
202 | +""" |
203 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
204 | # |
205 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
206 | @@ -16,13 +17,29 @@ |
207 | # |
208 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
209 | # |
210 | +""" |
211 | |
212 | PLUGINS = 'PLUGINS' |
213 | |
214 | PORT_STATE = 'port-state' |
215 | -PORT_UP = "UP" |
216 | +PORT_UP = "ACTIVE" |
217 | PORT_DOWN = "DOWN" |
218 | |
219 | +UUID = 'uuid' |
220 | +TENANTID = 'tenant_id' |
221 | +NETWORKID = 'network_id' |
222 | +NETWORKNAME = 'name' |
223 | +NETWORKPORTS = 'ports' |
224 | +INTERFACEID = 'interface_id' |
225 | +PORTSTATE = 'state' |
226 | +PORTID = 'port_id' |
227 | +PPNAME = 'name' |
228 | +PPVLANID = 'vlan_id' |
229 | +PPQOS = 'qos' |
230 | +PPID = 'portprofile_id' |
231 | +PPDEFAULT = 'default' |
232 | +VLANID = 'vlan_id' |
233 | + |
234 | ATTACHMENT = 'attachment' |
235 | PORT_ID = 'port-id' |
236 | |
237 | @@ -101,3 +118,5 @@ |
238 | PARAM_LIST = 'param-list' |
239 | |
240 | DEVICE_IP = 'device-ip' |
241 | + |
242 | +NO_VLAN_ID = 0 |
243 | |
244 | === modified file 'quantum/plugins/cisco/common/cisco_credentials.py' |
245 | --- quantum/plugins/cisco/common/cisco_credentials.py 2011-08-14 01:28:02 +0000 |
246 | +++ quantum/plugins/cisco/common/cisco_credentials.py 2011-08-23 20:09:26 +0000 |
247 | @@ -1,3 +1,4 @@ |
248 | +""" |
249 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
250 | # |
251 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
252 | @@ -16,6 +17,7 @@ |
253 | # |
254 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
255 | # |
256 | +""" |
257 | |
258 | import logging as LOG |
259 | import os |
260 | @@ -34,27 +36,35 @@ |
261 | |
262 | |
263 | class Store(object): |
264 | + """Credential Store""" |
265 | + |
266 | @staticmethod |
267 | def putCredential(id, username, password): |
268 | + """Set the username and password""" |
269 | _creds_dictionary[id] = {const.USERNAME: username, |
270 | - const.PASSWORD: password} |
271 | + const.PASSWORD: password} |
272 | |
273 | @staticmethod |
274 | def getUsername(id): |
275 | + """Get the username""" |
276 | return _creds_dictionary[id][const.USERNAME] |
277 | |
278 | @staticmethod |
279 | def getPassword(id): |
280 | + """Get the password""" |
281 | return _creds_dictionary[id][const.PASSWORD] |
282 | |
283 | @staticmethod |
284 | def getCredential(id): |
285 | + """Get the username and password""" |
286 | return _creds_dictionary[id] |
287 | |
288 | @staticmethod |
289 | def getCredentials(): |
290 | + """Get all usernames and passwords""" |
291 | return _creds_dictionary |
292 | |
293 | @staticmethod |
294 | def deleteCredential(id): |
295 | + """Delete a credential""" |
296 | return _creds_dictionary.pop(id) |
297 | |
298 | === modified file 'quantum/plugins/cisco/common/cisco_exceptions.py' |
299 | --- quantum/plugins/cisco/common/cisco_exceptions.py 2011-07-31 18:38:26 +0000 |
300 | +++ quantum/plugins/cisco/common/cisco_exceptions.py 2011-08-23 20:09:26 +0000 |
301 | @@ -1,3 +1,4 @@ |
302 | +""" |
303 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
304 | # |
305 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
306 | @@ -15,43 +16,89 @@ |
307 | # under the License. |
308 | # |
309 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
310 | -# |
311 | - |
312 | +# @author: Rohit Agarwalla, Cisco Systems, Inc. |
313 | +""" |
314 | """ |
315 | Exceptions used by the Cisco plugin |
316 | """ |
317 | - |
318 | from quantum.common import exceptions |
319 | |
320 | |
321 | class NoMoreNics(exceptions.QuantumException): |
322 | - message = _("Unable to complete operation on port %(port_id)s " \ |
323 | - "for network %(net_id)s. No more dynamic nics are available" \ |
324 | - "in the system.") |
325 | + """No more dynamic nics are available in the system""" |
326 | + message = _("Unable to complete operation. No more dynamic nics are " \ |
327 | + "available in the system.") |
328 | |
329 | |
330 | class PortProfileLimit(exceptions.QuantumException): |
331 | + """Port profile limit has been hit""" |
332 | message = _("Unable to complete operation on port %(port_id)s " \ |
333 | "for network %(net_id)s. The system has reached the maximum" \ |
334 | "limit of allowed port profiles.") |
335 | |
336 | |
337 | class UCSMPortProfileLimit(exceptions.QuantumException): |
338 | + """UCSM Port profile limit has been hit""" |
339 | message = _("Unable to complete operation on port %(port_id)s " \ |
340 | "for network %(net_id)s. The system has reached the maximum" \ |
341 | "limit of allowed UCSM port profiles.") |
342 | |
343 | |
344 | class NetworksLimit(exceptions.QuantumException): |
345 | + """Total number of network objects limit has been hit""" |
346 | message = _("Unable to create new network. Number of networks" \ |
347 | "for the system has exceeded the limit") |
348 | |
349 | |
350 | class PortProfileNotFound(exceptions.QuantumException): |
351 | + """Port profile cannot be found""" |
352 | message = _("Port profile %(portprofile_id)s could not be found " \ |
353 | "for tenant %(tenant_id)s") |
354 | |
355 | |
356 | class PortProfileInvalidDelete(exceptions.QuantumException): |
357 | + """Port profile cannot be deleted since its being used""" |
358 | message = _("Port profile %(profile_id)s could not be deleted " \ |
359 | "for tenant %(tenant_id)s since port associations exist") |
360 | + |
361 | + |
362 | +class NetworkVlanBindingAlreadyExists(exceptions.QuantumException): |
363 | + """Binding cannot be created, since it already exists""" |
364 | + message = _("NetworkVlanBinding for %(vlan_id)s and network " \ |
365 | + "%(network_id)s already exists") |
366 | + |
367 | + |
368 | +class PortProfileAlreadyExists(exceptions.QuantumException): |
369 | + """Port profile cannot be created since it already exisits""" |
370 | + message = _("PortProfile %(pp_name) for %(tenant_id)s " \ |
371 | + "already exists") |
372 | + |
373 | + |
374 | +class PortProfileBindingAlreadyExists(exceptions.QuantumException): |
375 | + """Binding cannot be created, since it already exists""" |
376 | + message = _("PortProfileBinding for port profile %(pp_id)s to " \ |
377 | + "port %(port_id) already exists") |
378 | + |
379 | + |
380 | +class VlanIDNotFound(exceptions.QuantumException): |
381 | + """VLAN ID cannot be found""" |
382 | + message = _("Vlan ID %(vlan_id)s not found") |
383 | + |
384 | + |
385 | +class VlanIDNotAvailable(exceptions.QuantumException): |
386 | + """VLAN ID is reserved""" |
387 | + message = _("No available Vlan ID found") |
388 | + |
389 | +try: |
390 | + _("test") |
391 | +except NameError: |
392 | + |
393 | + def _(a_string): |
394 | + """ |
395 | + Default implementation of the gettext string |
396 | + translation function: no translation |
397 | + """ |
398 | + return a_string |
399 | +except TypeError: |
400 | + # during doctesting, _ might mean something else |
401 | + pass |
402 | |
403 | === modified file 'quantum/plugins/cisco/common/cisco_nova_configuration.py' |
404 | --- quantum/plugins/cisco/common/cisco_nova_configuration.py 2011-08-14 01:28:02 +0000 |
405 | +++ quantum/plugins/cisco/common/cisco_nova_configuration.py 2011-08-23 20:09:26 +0000 |
406 | @@ -1,3 +1,4 @@ |
407 | +""" |
408 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
409 | # |
410 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
411 | @@ -16,6 +17,7 @@ |
412 | # |
413 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
414 | # |
415 | +""" |
416 | |
417 | import os |
418 | |
419 | @@ -23,13 +25,13 @@ |
420 | |
421 | CONF_FILE = "../conf/nova.ini" |
422 | |
423 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
424 | +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
425 | + "/" + CONF_FILE) |
426 | |
427 | -section = cp['NOVA'] |
428 | -DB_SERVER_IP = section['db_server_ip'] |
429 | -DB_NAME = section['db_name'] |
430 | -DB_USERNAME = section['db_username'] |
431 | -DB_PASSWORD = section['db_password'] |
432 | -NOVA_HOST_NAME = section['nova_host_name'] |
433 | -NOVA_PROJ_NAME = section['nova_proj_name'] |
434 | +SECTION = CP['NOVA'] |
435 | +DB_SERVER_IP = SECTION['db_server_ip'] |
436 | +DB_NAME = SECTION['db_name'] |
437 | +DB_USERNAME = SECTION['db_username'] |
438 | +DB_PASSWORD = SECTION['db_password'] |
439 | +NOVA_HOST_NAME = SECTION['nova_host_name'] |
440 | +NOVA_PROJ_NAME = SECTION['nova_proj_name'] |
441 | |
442 | === modified file 'quantum/plugins/cisco/common/cisco_utils.py' |
443 | --- quantum/plugins/cisco/common/cisco_utils.py 2011-08-05 09:59:54 +0000 |
444 | +++ quantum/plugins/cisco/common/cisco_utils.py 2011-08-23 20:09:26 +0000 |
445 | @@ -1,3 +1,4 @@ |
446 | +""" |
447 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
448 | # |
449 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
450 | @@ -16,27 +17,36 @@ |
451 | # |
452 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
453 | # |
454 | +""" |
455 | |
456 | +import hashlib |
457 | +import logging as LOG |
458 | import MySQLdb |
459 | -import logging as LOG |
460 | -import sys |
461 | import traceback |
462 | |
463 | -from quantum.common import exceptions as exc |
464 | from quantum.plugins.cisco.common import cisco_constants as const |
465 | -from quantum.plugins.cisco.common import cisco_credentials as cred |
466 | from quantum.plugins.cisco.common import cisco_nova_configuration as conf |
467 | |
468 | LOG.basicConfig(level=LOG.WARN) |
469 | LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
470 | |
471 | |
472 | +def get16ByteUUID(uuid): |
473 | + """ |
474 | + Return a 16 byte has of the UUID, used when smaller unique |
475 | + ID is required. |
476 | + """ |
477 | + return hashlib.md5(uuid).hexdigest()[:16] |
478 | + |
479 | + |
480 | class DBUtils(object): |
481 | + """Utilities to use connect to MySQL DB and execute queries""" |
482 | |
483 | def __init__(self): |
484 | pass |
485 | |
486 | def _get_db_connection(self): |
487 | + """Get a connection to the DB""" |
488 | db_ip = conf.DB_SERVER_IP |
489 | db_username = conf.DB_USERNAME |
490 | db_password = conf.DB_PASSWORD |
491 | @@ -45,6 +55,7 @@ |
492 | return self.db |
493 | |
494 | def execute_db_query(self, sql_query): |
495 | + """Execute a DB query""" |
496 | db = self._get_db_connection() |
497 | cursor = db.cursor() |
498 | try: |
499 | @@ -52,6 +63,7 @@ |
500 | results = cursor.fetchall() |
501 | db.commit() |
502 | LOG.debug("DB query execution succeeded: %s" % sql_query) |
503 | + db.close() |
504 | except: |
505 | db.rollback() |
506 | LOG.debug("DB query execution failed: %s" % sql_query) |
507 | |
508 | === added file 'quantum/plugins/cisco/conf/db_conn.ini' |
509 | --- quantum/plugins/cisco/conf/db_conn.ini 1970-01-01 00:00:00 +0000 |
510 | +++ quantum/plugins/cisco/conf/db_conn.ini 2011-08-23 20:09:26 +0000 |
511 | @@ -0,0 +1,5 @@ |
512 | +[DATABASE] |
513 | +name = quantum_l2network |
514 | +user = <put_db_user_name_here> |
515 | +pass = <put_db_password_here> |
516 | +host = <put_quantum_mysql_host_here> |
517 | |
518 | === modified file 'quantum/plugins/cisco/conf/nexus.ini' |
519 | --- quantum/plugins/cisco/conf/nexus.ini 2011-08-05 09:59:54 +0000 |
520 | +++ quantum/plugins/cisco/conf/nexus.ini 2011-08-23 20:09:26 +0000 |
521 | @@ -3,6 +3,8 @@ |
522 | nexus_ip_address=<put_nexus_switch_ip_address_here> |
523 | #Port number of the Interface connected from the Nexus 7K Switch to UCSM 6120, e.g.: 3/23 |
524 | nexus_port=<put_interface_name_here> |
525 | +#Port number where the SSH will be running at the Nexus Switch, e.g.: 22 (Default) |
526 | +nexus_ssh_port=22 |
527 | |
528 | [DRIVER] |
529 | name=quantum.plugins.cisco.nexus.cisco_nexus_network_driver.CiscoNEXUSDriver |
530 | |
531 | === added file 'quantum/plugins/cisco/db/api.py' |
532 | --- quantum/plugins/cisco/db/api.py 1970-01-01 00:00:00 +0000 |
533 | +++ quantum/plugins/cisco/db/api.py 2011-08-23 20:09:26 +0000 |
534 | @@ -0,0 +1,254 @@ |
535 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
536 | +# Copyright 2011 Nicira Networks, Inc. |
537 | +# All Rights Reserved. |
538 | +# |
539 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
540 | +# not use this file except in compliance with the License. You may obtain |
541 | +# a copy of the License at |
542 | +# |
543 | +# http://www.apache.org/licenses/LICENSE-2.0 |
544 | +# |
545 | +# Unless required by applicable law or agreed to in writing, software |
546 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
547 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
548 | +# License for the specific language governing permissions and limitations |
549 | +# under the License. |
550 | +# @author: Somik Behera, Nicira Networks, Inc. |
551 | +# @author: Brad Hall, Nicira Networks, Inc. |
552 | +# @author: Dan Wendlandt, Nicira Networks, Inc. |
553 | + |
554 | +from sqlalchemy import create_engine |
555 | +from sqlalchemy.orm import sessionmaker, exc, joinedload |
556 | + |
557 | +from quantum.common import exceptions as q_exc |
558 | +from quantum.plugins.cisco.db import models |
559 | + |
560 | +_ENGINE = None |
561 | +_MAKER = None |
562 | +BASE = models.BASE |
563 | + |
564 | + |
565 | +def configure_db(options): |
566 | + """ |
567 | + Establish the database, create an engine if needed, and |
568 | + register the models. |
569 | + |
570 | + :param options: Mapping of configuration options |
571 | + """ |
572 | + global _ENGINE |
573 | + if not _ENGINE: |
574 | + _ENGINE = create_engine(options['sql_connection'], |
575 | + echo=False, |
576 | + echo_pool=True, |
577 | + pool_recycle=3600) |
578 | + register_models() |
579 | + |
580 | + |
581 | +def clear_db(): |
582 | + global _ENGINE |
583 | + assert _ENGINE |
584 | + for table in reversed(BASE.metadata.sorted_tables): |
585 | + _ENGINE.execute(table.delete()) |
586 | + |
587 | + |
588 | +def get_session(autocommit=True, expire_on_commit=False): |
589 | + """Helper method to grab session""" |
590 | + global _MAKER, _ENGINE |
591 | + if not _MAKER: |
592 | + assert _ENGINE |
593 | + _MAKER = sessionmaker(bind=_ENGINE, |
594 | + autocommit=autocommit, |
595 | + expire_on_commit=expire_on_commit) |
596 | + return _MAKER() |
597 | + |
598 | + |
599 | +def register_models(): |
600 | + """Register Models and create properties""" |
601 | + global _ENGINE |
602 | + assert _ENGINE |
603 | + BASE.metadata.create_all(_ENGINE) |
604 | + |
605 | + |
606 | +def unregister_models(): |
607 | + """Unregister Models, useful clearing out data before testing""" |
608 | + global _ENGINE |
609 | + assert _ENGINE |
610 | + BASE.metadata.drop_all(_ENGINE) |
611 | + |
612 | + |
613 | +def _check_duplicate_net_name(tenant_id, net_name): |
614 | + session = get_session() |
615 | + try: |
616 | + net = session.query(models.Network).\ |
617 | + filter_by(tenant_id=tenant_id, name=net_name).\ |
618 | + one() |
619 | + raise q_exc.NetworkNameExists(tenant_id=tenant_id, |
620 | + net_name=net_name, net_id=net.uuid) |
621 | + except exc.NoResultFound: |
622 | + # this is the "normal" path, as API spec specifies |
623 | + # that net-names are unique within a tenant |
624 | + pass |
625 | + |
626 | + |
627 | +def network_create(tenant_id, name): |
628 | + session = get_session() |
629 | + |
630 | + _check_duplicate_net_name(tenant_id, name) |
631 | + with session.begin(): |
632 | + net = models.Network(tenant_id, name) |
633 | + session.add(net) |
634 | + session.flush() |
635 | + return net |
636 | + |
637 | + |
638 | +def network_list(tenant_id): |
639 | + session = get_session() |
640 | + return session.query(models.Network).\ |
641 | + options(joinedload(models.Network.ports)). \ |
642 | + filter_by(tenant_id=tenant_id).\ |
643 | + all() |
644 | + |
645 | + |
646 | +def network_get(net_id): |
647 | + session = get_session() |
648 | + try: |
649 | + return session.query(models.Network).\ |
650 | + options(joinedload(models.Network.ports)). \ |
651 | + filter_by(uuid=net_id).\ |
652 | + one() |
653 | + except exc.NoResultFound, e: |
654 | + raise q_exc.NetworkNotFound(net_id=net_id) |
655 | + |
656 | + |
657 | +def network_rename(tenant_id, net_id, new_name): |
658 | + session = get_session() |
659 | + net = network_get(net_id) |
660 | + _check_duplicate_net_name(tenant_id, new_name) |
661 | + net.name = new_name |
662 | + session.merge(net) |
663 | + session.flush() |
664 | + return net |
665 | + |
666 | + |
667 | +def network_destroy(net_id): |
668 | + session = get_session() |
669 | + try: |
670 | + net = session.query(models.Network).\ |
671 | + filter_by(uuid=net_id).\ |
672 | + one() |
673 | + session.delete(net) |
674 | + session.flush() |
675 | + return net |
676 | + except exc.NoResultFound: |
677 | + raise q_exc.NetworkNotFound(net_id=net_id) |
678 | + |
679 | + |
680 | +def port_create(net_id, state=None): |
681 | + # confirm network exists |
682 | + network_get(net_id) |
683 | + |
684 | + session = get_session() |
685 | + with session.begin(): |
686 | + port = models.Port(net_id) |
687 | + port['state'] = state or 'DOWN' |
688 | + session.add(port) |
689 | + session.flush() |
690 | + return port |
691 | + |
692 | + |
693 | +def port_list(net_id): |
694 | + session = get_session() |
695 | + return session.query(models.Port).\ |
696 | + options(joinedload(models.Port.network)). \ |
697 | + filter_by(network_id=net_id).\ |
698 | + all() |
699 | + |
700 | + |
701 | +def port_get(net_id, port_id): |
702 | + # confirm network exists |
703 | + network_get(net_id) |
704 | + session = get_session() |
705 | + try: |
706 | + return session.query(models.Port).\ |
707 | + filter_by(uuid=port_id).\ |
708 | + filter_by(network_id=net_id).\ |
709 | + one() |
710 | + except exc.NoResultFound: |
711 | + raise q_exc.PortNotFound(net_id=net_id, port_id=port_id) |
712 | + |
713 | + |
714 | +def port_set_state(net_id, port_id, new_state): |
715 | + if new_state not in ('ACTIVE', 'DOWN'): |
716 | + raise q_exc.StateInvalid(port_state=new_state) |
717 | + |
718 | + # confirm network exists |
719 | + network_get(net_id) |
720 | + |
721 | + port = port_get(net_id, port_id) |
722 | + session = get_session() |
723 | + port.state = new_state |
724 | + session.merge(port) |
725 | + session.flush() |
726 | + return port |
727 | + |
728 | + |
729 | +def port_set_attachment(net_id, port_id, new_interface_id): |
730 | + # confirm network exists |
731 | + network_get(net_id) |
732 | + |
733 | + session = get_session() |
734 | + port = port_get(net_id, port_id) |
735 | + |
736 | + if new_interface_id != "": |
737 | + # We are setting, not clearing, the attachment-id |
738 | + if port['interface_id']: |
739 | + raise q_exc.PortInUse(net_id=net_id, port_id=port_id, |
740 | + att_id=port['interface_id']) |
741 | + |
742 | + try: |
743 | + port = session.query(models.Port).\ |
744 | + filter_by(interface_id=new_interface_id).\ |
745 | + one() |
746 | + raise q_exc.AlreadyAttached(net_id=net_id, |
747 | + port_id=port_id, |
748 | + att_id=new_interface_id, |
749 | + att_port_id=port['uuid']) |
750 | + except exc.NoResultFound: |
751 | + # this is what should happen |
752 | + pass |
753 | + port.interface_id = new_interface_id |
754 | + session.merge(port) |
755 | + session.flush() |
756 | + return port |
757 | + |
758 | + |
759 | +def port_unset_attachment(net_id, port_id): |
760 | + # confirm network exists |
761 | + network_get(net_id) |
762 | + |
763 | + session = get_session() |
764 | + port = port_get(net_id, port_id) |
765 | + port.interface_id = None |
766 | + session.merge(port) |
767 | + session.flush() |
768 | + return port |
769 | + |
770 | + |
771 | +def port_destroy(net_id, port_id): |
772 | + # confirm network exists |
773 | + network_get(net_id) |
774 | + |
775 | + session = get_session() |
776 | + try: |
777 | + port = session.query(models.Port).\ |
778 | + filter_by(uuid=port_id).\ |
779 | + filter_by(network_id=net_id).\ |
780 | + one() |
781 | + if port['interface_id']: |
782 | + raise q_exc.PortInUse(net_id=net_id, port_id=port_id, |
783 | + att_id=port['interface_id']) |
784 | + session.delete(port) |
785 | + session.flush() |
786 | + return port |
787 | + except exc.NoResultFound: |
788 | + raise q_exc.PortNotFound(port_id=port_id) |
789 | |
790 | === added file 'quantum/plugins/cisco/db/l2network_db.py' |
791 | --- quantum/plugins/cisco/db/l2network_db.py 1970-01-01 00:00:00 +0000 |
792 | +++ quantum/plugins/cisco/db/l2network_db.py 2011-08-23 20:09:26 +0000 |
793 | @@ -0,0 +1,346 @@ |
794 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
795 | + |
796 | +# Copyright 2011, Cisco Systems, Inc. |
797 | +# |
798 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
799 | +# not use this file except in compliance with the License. You may obtain |
800 | +# a copy of the License at |
801 | +# |
802 | +# http://www.apache.org/licenses/LICENSE-2.0 |
803 | +# |
804 | +# Unless required by applicable law or agreed to in writing, software |
805 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
806 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
807 | +# License for the specific language governing permissions and limitations |
808 | +# under the License. |
809 | +# @author: Rohit Agarwalla, Cisco Systems, Inc. |
810 | + |
811 | +from sqlalchemy.orm import exc |
812 | + |
813 | +from quantum.common import exceptions as q_exc |
814 | +from quantum.plugins.cisco import l2network_plugin_configuration as conf |
815 | +from quantum.plugins.cisco.common import cisco_exceptions as c_exc |
816 | +from quantum.plugins.cisco.db import l2network_models |
817 | + |
818 | +import quantum.plugins.cisco.db.api as db |
819 | + |
820 | + |
821 | +def initialize(): |
822 | + 'Establish database connection and load models' |
823 | + options = {"sql_connection": "mysql://%s:%s@%s/%s" % (conf.DB_USER, |
824 | + conf.DB_PASS, conf.DB_HOST, conf.DB_NAME)} |
825 | + db.configure_db(options) |
826 | + |
827 | + |
828 | +def create_vlanids(): |
829 | + """Prepopulates the vlan_bindings table""" |
830 | + session = db.get_session() |
831 | + try: |
832 | + vlanid = session.query(l2network_models.VlanID).\ |
833 | + one() |
834 | + except exc.MultipleResultsFound: |
835 | + pass |
836 | + except exc.NoResultFound: |
837 | + start = int(conf.VLAN_START) |
838 | + end = int(conf.VLAN_END) |
839 | + while start <= end: |
840 | + vlanid = l2network_models.VlanID(start) |
841 | + session.add(vlanid) |
842 | + start += 1 |
843 | + session.flush() |
844 | + return |
845 | + |
846 | + |
847 | +def get_all_vlanids(): |
848 | + """Gets all the vlanids""" |
849 | + session = db.get_session() |
850 | + try: |
851 | + vlanids = session.query(l2network_models.VlanID).\ |
852 | + all() |
853 | + return vlanids |
854 | + except exc.NoResultFound: |
855 | + return [] |
856 | + |
857 | + |
858 | +def is_vlanid_used(vlan_id): |
859 | + """Checks if a vlanid is in use""" |
860 | + session = db.get_session() |
861 | + try: |
862 | + vlanid = session.query(l2network_models.VlanID).\ |
863 | + filter_by(vlan_id=vlan_id).\ |
864 | + one() |
865 | + return vlanid["vlan_used"] |
866 | + except exc.NoResultFound: |
867 | + raise c_exc.VlanIDNotFound(vlan_id=vlan_id) |
868 | + |
869 | + |
870 | +def release_vlanid(vlan_id): |
871 | + """Sets the vlanid state to be unused""" |
872 | + session = db.get_session() |
873 | + try: |
874 | + vlanid = session.query(l2network_models.VlanID).\ |
875 | + filter_by(vlan_id=vlan_id).\ |
876 | + one() |
877 | + vlanid["vlan_used"] = False |
878 | + session.merge(vlanid) |
879 | + session.flush() |
880 | + return vlanid["vlan_used"] |
881 | + except exc.NoResultFound: |
882 | + raise c_exc.VlanIDNotFound(vlan_id=vlan_id) |
883 | + return |
884 | + |
885 | + |
886 | +def delete_vlanid(vlan_id): |
887 | + """Deletes a vlanid entry from db""" |
888 | + session = db.get_session() |
889 | + try: |
890 | + vlanid = session.query(l2network_models.VlanID).\ |
891 | + filter_by(vlan_id=vlan_id).\ |
892 | + one() |
893 | + session.delete(vlanid) |
894 | + session.flush() |
895 | + return vlanid |
896 | + except exc.NoResultFound: |
897 | + pass |
898 | + |
899 | + |
900 | +def reserve_vlanid(): |
901 | + """Reserves the first unused vlanid""" |
902 | + session = db.get_session() |
903 | + try: |
904 | + rvlan = session.query(l2network_models.VlanID).\ |
905 | + filter_by(vlan_used=False).\ |
906 | + first() |
907 | + rvlanid = session.query(l2network_models.VlanID).\ |
908 | + filter_by(vlan_id=rvlan["vlan_id"]).\ |
909 | + one() |
910 | + rvlanid["vlan_used"] = True |
911 | + session.merge(rvlanid) |
912 | + session.flush() |
913 | + return rvlan["vlan_id"] |
914 | + except exc.NoResultFound: |
915 | + raise c_exc.VlanIDNotAvailable() |
916 | + |
917 | + |
918 | +def get_all_vlan_bindings(): |
919 | + """Lists all the vlan to network associations""" |
920 | + session = db.get_session() |
921 | + try: |
922 | + bindings = session.query(l2network_models.VlanBinding).\ |
923 | + all() |
924 | + return bindings |
925 | + except exc.NoResultFound: |
926 | + return [] |
927 | + |
928 | + |
929 | +def get_vlan_binding(netid): |
930 | + """Lists the vlan given a network_id""" |
931 | + session = db.get_session() |
932 | + try: |
933 | + binding = session.query(l2network_models.VlanBinding).\ |
934 | + filter_by(network_id=netid).\ |
935 | + one() |
936 | + return binding |
937 | + except exc.NoResultFound: |
938 | + raise q_exc.NetworkNotFound(net_id=netid) |
939 | + |
940 | + |
941 | +def add_vlan_binding(vlanid, vlanname, netid): |
942 | + """Adds a vlan to network association""" |
943 | + session = db.get_session() |
944 | + try: |
945 | + binding = session.query(l2network_models.VlanBinding).\ |
946 | + filter_by(vlan_id=vlanid).\ |
947 | + one() |
948 | + raise c_exc.NetworkVlanBindingAlreadyExists(vlan_id=vlanid, |
949 | + network_id=netid) |
950 | + except exc.NoResultFound: |
951 | + binding = l2network_models.VlanBinding(vlanid, vlanname, netid) |
952 | + session.add(binding) |
953 | + session.flush() |
954 | + return binding |
955 | + |
956 | + |
957 | +def remove_vlan_binding(netid): |
958 | + """Removes a vlan to network association""" |
959 | + session = db.get_session() |
960 | + try: |
961 | + binding = session.query(l2network_models.VlanBinding).\ |
962 | + filter_by(network_id=netid).\ |
963 | + one() |
964 | + session.delete(binding) |
965 | + session.flush() |
966 | + return binding |
967 | + except exc.NoResultFound: |
968 | + pass |
969 | + |
970 | + |
971 | +def update_vlan_binding(netid, newvlanid=None, newvlanname=None): |
972 | + """Updates a vlan to network association""" |
973 | + session = db.get_session() |
974 | + try: |
975 | + binding = session.query(l2network_models.VlanBinding).\ |
976 | + filter_by(network_id=netid).\ |
977 | + one() |
978 | + if newvlanid: |
979 | + binding["vlan_id"] = newvlanid |
980 | + if newvlanname: |
981 | + binding["vlan_name"] = newvlanname |
982 | + session.merge(binding) |
983 | + session.flush() |
984 | + return binding |
985 | + except exc.NoResultFound: |
986 | + raise q_exc.NetworkNotFound(net_id=netid) |
987 | + |
988 | + |
989 | +def get_all_portprofiles(): |
990 | + """Lists all the port profiles""" |
991 | + session = db.get_session() |
992 | + try: |
993 | + pps = session.query(l2network_models.PortProfile).\ |
994 | + all() |
995 | + return pps |
996 | + except exc.NoResultFound: |
997 | + return [] |
998 | + |
999 | + |
1000 | +def get_portprofile(tenantid, ppid): |
1001 | + """Lists a port profile""" |
1002 | + session = db.get_session() |
1003 | + try: |
1004 | + pp = session.query(l2network_models.PortProfile).\ |
1005 | + filter_by(uuid=ppid).\ |
1006 | + one() |
1007 | + return pp |
1008 | + except exc.NoResultFound: |
1009 | + raise c_exc.PortProfileNotFound(tenant_id=tenantid, |
1010 | + portprofile_id=ppid) |
1011 | + |
1012 | + |
1013 | +def add_portprofile(tenantid, ppname, vlanid, qos): |
1014 | + """Adds a port profile""" |
1015 | + session = db.get_session() |
1016 | + try: |
1017 | + pp = session.query(l2network_models.PortProfile).\ |
1018 | + filter_by(name=ppname).\ |
1019 | + one() |
1020 | + raise c_exc.PortProfileAlreadyExists(tenant_id=tenantid, |
1021 | + pp_name=ppname) |
1022 | + except exc.NoResultFound: |
1023 | + pp = l2network_models.PortProfile(ppname, vlanid, qos) |
1024 | + session.add(pp) |
1025 | + session.flush() |
1026 | + return pp |
1027 | + |
1028 | + |
1029 | +def remove_portprofile(tenantid, ppid): |
1030 | + """Removes a port profile""" |
1031 | + session = db.get_session() |
1032 | + try: |
1033 | + pp = session.query(l2network_models.PortProfile).\ |
1034 | + filter_by(uuid=ppid).\ |
1035 | + one() |
1036 | + session.delete(pp) |
1037 | + session.flush() |
1038 | + return pp |
1039 | + except exc.NoResultFound: |
1040 | + pass |
1041 | + |
1042 | + |
1043 | +def update_portprofile(tenantid, ppid, newppname=None, newvlanid=None, |
1044 | + newqos=None): |
1045 | + """Updates port profile""" |
1046 | + session = db.get_session() |
1047 | + try: |
1048 | + pp = session.query(l2network_models.PortProfile).\ |
1049 | + filter_by(uuid=ppid).\ |
1050 | + one() |
1051 | + if newppname: |
1052 | + pp["name"] = newppname |
1053 | + if newvlanid: |
1054 | + pp["vlan_id"] = newvlanid |
1055 | + if newqos: |
1056 | + pp["qos"] = newqos |
1057 | + session.merge(pp) |
1058 | + session.flush() |
1059 | + return pp |
1060 | + except exc.NoResultFound: |
1061 | + raise c_exc.PortProfileNotFound(tenant_id=tenantid, |
1062 | + portprofile_id=ppid) |
1063 | + |
1064 | + |
1065 | +def get_all_pp_bindings(): |
1066 | + """Lists all the port profiles""" |
1067 | + session = db.get_session() |
1068 | + try: |
1069 | + bindings = session.query(l2network_models.PortProfileBinding).\ |
1070 | + all() |
1071 | + return bindings |
1072 | + except exc.NoResultFound: |
1073 | + return [] |
1074 | + |
1075 | + |
1076 | +def get_pp_binding(tenantid, ppid): |
1077 | + """Lists a port profile binding""" |
1078 | + session = db.get_session() |
1079 | + try: |
1080 | + binding = session.query(l2network_models.PortProfileBinding).\ |
1081 | + filter_by(portprofile_id=ppid).\ |
1082 | + one() |
1083 | + return binding |
1084 | + except exc.NoResultFound: |
1085 | + return [] |
1086 | + |
1087 | + |
1088 | +def add_pp_binding(tenantid, portid, ppid, default): |
1089 | + """Adds a port profile binding""" |
1090 | + session = db.get_session() |
1091 | + try: |
1092 | + binding = session.query(l2network_models.PortProfileBinding).\ |
1093 | + filter_by(portprofile_id=ppid).\ |
1094 | + one() |
1095 | + raise c_exc.PortProfileBindingAlreadyExists(pp_id=ppid, |
1096 | + port_id=portid) |
1097 | + except exc.NoResultFound: |
1098 | + binding = l2network_models.PortProfileBinding(tenantid, portid, \ |
1099 | + ppid, default) |
1100 | + session.add(binding) |
1101 | + session.flush() |
1102 | + return binding |
1103 | + |
1104 | + |
1105 | +def remove_pp_binding(tenantid, portid, ppid): |
1106 | + """Removes a port profile binding""" |
1107 | + session = db.get_session() |
1108 | + try: |
1109 | + binding = session.query(l2network_models.PortProfileBinding).\ |
1110 | + filter_by(portprofile_id=ppid).\ |
1111 | + filter_by(port_id=portid).\ |
1112 | + one() |
1113 | + session.delete(binding) |
1114 | + session.flush() |
1115 | + return binding |
1116 | + except exc.NoResultFound: |
1117 | + pass |
1118 | + |
1119 | + |
1120 | +def update_pp_binding(tenantid, ppid, newtenantid=None, newportid=None, |
1121 | + newdefault=None): |
1122 | + """Updates port profile binding""" |
1123 | + session = db.get_session() |
1124 | + try: |
1125 | + binding = session.query(l2network_models.PortProfileBinding).\ |
1126 | + filter_by(portprofile_id=ppid).\ |
1127 | + one() |
1128 | + if newtenantid: |
1129 | + binding["tenant_id"] = newtenantid |
1130 | + if newportid: |
1131 | + binding["port_id"] = newportid |
1132 | + if newdefault: |
1133 | + binding["default"] = newdefault |
1134 | + session.merge(binding) |
1135 | + session.flush() |
1136 | + return binding |
1137 | + except exc.NoResultFound: |
1138 | + raise c_exc.PortProfileNotFound(tenant_id=tenantid, |
1139 | + portprofile_id=ppid) |
1140 | |
1141 | === added file 'quantum/plugins/cisco/db/l2network_models.py' |
1142 | --- quantum/plugins/cisco/db/l2network_models.py 1970-01-01 00:00:00 +0000 |
1143 | +++ quantum/plugins/cisco/db/l2network_models.py 2011-08-23 20:09:26 +0000 |
1144 | @@ -0,0 +1,147 @@ |
1145 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1146 | + |
1147 | +# Copyright 2011, Cisco Systems, Inc. |
1148 | +# |
1149 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1150 | +# not use this file except in compliance with the License. You may obtain |
1151 | +# a copy of the License at |
1152 | +# |
1153 | +# http://www.apache.org/licenses/LICENSE-2.0 |
1154 | +# |
1155 | +# Unless required by applicable law or agreed to in writing, software |
1156 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1157 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1158 | +# License for the specific language governing permissions and limitations |
1159 | +# under the License. |
1160 | +# @author: Rohit Agarwalla, Cisco Systems, Inc. |
1161 | + |
1162 | +import uuid |
1163 | + |
1164 | +from sqlalchemy import Column, Integer, String, ForeignKey, Boolean |
1165 | +from sqlalchemy.orm import relation, object_mapper |
1166 | + |
1167 | +from quantum.plugins.cisco.db.models import BASE |
1168 | +from quantum.plugins.cisco.db import models |
1169 | + |
1170 | + |
1171 | +class L2NetworkBase(object): |
1172 | + """Base class for L2Network Models.""" |
1173 | + __table_args__ = {'mysql_engine': 'InnoDB'} |
1174 | + |
1175 | + def __setitem__(self, key, value): |
1176 | + """Internal Dict set method""" |
1177 | + setattr(self, key, value) |
1178 | + |
1179 | + def __getitem__(self, key): |
1180 | + """Internal Dict get method""" |
1181 | + return getattr(self, key) |
1182 | + |
1183 | + def get(self, key, default=None): |
1184 | + """Dict get method""" |
1185 | + return getattr(self, key, default) |
1186 | + |
1187 | + def __iter__(self): |
1188 | + """Iterate over table columns""" |
1189 | + self._i = iter(object_mapper(self).columns) |
1190 | + return self |
1191 | + |
1192 | + def next(self): |
1193 | + """Next method for the iterator""" |
1194 | + n = self._i.next().name |
1195 | + return n, getattr(self, n) |
1196 | + |
1197 | + def update(self, values): |
1198 | + """Make the model object behave like a dict""" |
1199 | + for k, v in values.iteritems(): |
1200 | + setattr(self, k, v) |
1201 | + |
1202 | + def iteritems(self): |
1203 | + """Make the model object behave like a dict" |
1204 | + Includes attributes from joins.""" |
1205 | + local = dict(self) |
1206 | + joined = dict([(k, v) for k, v in self.__dict__.iteritems() |
1207 | + if not k[0] == '_']) |
1208 | + local.update(joined) |
1209 | + return local.iteritems() |
1210 | + |
1211 | + |
1212 | +class VlanID(BASE, L2NetworkBase): |
1213 | + """Represents a vlan_id usage""" |
1214 | + __tablename__ = 'vlan_ids' |
1215 | + |
1216 | + vlan_id = Column(Integer, primary_key=True) |
1217 | + vlan_used = Column(Boolean) |
1218 | + |
1219 | + def __init__(self, vlan_id): |
1220 | + self.vlan_id = vlan_id |
1221 | + self.vlan_used = False |
1222 | + |
1223 | + def __repr__(self): |
1224 | + return "<VlanBinding(%d,%s)>" % \ |
1225 | + (self.vlan_id, self.vlan_used) |
1226 | + |
1227 | + |
1228 | +class VlanBinding(BASE, L2NetworkBase): |
1229 | + """Represents a binding of vlan_id to network_id""" |
1230 | + __tablename__ = 'vlan_bindings' |
1231 | + |
1232 | + vlan_id = Column(Integer, primary_key=True) |
1233 | + vlan_name = Column(String(255)) |
1234 | + network_id = Column(String(255), ForeignKey("networks.uuid"), \ |
1235 | + nullable=False) |
1236 | + network = relation(models.Network, uselist=False) |
1237 | + |
1238 | + def __init__(self, vlan_id, vlan_name, network_id): |
1239 | + self.vlan_id = vlan_id |
1240 | + self.vlan_name = vlan_name |
1241 | + self.network_id = network_id |
1242 | + |
1243 | + def __repr__(self): |
1244 | + return "<VlanBinding(%d,%s,%s)>" % \ |
1245 | + (self.vlan_id, self.vlan_name, self.network_id) |
1246 | + |
1247 | + |
1248 | +class PortProfile(BASE, L2NetworkBase): |
1249 | + """Represents L2 network plugin level PortProfile for a network""" |
1250 | + __tablename__ = 'portprofiles' |
1251 | + |
1252 | + uuid = Column(String(255), primary_key=True) |
1253 | + name = Column(String(255)) |
1254 | + vlan_id = Column(Integer) |
1255 | + qos = Column(String(255)) |
1256 | + |
1257 | + def __init__(self, name, vlan_id, qos=None): |
1258 | + self.uuid = uuid.uuid4() |
1259 | + self.name = name |
1260 | + self.vlan_id = vlan_id |
1261 | + self.qos = qos |
1262 | + |
1263 | + def __repr__(self): |
1264 | + return "<PortProfile(%s,%s,%d,%s)>" % \ |
1265 | + (self.uuid, self.name, self.vlan_id, self.qos) |
1266 | + |
1267 | + |
1268 | +class PortProfileBinding(BASE, L2NetworkBase): |
1269 | + """Represents PortProfile binding to tenant and network""" |
1270 | + __tablename__ = 'portprofile_bindings' |
1271 | + |
1272 | + id = Column(Integer, primary_key=True, autoincrement=True) |
1273 | + tenant_id = Column(String(255)) |
1274 | + |
1275 | + port_id = Column(String(255), ForeignKey("ports.uuid"), \ |
1276 | + nullable=False) |
1277 | + portprofile_id = Column(String(255), ForeignKey("portprofiles.uuid"), \ |
1278 | + nullable=False) |
1279 | + default = Column(Boolean) |
1280 | + ports = relation(models.Port) |
1281 | + portprofile = relation(PortProfile, uselist=False) |
1282 | + |
1283 | + def __init__(self, tenant_id, port_id, portprofile_id, default): |
1284 | + self.tenant_id = tenant_id |
1285 | + self.port_id = port_id |
1286 | + self.portprofile_id = portprofile_id |
1287 | + self.default = default |
1288 | + |
1289 | + def __repr__(self): |
1290 | + return "<PortProfile Binding(%s,%s,%s,%s)>" % \ |
1291 | + (self.tenant_id, self.port_id, self.portprofile_id, self.default) |
1292 | |
1293 | === added file 'quantum/plugins/cisco/db/models.py' |
1294 | --- quantum/plugins/cisco/db/models.py 1970-01-01 00:00:00 +0000 |
1295 | +++ quantum/plugins/cisco/db/models.py 2011-08-23 20:09:26 +0000 |
1296 | @@ -0,0 +1,102 @@ |
1297 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1298 | +# Copyright 2011 Nicira Networks, Inc. |
1299 | +# All Rights Reserved. |
1300 | +# |
1301 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
1302 | +# not use this file except in compliance with the License. You may obtain |
1303 | +# a copy of the License at |
1304 | +# |
1305 | +# http://www.apache.org/licenses/LICENSE-2.0 |
1306 | +# |
1307 | +# Unless required by applicable law or agreed to in writing, software |
1308 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
1309 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
1310 | +# License for the specific language governing permissions and limitations |
1311 | +# under the License. |
1312 | +# @author: Somik Behera, Nicira Networks, Inc. |
1313 | +# @author: Brad Hall, Nicira Networks, Inc. |
1314 | +# @author: Dan Wendlandt, Nicira Networks, Inc. |
1315 | + |
1316 | +import uuid |
1317 | + |
1318 | +from sqlalchemy import Column, String, ForeignKey |
1319 | +from sqlalchemy.ext.declarative import declarative_base |
1320 | +from sqlalchemy.orm import relation, object_mapper |
1321 | + |
1322 | +BASE = declarative_base() |
1323 | + |
1324 | + |
1325 | +class QuantumBase(object): |
1326 | + """Base class for Quantum Models.""" |
1327 | + __table_args__ = {'mysql_engine': 'InnoDB'} |
1328 | + |
1329 | + def __setitem__(self, key, value): |
1330 | + setattr(self, key, value) |
1331 | + |
1332 | + def __getitem__(self, key): |
1333 | + return getattr(self, key) |
1334 | + |
1335 | + def get(self, key, default=None): |
1336 | + return getattr(self, key, default) |
1337 | + |
1338 | + def __iter__(self): |
1339 | + self._i = iter(object_mapper(self).columns) |
1340 | + return self |
1341 | + |
1342 | + def next(self): |
1343 | + n = self._i.next().name |
1344 | + return n, getattr(self, n) |
1345 | + |
1346 | + def update(self, values): |
1347 | + """Make the model object behave like a dict""" |
1348 | + for k, v in values.iteritems(): |
1349 | + setattr(self, k, v) |
1350 | + |
1351 | + def iteritems(self): |
1352 | + """Make the model object behave like a dict. |
1353 | + Includes attributes from joins.""" |
1354 | + local = dict(self) |
1355 | + joined = dict([(k, v) for k, v in self.__dict__.iteritems() |
1356 | + if not k[0] == '_']) |
1357 | + local.update(joined) |
1358 | + return local.iteritems() |
1359 | + |
1360 | + |
1361 | +class Port(BASE, QuantumBase): |
1362 | + """Represents a port on a quantum network""" |
1363 | + __tablename__ = 'ports' |
1364 | + |
1365 | + uuid = Column(String(255), primary_key=True) |
1366 | + network_id = Column(String(255), ForeignKey("networks.uuid"), |
1367 | + nullable=False) |
1368 | + interface_id = Column(String(255)) |
1369 | + # Port state - Hardcoding string value at the moment |
1370 | + state = Column(String(8)) |
1371 | + |
1372 | + def __init__(self, network_id): |
1373 | + self.uuid = str(uuid.uuid4()) |
1374 | + self.network_id = network_id |
1375 | + self.state = "DOWN" |
1376 | + |
1377 | + def __repr__(self): |
1378 | + return "<Port(%s,%s,%s,%s)>" % (self.uuid, self.network_id, |
1379 | + self.state, self.interface_id) |
1380 | + |
1381 | + |
1382 | +class Network(BASE, QuantumBase): |
1383 | + """Represents a quantum network""" |
1384 | + __tablename__ = 'networks' |
1385 | + |
1386 | + uuid = Column(String(255), primary_key=True) |
1387 | + tenant_id = Column(String(255), nullable=False) |
1388 | + name = Column(String(255)) |
1389 | + ports = relation(Port, order_by=Port.uuid, backref="network") |
1390 | + |
1391 | + def __init__(self, tenant_id, name): |
1392 | + self.uuid = str(uuid.uuid4()) |
1393 | + self.tenant_id = tenant_id |
1394 | + self.name = name |
1395 | + |
1396 | + def __repr__(self): |
1397 | + return "<Network(%s,%s,%s)>" % \ |
1398 | + (self.uuid, self.name, self.tenant_id) |
1399 | |
1400 | === modified file 'quantum/plugins/cisco/l2device_plugin_base.py' |
1401 | --- quantum/plugins/cisco/l2device_plugin_base.py 2011-08-07 11:58:50 +0000 |
1402 | +++ quantum/plugins/cisco/l2device_plugin_base.py 2011-08-23 20:09:26 +0000 |
1403 | @@ -1,3 +1,4 @@ |
1404 | +""" |
1405 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1406 | # |
1407 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1408 | @@ -16,12 +17,19 @@ |
1409 | # |
1410 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1411 | # |
1412 | +""" |
1413 | |
1414 | import inspect |
1415 | from abc import ABCMeta, abstractmethod |
1416 | |
1417 | |
1418 | class L2DevicePluginBase(object): |
1419 | + """ |
1420 | + Base class for a device-specific plugin. |
1421 | + An example of a device-specific plugin is a Nexus switch plugin. |
1422 | + The network model relies on device-category-specific plugins to perform |
1423 | + the configuration on each device. |
1424 | + """ |
1425 | |
1426 | __metaclass__ = ABCMeta |
1427 | |
1428 | @@ -133,7 +141,7 @@ |
1429 | marked with the abstractmethod decorator is |
1430 | provided by the plugin class. |
1431 | """ |
1432 | - if cls is QuantumPluginBase: |
1433 | + if cls is L2DevicePluginBase: |
1434 | for method in cls.__abstractmethods__: |
1435 | method_ok = False |
1436 | for base in klass.__mro__: |
1437 | |
1438 | === modified file 'quantum/plugins/cisco/l2network_model.py' |
1439 | --- quantum/plugins/cisco/l2network_model.py 2011-08-14 01:28:02 +0000 |
1440 | +++ quantum/plugins/cisco/l2network_model.py 2011-08-23 20:09:26 +0000 |
1441 | @@ -1,3 +1,4 @@ |
1442 | +""" |
1443 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1444 | # |
1445 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1446 | @@ -16,6 +17,7 @@ |
1447 | # |
1448 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1449 | # |
1450 | +""" |
1451 | |
1452 | import inspect |
1453 | import logging as LOG |
1454 | @@ -30,71 +32,92 @@ |
1455 | |
1456 | |
1457 | class L2NetworkModel(L2NetworkModelBase): |
1458 | + """ |
1459 | + Implements the L2NetworkModelBase |
1460 | + This implementation works with UCS and Nexus plugin, |
1461 | + with one UCS blade, and one Nexus switch. |
1462 | + """ |
1463 | _plugins = {} |
1464 | |
1465 | def __init__(self): |
1466 | - for key in conf.plugins[const.PLUGINS].keys(): |
1467 | + for key in conf.PLUGINS[const.PLUGINS].keys(): |
1468 | self._plugins[key] = utils.import_object( |
1469 | - conf.plugins[const.PLUGINS][key]) |
1470 | - LOG.debug("Loaded device plugin %s\n" % \ |
1471 | - conf.plugins[const.PLUGINS][key]) |
1472 | + conf.PLUGINS[const.PLUGINS][key]) |
1473 | + LOG.debug("Loaded device plugin %s" % \ |
1474 | + conf.PLUGINS[const.PLUGINS][key]) |
1475 | |
1476 | - def _funcName(self, offset=0): |
1477 | + def _func_name(self, offset=0): |
1478 | + """Get the name of the calling function""" |
1479 | return inspect.stack()[1 + offset][3] |
1480 | |
1481 | - def _invokeAllDevicePlugins(self, function_name, args, kwargs): |
1482 | - for pluginObjRef in self._plugins.values(): |
1483 | - getattr(pluginObjRef, function_name)(*args, **kwargs) |
1484 | + def _invoke_all_device_plugins(self, function_name, args, kwargs): |
1485 | + """Invoke all device plugins for this model implementation""" |
1486 | + for plugin_obj_ref in self._plugins.values(): |
1487 | + getattr(plugin_obj_ref, function_name)(*args, **kwargs) |
1488 | |
1489 | - def _invokeUCSPlugin(self, function_name, args, kwargs): |
1490 | + def _invoke_ucs_plugin(self, function_name, args, kwargs): |
1491 | + """Invoke only the UCS plugin""" |
1492 | if const.UCS_PLUGIN in self._plugins.keys(): |
1493 | getattr(self._plugins[const.UCS_PLUGIN], |
1494 | function_name)(*args, **kwargs) |
1495 | |
1496 | - def _invokeNexusPlugin(self, function_name, args, kwargs): |
1497 | + def _invoke_nexus_plugin(self, function_name, args, kwargs): |
1498 | + """Invoke only the Nexus plugin""" |
1499 | if const.NEXUS_PLUGIN in self._plugins.keys(): |
1500 | getattr(self._plugins[const.NEXUS_PLUGIN], |
1501 | function_name)(*args, **kwargs) |
1502 | |
1503 | def get_all_networks(self, args): |
1504 | + """Not implemented for this model""" |
1505 | pass |
1506 | |
1507 | def create_network(self, args): |
1508 | - deviceParams = {const.DEVICE_IP: ""} |
1509 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
1510 | + """Support for the Quantum core API call""" |
1511 | + device_params = {const.DEVICE_IP: ""} |
1512 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
1513 | |
1514 | def delete_network(self, args): |
1515 | - deviceParams = {const.DEVICE_IP: ""} |
1516 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
1517 | + """Support for the Quantum core API call""" |
1518 | + device_params = {const.DEVICE_IP: ""} |
1519 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
1520 | |
1521 | def get_network_details(self, args): |
1522 | + """Not implemented for this model""" |
1523 | pass |
1524 | |
1525 | def rename_network(self, args): |
1526 | - deviceParams = {const.DEVICE_IP: ""} |
1527 | - self._invokeAllDevicePlugins(self._funcName(), args, deviceParams) |
1528 | + """Support for the Quantum core API call""" |
1529 | + device_params = {const.DEVICE_IP: ""} |
1530 | + self._invoke_all_device_plugins(self._func_name(), args, device_params) |
1531 | |
1532 | def get_all_ports(self, args): |
1533 | + """Not implemented for this model""" |
1534 | pass |
1535 | |
1536 | def create_port(self, args): |
1537 | - deviceParams = {const.DEVICE_IP: ""} |
1538 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
1539 | + """Support for the Quantum core API call""" |
1540 | + device_params = {const.DEVICE_IP: ""} |
1541 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
1542 | |
1543 | def delete_port(self, args): |
1544 | - deviceParams = {const.DEVICE_IP: ""} |
1545 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
1546 | + """Support for the Quantum core API call""" |
1547 | + device_params = {const.DEVICE_IP: ""} |
1548 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
1549 | |
1550 | def update_port(self, args): |
1551 | + """Not implemented for this model""" |
1552 | pass |
1553 | |
1554 | def get_port_details(self, args): |
1555 | + """Not implemented for this model""" |
1556 | pass |
1557 | |
1558 | def plug_interface(self, args): |
1559 | - deviceParams = {const.DEVICE_IP: ""} |
1560 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
1561 | + """Support for the Quantum core API call""" |
1562 | + device_params = {const.DEVICE_IP: ""} |
1563 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
1564 | |
1565 | def unplug_interface(self, args): |
1566 | - deviceParams = {const.DEVICE_IP: ""} |
1567 | - self._invokeUCSPlugin(self._funcName(), args, deviceParams) |
1568 | + """Support for the Quantum core API call""" |
1569 | + device_params = {const.DEVICE_IP: ""} |
1570 | + self._invoke_ucs_plugin(self._func_name(), args, device_params) |
1571 | |
1572 | === modified file 'quantum/plugins/cisco/l2network_model_base.py' |
1573 | --- quantum/plugins/cisco/l2network_model_base.py 2011-08-07 11:58:50 +0000 |
1574 | +++ quantum/plugins/cisco/l2network_model_base.py 2011-08-23 20:09:26 +0000 |
1575 | @@ -1,3 +1,4 @@ |
1576 | +""" |
1577 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1578 | # |
1579 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1580 | @@ -16,12 +17,20 @@ |
1581 | # |
1582 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1583 | # |
1584 | +""" |
1585 | |
1586 | import inspect |
1587 | from abc import ABCMeta, abstractmethod |
1588 | |
1589 | |
1590 | class L2NetworkModelBase(object): |
1591 | + """ |
1592 | + Base class for L2 Network Model |
1593 | + It relies on a pluggable network configuration module to gather |
1594 | + knowledge of the system, but knows which device-specific plugins |
1595 | + to invoke for a corresponding core API call, and what parameters to pass |
1596 | + to that plugin. |
1597 | + """ |
1598 | |
1599 | __metaclass__ = ABCMeta |
1600 | |
1601 | @@ -131,7 +140,7 @@ |
1602 | marked with the abstractmethod decorator is |
1603 | provided by the plugin class. |
1604 | """ |
1605 | - if cls is QuantumPluginBase: |
1606 | + if cls is L2NetworkModelBase: |
1607 | for method in cls.__abstractmethods__: |
1608 | method_ok = False |
1609 | for base in klass.__mro__: |
1610 | |
1611 | === modified file 'quantum/plugins/cisco/l2network_plugin.py' |
1612 | --- quantum/plugins/cisco/l2network_plugin.py 2011-08-14 01:28:02 +0000 |
1613 | +++ quantum/plugins/cisco/l2network_plugin.py 2011-08-23 20:09:26 +0000 |
1614 | @@ -1,3 +1,4 @@ |
1615 | +""" |
1616 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
1617 | # |
1618 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
1619 | @@ -16,6 +17,7 @@ |
1620 | # |
1621 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
1622 | # |
1623 | +""" |
1624 | |
1625 | import inspect |
1626 | import logging as LOG |
1627 | @@ -26,22 +28,22 @@ |
1628 | from quantum.plugins.cisco import l2network_plugin_configuration as conf |
1629 | from quantum.plugins.cisco.common import cisco_constants as const |
1630 | from quantum.plugins.cisco.common import cisco_exceptions as cexc |
1631 | +from quantum.plugins.cisco.db import api as db |
1632 | +from quantum.plugins.cisco.db import l2network_db as cdb |
1633 | |
1634 | LOG.basicConfig(level=LOG.WARN) |
1635 | LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
1636 | |
1637 | |
1638 | class L2Network(QuantumPluginBase): |
1639 | - _networks = {} |
1640 | - _tenants = {} |
1641 | - _portprofiles = {} |
1642 | + """ L2 Network Framework Plugin """ |
1643 | |
1644 | def __init__(self): |
1645 | - self._net_counter = 0 |
1646 | - self._portprofile_counter = 0 |
1647 | - self._port_counter = 0 |
1648 | self._vlan_counter = int(conf.VLAN_START) - 1 |
1649 | self._model = utils.import_object(conf.MODEL_CLASS) |
1650 | + cdb.initialize() |
1651 | + # TODO (Sumit): The following should move to the segmentation module |
1652 | + cdb.create_vlanids() |
1653 | |
1654 | """ |
1655 | Core API implementation |
1656 | @@ -53,8 +55,16 @@ |
1657 | the specified tenant. |
1658 | """ |
1659 | LOG.debug("get_all_networks() called\n") |
1660 | - self._invokeDevicePlugins(self._funcName(), [tenant_id]) |
1661 | - return self._networks.values() |
1662 | + self._invoke_device_plugins(self._func_name(), [tenant_id]) |
1663 | + networks_list = db.network_list(tenant_id) |
1664 | + new_networks_list = [] |
1665 | + for network in networks_list: |
1666 | + new_network_dict = self._make_net_dict(network[const.UUID], |
1667 | + network[const.NETWORKNAME], |
1668 | + []) |
1669 | + new_networks_list.append(new_network_dict) |
1670 | + |
1671 | + return new_networks_list |
1672 | |
1673 | def create_network(self, tenant_id, net_name): |
1674 | """ |
1675 | @@ -62,22 +72,17 @@ |
1676 | a symbolic name. |
1677 | """ |
1678 | LOG.debug("create_network() called\n") |
1679 | - new_net_id = self._get_unique_net_id(tenant_id) |
1680 | + new_network = db.network_create(tenant_id, net_name) |
1681 | + new_net_id = new_network[const.UUID] |
1682 | vlan_id = self._get_vlan_for_tenant(tenant_id, net_name) |
1683 | vlan_name = self._get_vlan_name(new_net_id, str(vlan_id)) |
1684 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_name, |
1685 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_name, |
1686 | new_net_id, vlan_name, |
1687 | vlan_id]) |
1688 | + cdb.add_vlan_binding(vlan_id, vlan_name, new_net_id) |
1689 | new_net_dict = {const.NET_ID: new_net_id, |
1690 | const.NET_NAME: net_name, |
1691 | - const.NET_PORTS: {}, |
1692 | - const.NET_VLAN_NAME: vlan_name, |
1693 | - const.NET_VLAN_ID: vlan_id, |
1694 | - const.NET_TENANTS: [tenant_id]} |
1695 | - self._networks[new_net_id] = new_net_dict |
1696 | - tenant = self._get_tenant(tenant_id) |
1697 | - tenant_networks = tenant[const.TENANT_NETWORKS] |
1698 | - tenant_networks[new_net_id] = new_net_dict |
1699 | + const.NET_PORTS: []} |
1700 | return new_net_dict |
1701 | |
1702 | def delete_network(self, tenant_id, net_id): |
1703 | @@ -86,22 +91,24 @@ |
1704 | belonging to the specified tenant. |
1705 | """ |
1706 | LOG.debug("delete_network() called\n") |
1707 | - net = self._networks.get(net_id) |
1708 | + net = db.network_get(net_id) |
1709 | if net: |
1710 | - if len(net[const.NET_PORTS].values()) > 0: |
1711 | - ports_on_net = net[const.NET_PORTS].values() |
1712 | + if len(net[const.NETWORKPORTS]) > 0: |
1713 | + ports_on_net = db.port_list(net_id) |
1714 | for port in ports_on_net: |
1715 | - if port[const.ATTACHMENT]: |
1716 | + if port[const.INTERFACEID]: |
1717 | raise exc.NetworkInUse(net_id=net_id) |
1718 | for port in ports_on_net: |
1719 | - self.delete_port(tenant_id, net_id, port[const.PORT_ID]) |
1720 | + self.delete_port(tenant_id, net_id, port[const.PORTID]) |
1721 | |
1722 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
1723 | - self._networks.pop(net_id) |
1724 | - tenant = self._get_tenant(tenant_id) |
1725 | - tenant_networks = tenant[const.TENANT_NETWORKS] |
1726 | - tenant_networks.pop(net_id) |
1727 | - return net |
1728 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
1729 | + net_dict = self._make_net_dict(net[const.UUID], |
1730 | + net[const.NETWORKNAME], |
1731 | + []) |
1732 | + self._release_vlan_for_tenant(tenant_id, net_id) |
1733 | + cdb.remove_vlan_binding(net_id) |
1734 | + db.network_destroy(net_id) |
1735 | + return net_dict |
1736 | # Network not found |
1737 | raise exc.NetworkNotFound(net_id=net_id) |
1738 | |
1739 | @@ -110,12 +117,22 @@ |
1740 | Gets the details of a particular network |
1741 | """ |
1742 | LOG.debug("get_network_details() called\n") |
1743 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
1744 | - network = self._get_network(tenant_id, net_id) |
1745 | - ports_on_net = network[const.NET_PORTS].values() |
1746 | - return {const.NET_ID: network[const.NET_ID], |
1747 | - const.NET_NAME: network[const.NET_NAME], |
1748 | - const.NET_PORTS: ports_on_net} |
1749 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
1750 | + network = db.network_get(net_id) |
1751 | + ports_list = network[const.NETWORKPORTS] |
1752 | + ports_on_net = [] |
1753 | + for port in ports_list: |
1754 | + new_port = self._make_port_dict(port[const.UUID], |
1755 | + port[const.PORTSTATE], |
1756 | + port[const.NETWORKID], |
1757 | + port[const.INTERFACEID]) |
1758 | + ports_on_net.append(new_port) |
1759 | + |
1760 | + new_network = self._make_net_dict(network[const.UUID], |
1761 | + network[const.NETWORKNAME], |
1762 | + ports_on_net) |
1763 | + |
1764 | + return new_network |
1765 | |
1766 | def rename_network(self, tenant_id, net_id, new_name): |
1767 | """ |
1768 | @@ -123,11 +140,13 @@ |
1769 | Virtual Network. |
1770 | """ |
1771 | LOG.debug("rename_network() called\n") |
1772 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1773 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1774 | new_name]) |
1775 | - network = self._get_network(tenant_id, net_id) |
1776 | - network[const.NET_NAME] = new_name |
1777 | - return network |
1778 | + network = db.network_rename(tenant_id, net_id, new_name) |
1779 | + net_dict = self._make_net_dict(network[const.UUID], |
1780 | + network[const.NETWORKNAME], |
1781 | + []) |
1782 | + return net_dict |
1783 | |
1784 | def get_all_ports(self, tenant_id, net_id): |
1785 | """ |
1786 | @@ -135,9 +154,17 @@ |
1787 | specified Virtual Network. |
1788 | """ |
1789 | LOG.debug("get_all_ports() called\n") |
1790 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id]) |
1791 | - network = self._get_network(tenant_id, net_id) |
1792 | - ports_on_net = network[const.NET_PORTS].values() |
1793 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id]) |
1794 | + network = db.network_get(net_id) |
1795 | + ports_list = network[const.NETWORKPORTS] |
1796 | + ports_on_net = [] |
1797 | + for port in ports_list: |
1798 | + new_port = self._make_port_dict(port[const.UUID], |
1799 | + port[const.PORTSTATE], |
1800 | + port[const.NETWORKID], |
1801 | + port[const.INTERFACEID]) |
1802 | + ports_on_net.append(new_port) |
1803 | + |
1804 | return ports_on_net |
1805 | |
1806 | def create_port(self, tenant_id, net_id, port_state=None): |
1807 | @@ -145,16 +172,15 @@ |
1808 | Creates a port on the specified Virtual Network. |
1809 | """ |
1810 | LOG.debug("create_port() called\n") |
1811 | - net = self._get_network(tenant_id, net_id) |
1812 | - ports = net[const.NET_PORTS] |
1813 | - unique_port_id_string = self._get_unique_port_id(tenant_id, net_id) |
1814 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1815 | + port = db.port_create(net_id, port_state) |
1816 | + unique_port_id_string = port[const.UUID] |
1817 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1818 | port_state, |
1819 | unique_port_id_string]) |
1820 | - new_port_dict = {const.PORT_ID: unique_port_id_string, |
1821 | - const.PORT_STATE: const.PORT_UP, |
1822 | - const.ATTACHMENT: None} |
1823 | - ports[unique_port_id_string] = new_port_dict |
1824 | + new_port_dict = self._make_port_dict(port[const.UUID], |
1825 | + port[const.PORTSTATE], |
1826 | + port[const.NETWORKID], |
1827 | + port[const.INTERFACEID]) |
1828 | return new_port_dict |
1829 | |
1830 | def delete_port(self, tenant_id, net_id, port_id): |
1831 | @@ -165,31 +191,24 @@ |
1832 | then the port can be deleted. |
1833 | """ |
1834 | LOG.debug("delete_port() called\n") |
1835 | - port = self._get_port(tenant_id, net_id, port_id) |
1836 | - if port[const.ATTACHMENT]: |
1837 | - raise exc.PortInUse(net_id=net_id, port_id=port_id, |
1838 | - att_id=port[const.ATTACHMENT]) |
1839 | - try: |
1840 | - #TODO (Sumit): Before deleting port profile make sure that there |
1841 | - # is no VM using this port profile |
1842 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1843 | - port_id]) |
1844 | - net = self._get_network(tenant_id, net_id) |
1845 | - net[const.NET_PORTS].pop(port_id) |
1846 | - except KeyError: |
1847 | - raise exc.PortNotFound(net_id=net_id, port_id=port_id) |
1848 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1849 | + port_id]) |
1850 | + db.port_destroy(net_id, port_id) |
1851 | + new_port_dict = self._make_port_dict(port_id, None, None, None) |
1852 | + return new_port_dict |
1853 | |
1854 | def update_port(self, tenant_id, net_id, port_id, port_state): |
1855 | """ |
1856 | Updates the state of a port on the specified Virtual Network. |
1857 | """ |
1858 | LOG.debug("update_port() called\n") |
1859 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1860 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1861 | port_id, port_state]) |
1862 | - port = self._get_port(tenant_id, net_id, port_id) |
1863 | self._validate_port_state(port_state) |
1864 | - port[const.PORT_STATE] = port_state |
1865 | - return port |
1866 | + db.port_set_state(net_id, port_id, port_state) |
1867 | + new_port_dict = self._make_port_dict(port_id, port_state, net_id, |
1868 | + None) |
1869 | + return new_port_dict |
1870 | |
1871 | def get_port_details(self, tenant_id, net_id, port_id): |
1872 | """ |
1873 | @@ -197,9 +216,14 @@ |
1874 | that is attached to this particular port. |
1875 | """ |
1876 | LOG.debug("get_port_details() called\n") |
1877 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1878 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1879 | port_id]) |
1880 | - return self._get_port(tenant_id, net_id, port_id) |
1881 | + port = db.port_get(net_id, port_id) |
1882 | + new_port_dict = self._make_port_dict(port[const.UUID], |
1883 | + port[const.PORTSTATE], |
1884 | + port[const.NETWORKID], |
1885 | + port[const.INTERFACEID]) |
1886 | + return new_port_dict |
1887 | |
1888 | def plug_interface(self, tenant_id, net_id, port_id, |
1889 | remote_interface_id): |
1890 | @@ -208,16 +232,10 @@ |
1891 | specified Virtual Network. |
1892 | """ |
1893 | LOG.debug("plug_interface() called\n") |
1894 | - self._validate_attachment(tenant_id, net_id, port_id, |
1895 | - remote_interface_id) |
1896 | - port = self._get_port(tenant_id, net_id, port_id) |
1897 | - if port[const.ATTACHMENT]: |
1898 | - raise exc.PortInUse(net_id=net_id, port_id=port_id, |
1899 | - att_id=port[const.ATTACHMENT]) |
1900 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1901 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1902 | port_id, |
1903 | remote_interface_id]) |
1904 | - port[const.ATTACHMENT] = remote_interface_id |
1905 | + db.port_set_attachment(net_id, port_id, remote_interface_id) |
1906 | |
1907 | def unplug_interface(self, tenant_id, net_id, port_id): |
1908 | """ |
1909 | @@ -225,170 +243,165 @@ |
1910 | specified Virtual Network. |
1911 | """ |
1912 | LOG.debug("unplug_interface() called\n") |
1913 | - port = self._get_port(tenant_id, net_id, port_id) |
1914 | - self._invokeDevicePlugins(self._funcName(), [tenant_id, net_id, |
1915 | + self._invoke_device_plugins(self._func_name(), [tenant_id, net_id, |
1916 | port_id]) |
1917 | - port[const.ATTACHMENT] = None |
1918 | + db.port_unset_attachment(net_id, port_id) |
1919 | |
1920 | """ |
1921 | Extension API implementation |
1922 | """ |
1923 | def get_all_portprofiles(self, tenant_id): |
1924 | - return self._portprofiles.values() |
1925 | + """Get all port profiles""" |
1926 | + pplist = cdb.get_all_portprofiles() |
1927 | + new_pplist = [] |
1928 | + for portprofile in pplist: |
1929 | + new_pp = self._make_portprofile_dict(tenant_id, |
1930 | + portprofile[const.UUID], |
1931 | + portprofile[const.PPNAME], |
1932 | + portprofile[const.PPQOS]) |
1933 | + new_pplist.append(new_pp) |
1934 | + |
1935 | + return new_pplist |
1936 | |
1937 | def get_portprofile_details(self, tenant_id, profile_id): |
1938 | - return self._get_portprofile(tenant_id, profile_id) |
1939 | + """Get port profile details""" |
1940 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
1941 | + new_pp = self._make_portprofile_dict(tenant_id, |
1942 | + portprofile[const.UUID], |
1943 | + portprofile[const.PPNAME], |
1944 | + portprofile[const.PPQOS]) |
1945 | + return new_pp |
1946 | |
1947 | - def create_portprofile(self, tenant_id, profile_name, vlan_id): |
1948 | - profile_id = self._get_unique_profile_id(tenant_id) |
1949 | - new_port_profile_dict = {const.PROFILE_ID: profile_id, |
1950 | - const.PROFILE_NAME: profile_name, |
1951 | - const.PROFILE_ASSOCIATIONS: [], |
1952 | - const.PROFILE_VLAN_ID: vlan_id, |
1953 | - const.PROFILE_QOS: None} |
1954 | - self._portprofiles[profile_id] = new_port_profile_dict |
1955 | - tenant = self._get_tenant(tenant_id) |
1956 | - portprofiles = tenant[const.TENANT_PORTPROFILES] |
1957 | - portprofiles[profile_id] = new_port_profile_dict |
1958 | - return new_port_profile_dict |
1959 | + def create_portprofile(self, tenant_id, profile_name, qos): |
1960 | + """Create port profile""" |
1961 | + portprofile = cdb.add_portprofile(tenant_id, profile_name, |
1962 | + const.NO_VLAN_ID, qos) |
1963 | + new_pp = self._make_portprofile_dict(tenant_id, |
1964 | + portprofile[const.UUID], |
1965 | + portprofile[const.PPNAME], |
1966 | + portprofile[const.PPQOS]) |
1967 | + return new_pp |
1968 | |
1969 | def delete_portprofile(self, tenant_id, profile_id): |
1970 | - portprofile = self._get_portprofile(tenant_id, profile_id) |
1971 | - associations = portprofile[const.PROFILE_ASSOCIATIONS] |
1972 | - if len(associations) > 0: |
1973 | + """Delete portprofile""" |
1974 | + try: |
1975 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
1976 | + except Exception, exc: |
1977 | + raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
1978 | + portprofile_id=profile_id) |
1979 | + |
1980 | + plist = cdb.get_pp_binding(tenant_id, profile_id) |
1981 | + if plist: |
1982 | raise cexc.PortProfileInvalidDelete(tenant_id=tenant_id, |
1983 | - profile_id=profile_id) |
1984 | + profile_id=profile_id) |
1985 | else: |
1986 | - self._portprofiles.pop(profile_id) |
1987 | - tenant = self._get_tenant(tenant_id) |
1988 | - tenant[const.TENANT_PORTPROFILES].pop(profile_id) |
1989 | + cdb.remove_portprofile(tenant_id, profile_id) |
1990 | |
1991 | def rename_portprofile(self, tenant_id, profile_id, new_name): |
1992 | - portprofile = self._get_portprofile(tenant_id, profile_id) |
1993 | - portprofile[const.PROFILE_NAME] = new_name |
1994 | - return portprofile |
1995 | + """Rename port profile""" |
1996 | + try: |
1997 | + portprofile = cdb.get_portprofile(tenant_id, profile_id) |
1998 | + except Exception, exc: |
1999 | + raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
2000 | + portprofile_id=profile_id) |
2001 | + portprofile = cdb.update_portprofile(tenant_id, profile_id, new_name) |
2002 | + new_pp = self._make_portprofile_dict(tenant_id, |
2003 | + portprofile[const.UUID], |
2004 | + portprofile[const.PPNAME], |
2005 | + portprofile[const.PPQOS]) |
2006 | + return new_pp |
2007 | |
2008 | def associate_portprofile(self, tenant_id, net_id, |
2009 | port_id, portprofile_id): |
2010 | - portprofile = self._get_portprofile(tenant_id, portprofile_id) |
2011 | - associations = portprofile[const.PROFILE_ASSOCIATIONS] |
2012 | - associations.append(port_id) |
2013 | + """Associate port profile""" |
2014 | + try: |
2015 | + portprofile = cdb.get_portprofile(tenant_id, portprofile_id) |
2016 | + except Exception, exc: |
2017 | + raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
2018 | + portprofile_id=portprofile_id) |
2019 | + |
2020 | + cdb.add_pp_binding(tenant_id, port_id, portprofile_id, False) |
2021 | |
2022 | def disassociate_portprofile(self, tenant_id, net_id, |
2023 | port_id, portprofile_id): |
2024 | - portprofile = self._get_portprofile(tenant_id, portprofile_id) |
2025 | - associations = portprofile[const.PROFILE_ASSOCIATIONS] |
2026 | - associations.remove(port_id) |
2027 | + """Disassociate port profile""" |
2028 | + try: |
2029 | + portprofile = cdb.get_portprofile(tenant_id, portprofile_id) |
2030 | + except Exception, exc: |
2031 | + raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
2032 | + portprofile_id=portprofile_id) |
2033 | |
2034 | - def create_defaultPProfile(self, tenant_id, network_id, profile_name, |
2035 | - vlan_id): |
2036 | - pass |
2037 | + cdb.remove_pp_binding(tenant_id, port_id, portprofile_id) |
2038 | |
2039 | """ |
2040 | Private functions |
2041 | """ |
2042 | - def _invokeDevicePlugins(self, function_name, args): |
2043 | + def _invoke_device_plugins(self, function_name, args): |
2044 | """ |
2045 | All device-specific calls are delegate to the model |
2046 | """ |
2047 | getattr(self._model, function_name)(args) |
2048 | |
2049 | def _get_vlan_for_tenant(self, tenant_id, net_name): |
2050 | + """Get vlan ID""" |
2051 | # TODO (Sumit): |
2052 | # The VLAN ID for a tenant might need to be obtained from |
2053 | # somewhere (from Donabe/Melange?) |
2054 | # Also need to make sure that the VLAN ID is not being used already |
2055 | # Currently, just a wrap-around counter ranging from VLAN_START to |
2056 | # VLAN_END |
2057 | - self._vlan_counter += 1 |
2058 | - self._vlan_counter %= int(conf.VLAN_END) |
2059 | - if self._vlan_counter < int(conf.VLAN_START): |
2060 | - self._vlan_counter = int(conf.VLAN_START) |
2061 | - return self._vlan_counter |
2062 | + return cdb.reserve_vlanid() |
2063 | + |
2064 | + def _release_vlan_for_tenant(self, tenant_id, net_id): |
2065 | + """Relase VLAN""" |
2066 | + vlan_binding = cdb.get_vlan_binding(net_id) |
2067 | + return cdb.release_vlanid(vlan_binding[const.VLANID]) |
2068 | |
2069 | def _get_vlan_name(self, net_id, vlan): |
2070 | - vlan_name = conf.VLAN_NAME_PREFIX + net_id + "-" + vlan |
2071 | + """Getting the vlan name from the tenant and vlan""" |
2072 | + vlan_name = conf.VLAN_NAME_PREFIX + vlan |
2073 | return vlan_name |
2074 | |
2075 | def _validate_port_state(self, port_state): |
2076 | + """Checking the port state""" |
2077 | if port_state.upper() not in (const.PORT_UP, const.PORT_DOWN): |
2078 | raise exc.StateInvalid(port_state=port_state) |
2079 | return True |
2080 | |
2081 | - def _validate_attachment(self, tenant_id, network_id, port_id, |
2082 | - remote_interface_id): |
2083 | - network = self._get_network(tenant_id, network_id) |
2084 | - for port in network[const.NET_PORTS].values(): |
2085 | - if port[const.ATTACHMENT] == remote_interface_id: |
2086 | - raise exc.AlreadyAttached(net_id=network_id, |
2087 | - port_id=port_id, |
2088 | - att_id=port[const.ATTACHMENT], |
2089 | - att_port_id=port[const.PORT_ID]) |
2090 | - |
2091 | - def _get_network(self, tenant_id, network_id): |
2092 | - network = self._networks.get(network_id) |
2093 | - if not network: |
2094 | - raise exc.NetworkNotFound(net_id=network_id) |
2095 | - return network |
2096 | - |
2097 | - def _get_tenant(self, tenant_id): |
2098 | - tenant = self._tenants.get(tenant_id) |
2099 | - if not tenant: |
2100 | - LOG.debug("Creating new tenant record with tenant id %s\n" % |
2101 | - tenant_id) |
2102 | - tenant = {const.TENANT_ID: tenant_id, |
2103 | - const.TENANT_NAME: tenant_id, |
2104 | - const.TENANT_NETWORKS: {}, |
2105 | - const.TENANT_PORTPROFILES: {}} |
2106 | - self._tenants[tenant_id] = tenant |
2107 | - return tenant |
2108 | - |
2109 | - def _get_port(self, tenant_id, network_id, port_id): |
2110 | - net = self._get_network(tenant_id, network_id) |
2111 | - port = net[const.NET_PORTS].get(port_id) |
2112 | - if not port: |
2113 | - raise exc.PortNotFound(net_id=network_id, port_id=port_id) |
2114 | - return port |
2115 | - |
2116 | - def _get_portprofile(self, tenant_id, portprofile_id): |
2117 | - portprofile = self._portprofiles.get(portprofile_id) |
2118 | - if not portprofile: |
2119 | - raise cexc.PortProfileNotFound(tenant_id=tenant_id, |
2120 | - portprofile_id=portprofile_id) |
2121 | - return portprofile |
2122 | - |
2123 | - def _get_unique_net_id(self, tenant_id): |
2124 | - self._net_counter += 1 |
2125 | - self._net_counter %= int(conf.MAX_NETWORKS) |
2126 | - id = tenant_id[:3] + \ |
2127 | - "-n-" + ("0" * (6 - len(str(self._net_counter)))) + \ |
2128 | - str(self._net_counter) |
2129 | - # TODO (Sumit): Need to check if the ID has already been allocated |
2130 | - # ID will be generated by DB |
2131 | - return id |
2132 | - |
2133 | - def _get_unique_port_id(self, tenant_id, net_id): |
2134 | - self._port_counter += 1 |
2135 | - self._port_counter %= int(conf.MAX_PORTS) |
2136 | - id = net_id + "-p-" + str(self._port_counter) |
2137 | - # TODO (Sumit): Need to check if the ID has already been allocated |
2138 | - # ID will be generated by DB |
2139 | - return id |
2140 | - |
2141 | - def _get_unique_profile_id(self, tenant_id): |
2142 | - self._portprofile_counter += 1 |
2143 | - self._portprofile_counter %= int(conf.MAX_PORT_PROFILES) |
2144 | - id = tenant_id[:3] + "-pp-" + \ |
2145 | - ("0" * (6 - len(str(self._net_counter)))) \ |
2146 | - + str(self._portprofile_counter) |
2147 | - # TODO (Sumit): Need to check if the ID has already been allocated |
2148 | - # ID will be generated by DB |
2149 | - return id |
2150 | - |
2151 | - def _funcName(self, offset=0): |
2152 | + def _func_name(self, offset=0): |
2153 | + """Getting the name of the calling funciton""" |
2154 | return inspect.stack()[1 + offset][3] |
2155 | |
2156 | -""" |
2157 | -TODO (Sumit): |
2158 | -(1) Persistent storage |
2159 | -""" |
2160 | + def _make_net_dict(self, net_id, net_name, ports): |
2161 | + """Helper funciton""" |
2162 | + res = {const.NET_ID: net_id, const.NET_NAME: net_name} |
2163 | + res[const.NET_PORTS] = ports |
2164 | + return res |
2165 | + |
2166 | + def _make_port_dict(self, port_id, port_state, net_id, attachment): |
2167 | + """Helper funciton""" |
2168 | + res = {const.PORT_ID: port_id, const.PORT_STATE: port_state} |
2169 | + res[const.NET_ID] = net_id |
2170 | + res[const.ATTACHMENT] = attachment |
2171 | + return res |
2172 | + |
2173 | + def _make_portprofile_dict(self, tenant_id, profile_id, profile_name, |
2174 | + qos): |
2175 | + """Helper funciton""" |
2176 | + profile_associations = self._make_portprofile_assc_list(tenant_id, |
2177 | + profile_id) |
2178 | + res = {const.PROFILE_ID: str(profile_id), |
2179 | + const.PROFILE_NAME: profile_name, |
2180 | + const.PROFILE_ASSOCIATIONS: profile_associations, |
2181 | + const.PROFILE_VLAN_ID: None, |
2182 | + const.PROFILE_QOS: qos} |
2183 | + return res |
2184 | + |
2185 | + def _make_portprofile_assc_list(self, tenant_id, profile_id): |
2186 | + """Helper function to create port profile association list""" |
2187 | + plist = cdb.get_pp_binding(tenant_id, profile_id) |
2188 | + assc_list = [] |
2189 | + for port in plist: |
2190 | + assc_list.append(port[const.PORTID]) |
2191 | + |
2192 | + return assc_list |
2193 | |
2194 | === modified file 'quantum/plugins/cisco/l2network_plugin_configuration.py' |
2195 | --- quantum/plugins/cisco/l2network_plugin_configuration.py 2011-08-14 01:28:02 +0000 |
2196 | +++ quantum/plugins/cisco/l2network_plugin_configuration.py 2011-08-23 20:09:26 +0000 |
2197 | @@ -1,3 +1,4 @@ |
2198 | +""" |
2199 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2200 | # |
2201 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
2202 | @@ -15,7 +16,8 @@ |
2203 | # under the License. |
2204 | # |
2205 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
2206 | -# |
2207 | +# @author: Rohit Agarwalla, Cisco Systems, Inc. |
2208 | +""" |
2209 | |
2210 | import os |
2211 | |
2212 | @@ -23,28 +25,43 @@ |
2213 | |
2214 | CONF_FILE = "conf/l2network_plugin.ini" |
2215 | |
2216 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
2217 | - + "/" + CONF_FILE) |
2218 | - |
2219 | -section = cp['VLANS'] |
2220 | -VLAN_NAME_PREFIX = section['vlan_name_prefix'] |
2221 | -VLAN_START = section['vlan_start'] |
2222 | -VLAN_END = section['vlan_end'] |
2223 | - |
2224 | -section = cp['PORTS'] |
2225 | -MAX_PORTS = section['max_ports'] |
2226 | - |
2227 | -section = cp['PORTPROFILES'] |
2228 | -MAX_PORT_PROFILES = section['max_port_profiles'] |
2229 | - |
2230 | -section = cp['NETWORKS'] |
2231 | -MAX_NETWORKS = section['max_networks'] |
2232 | - |
2233 | -section = cp['MODEL'] |
2234 | -MODEL_CLASS = section['model_class'] |
2235 | +CONF_PARSER_OBJ = confp.\ |
2236 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
2237 | +"/" + CONF_FILE) |
2238 | + |
2239 | +SECTION_CONF = CONF_PARSER_OBJ['VLANS'] |
2240 | +VLAN_NAME_PREFIX = SECTION_CONF['vlan_name_prefix'] |
2241 | +VLAN_START = SECTION_CONF['vlan_start'] |
2242 | +VLAN_END = SECTION_CONF['vlan_end'] |
2243 | + |
2244 | +SECTION_CONF = CONF_PARSER_OBJ['PORTS'] |
2245 | +MAX_PORTS = SECTION_CONF['max_ports'] |
2246 | + |
2247 | +SECTION_CONF = CONF_PARSER_OBJ['PORTPROFILES'] |
2248 | +MAX_PORT_PROFILES = SECTION_CONF['max_port_profiles'] |
2249 | + |
2250 | +SECTION_CONF = CONF_PARSER_OBJ['NETWORKS'] |
2251 | +MAX_NETWORKS = SECTION_CONF['max_networks'] |
2252 | + |
2253 | +SECTION_CONF = CONF_PARSER_OBJ['MODEL'] |
2254 | +MODEL_CLASS = SECTION_CONF['model_class'] |
2255 | |
2256 | CONF_FILE = "conf/plugins.ini" |
2257 | |
2258 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
2259 | - + "/" + CONF_FILE) |
2260 | -plugins = cp.walk(cp.dummy) |
2261 | +CONF_PARSER_OBJ = confp.\ |
2262 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
2263 | +"/" + CONF_FILE) |
2264 | + |
2265 | +PLUGINS = CONF_PARSER_OBJ.walk(CONF_PARSER_OBJ.dummy) |
2266 | + |
2267 | +CONF_FILE = "conf/db_conn.ini" |
2268 | + |
2269 | +CONF_PARSER_OBJ = confp.\ |
2270 | +CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) + \ |
2271 | +"/" + CONF_FILE) |
2272 | + |
2273 | +SECTION_CONF = CONF_PARSER_OBJ['DATABASE'] |
2274 | +DB_NAME = SECTION_CONF['name'] |
2275 | +DB_USER = SECTION_CONF['user'] |
2276 | +DB_PASS = SECTION_CONF['pass'] |
2277 | +DB_HOST = SECTION_CONF['host'] |
2278 | |
2279 | === modified file 'quantum/plugins/cisco/nexus/__init__.py' |
2280 | --- quantum/plugins/cisco/nexus/__init__.py 2011-07-31 19:04:01 +0000 |
2281 | +++ quantum/plugins/cisco/nexus/__init__.py 2011-08-23 20:09:26 +0000 |
2282 | @@ -15,4 +15,7 @@ |
2283 | # under the License. |
2284 | # |
2285 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
2286 | -# |
2287 | +# @author: Edgar Magana, Cisco Systems, Inc. |
2288 | +""" |
2289 | +Init module for Nexus Driver |
2290 | +""" |
2291 | |
2292 | === modified file 'quantum/plugins/cisco/nexus/cisco_nexus_configuration.py' |
2293 | --- quantum/plugins/cisco/nexus/cisco_nexus_configuration.py 2011-08-14 01:28:02 +0000 |
2294 | +++ quantum/plugins/cisco/nexus/cisco_nexus_configuration.py 2011-08-23 20:09:26 +0000 |
2295 | @@ -17,19 +17,24 @@ |
2296 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
2297 | # @author: Edgar Magana, Cisco Systems, Inc. |
2298 | # |
2299 | - |
2300 | +""" |
2301 | +Configuration consolidation for the Nexus Driver |
2302 | +This module will export the configuration parameters |
2303 | +from the nexus.ini file |
2304 | +""" |
2305 | import os |
2306 | |
2307 | from quantum.plugins.cisco.common import cisco_configparser as confp |
2308 | |
2309 | CONF_FILE = "../conf/nexus.ini" |
2310 | |
2311 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
2312 | +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
2313 | + "/" + CONF_FILE) |
2314 | |
2315 | -section = cp['SWITCH'] |
2316 | -NEXUS_IP_ADDRESS = section['nexus_ip_address'] |
2317 | -NEXUS_PORT = section['nexus_port'] |
2318 | +SECTION = CP['SWITCH'] |
2319 | +NEXUS_IP_ADDRESS = SECTION['nexus_ip_address'] |
2320 | +NEXUS_PORT = SECTION['nexus_port'] |
2321 | +NEXUS_SSH_PORT = SECTION['nexus_ssh_port'] |
2322 | |
2323 | -section = cp['DRIVER'] |
2324 | -NEXUS_DRIVER = section['name'] |
2325 | +SECTION = CP['DRIVER'] |
2326 | +NEXUS_DRIVER = SECTION['name'] |
2327 | |
2328 | === modified file 'quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py' |
2329 | --- quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py 2011-08-15 16:02:24 +0000 |
2330 | +++ quantum/plugins/cisco/nexus/cisco_nexus_network_driver.py 2011-08-23 20:09:26 +0000 |
2331 | @@ -22,11 +22,9 @@ |
2332 | """ |
2333 | |
2334 | import logging as LOG |
2335 | -import string |
2336 | -import subprocess |
2337 | |
2338 | from quantum.plugins.cisco.common import cisco_constants as const |
2339 | -from quantum.plugins.cisco.common import cisco_exceptions as cexc |
2340 | +from quantum.plugins.cisco.nexus import cisco_nexus_snippets as snipp |
2341 | |
2342 | from ncclient import manager |
2343 | |
2344 | @@ -34,193 +32,101 @@ |
2345 | LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
2346 | |
2347 | |
2348 | -# The following are standard strings, messages used to communicate with Nexus, |
2349 | -#only place holder values change for each message |
2350 | -exec_conf_prefix = """ |
2351 | - <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> |
2352 | - <configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> |
2353 | - <__XML__MODE__exec_configure> |
2354 | -""" |
2355 | - |
2356 | - |
2357 | -exec_conf_postfix = """ |
2358 | - </__XML__MODE__exec_configure> |
2359 | - </configure> |
2360 | - </config> |
2361 | -""" |
2362 | - |
2363 | - |
2364 | -cmd_vlan_conf_snippet = """ |
2365 | - <vlan> |
2366 | - <vlan-id-create-delete> |
2367 | - <__XML__PARAM_value>%s</__XML__PARAM_value> |
2368 | - <__XML__MODE_vlan> |
2369 | - <name> |
2370 | - <vlan-name>%s</vlan-name> |
2371 | - </name> |
2372 | - <state> |
2373 | - <vstate>active</vstate> |
2374 | - </state> |
2375 | - <no> |
2376 | - <shutdown/> |
2377 | - </no> |
2378 | - </__XML__MODE_vlan> |
2379 | - </vlan-id-create-delete> |
2380 | - </vlan> |
2381 | -""" |
2382 | - |
2383 | -cmd_no_vlan_conf_snippet = """ |
2384 | - <no> |
2385 | - <vlan> |
2386 | - <vlan-id-create-delete> |
2387 | - <__XML__PARAM_value>%s</__XML__PARAM_value> |
2388 | - </vlan-id-create-delete> |
2389 | - </vlan> |
2390 | - </no> |
2391 | -""" |
2392 | - |
2393 | -cmd_vlan_int_snippet = """ |
2394 | - <interface> |
2395 | - <ethernet> |
2396 | - <interface>%s</interface> |
2397 | - <__XML__MODE_if-ethernet-switch> |
2398 | - <switchport></switchport> |
2399 | - <switchport> |
2400 | - <trunk> |
2401 | - <allowed> |
2402 | - <vlan> |
2403 | - <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2404 | - <allow-vlans>%s</allow-vlans> |
2405 | - </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2406 | - </vlan> |
2407 | - </allowed> |
2408 | - </trunk> |
2409 | - </switchport> |
2410 | - </__XML__MODE_if-ethernet-switch> |
2411 | - </ethernet> |
2412 | - </interface> |
2413 | -""" |
2414 | - |
2415 | -cmd_port_trunk = """ |
2416 | - <interface> |
2417 | - <ethernet> |
2418 | - <interface>%s</interface> |
2419 | - <__XML__MODE_if-ethernet-switch> |
2420 | - <switchport></switchport> |
2421 | - <switchport> |
2422 | - <mode> |
2423 | - <trunk> |
2424 | - </trunk> |
2425 | - </mode> |
2426 | - </switchport> |
2427 | - </__XML__MODE_if-ethernet-switch> |
2428 | - </ethernet> |
2429 | - </interface> |
2430 | -""" |
2431 | - |
2432 | -cmd_no_switchport = """ |
2433 | - <interface> |
2434 | - <ethernet> |
2435 | - <interface>%s</interface> |
2436 | - <__XML__MODE_if-ethernet-switch> |
2437 | - <no> |
2438 | - <switchport> |
2439 | - </switchport> |
2440 | - </no> |
2441 | - </__XML__MODE_if-ethernet-switch> |
2442 | - </ethernet> |
2443 | - </interface> |
2444 | -""" |
2445 | - |
2446 | - |
2447 | -cmd_no_vlan_int_snippet = """ |
2448 | - <interface> |
2449 | - <ethernet> |
2450 | - <interface>%s</interface> |
2451 | - <__XML__MODE_if-ethernet-switch> |
2452 | - <switchport></switchport> |
2453 | - <no> |
2454 | - <switchport> |
2455 | - <trunk> |
2456 | - <allowed> |
2457 | - <vlan> |
2458 | - <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2459 | - <allow-vlans>%s</allow-vlans> |
2460 | - </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2461 | - </vlan> |
2462 | - </allowed> |
2463 | - </trunk> |
2464 | - </switchport> |
2465 | - </no> |
2466 | - </__XML__MODE_if-ethernet-switch> |
2467 | - </ethernet> |
2468 | - </interface> |
2469 | -""" |
2470 | - |
2471 | - |
2472 | -filter_show_vlan_brief_snippet = """ |
2473 | - <show xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> |
2474 | - <vlan> |
2475 | - <brief/> |
2476 | - </vlan> |
2477 | - </show> """ |
2478 | - |
2479 | - |
2480 | class CiscoNEXUSDriver(): |
2481 | - |
2482 | + """ |
2483 | + Nexus Driver Main Class |
2484 | + """ |
2485 | def __init__(self): |
2486 | pass |
2487 | |
2488 | - def nxos_connect(self, nexus_host, port, nexus_user, nexus_password): |
2489 | - m = manager.connect(host=nexus_host, port=22, username=nexus_user, |
2490 | - password=nexus_password) |
2491 | - return m |
2492 | + def nxos_connect(self, nexus_host, nexus_ssh_port, nexus_user, |
2493 | + nexus_password): |
2494 | + """ |
2495 | + Makes the SSH connection to the Nexus Switch |
2496 | + """ |
2497 | + man = manager.connect(host=nexus_host, port=nexus_ssh_port, |
2498 | + username=nexus_user, password=nexus_password) |
2499 | + return man |
2500 | + |
2501 | + def create_xml_snippet(self, cutomized_config): |
2502 | + """ |
2503 | + Creates the Proper XML structure for the Nexus Switch Configuration |
2504 | + """ |
2505 | + conf_xml_snippet = snipp.EXEC_CONF_SNIPPET % (cutomized_config) |
2506 | + return conf_xml_snippet |
2507 | |
2508 | def enable_vlan(self, mgr, vlanid, vlanname): |
2509 | - confstr = cmd_vlan_conf_snippet % (vlanid, vlanname) |
2510 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2511 | + """ |
2512 | + Creates a VLAN on Nexus Switch given the VLAN ID and Name |
2513 | + """ |
2514 | + confstr = snipp.CMD_VLAN_CONF_SNIPPET % (vlanid, vlanname) |
2515 | + confstr = self.create_xml_snippet(confstr) |
2516 | mgr.edit_config(target='running', config=confstr) |
2517 | |
2518 | def disable_vlan(self, mgr, vlanid): |
2519 | - confstr = cmd_no_vlan_conf_snippet % vlanid |
2520 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2521 | + """ |
2522 | + Delete a VLAN on Nexus Switch given the VLAN ID |
2523 | + """ |
2524 | + confstr = snipp.CMD_NO_VLAN_CONF_SNIPPET % vlanid |
2525 | + confstr = self.create_xml_snippet(confstr) |
2526 | mgr.edit_config(target='running', config=confstr) |
2527 | |
2528 | def enable_port_trunk(self, mgr, interface): |
2529 | - confstr = cmd_port_trunk % (interface) |
2530 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2531 | - print confstr |
2532 | + """ |
2533 | + Enables trunk mode an interface on Nexus Switch |
2534 | + """ |
2535 | + confstr = snipp.CMD_PORT_TRUNK % (interface) |
2536 | + confstr = self.create_xml_snippet(confstr) |
2537 | + LOG.debug("NexusDriver: %s" % confstr) |
2538 | mgr.edit_config(target='running', config=confstr) |
2539 | |
2540 | def disable_switch_port(self, mgr, interface): |
2541 | - confstr = cmd_no_switchport % (interface) |
2542 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2543 | - print confstr |
2544 | + """ |
2545 | + Disables trunk mode an interface on Nexus Switch |
2546 | + """ |
2547 | + confstr = snipp.CMD_NO_SWITCHPORT % (interface) |
2548 | + confstr = self.create_xml_snippet(confstr) |
2549 | + LOG.debug("NexusDriver: %s" % confstr) |
2550 | mgr.edit_config(target='running', config=confstr) |
2551 | |
2552 | def enable_vlan_on_trunk_int(self, mgr, interface, vlanid): |
2553 | - confstr = cmd_vlan_int_snippet % (interface, vlanid) |
2554 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2555 | - print confstr |
2556 | + """ |
2557 | + Enables trunk mode vlan access an interface on Nexus Switch given |
2558 | + VLANID |
2559 | + """ |
2560 | + confstr = snipp.CMD_VLAN_INT_SNIPPET % (interface, vlanid) |
2561 | + confstr = self.create_xml_snippet(confstr) |
2562 | + LOG.debug("NexusDriver: %s" % confstr) |
2563 | mgr.edit_config(target='running', config=confstr) |
2564 | |
2565 | def disable_vlan_on_trunk_int(self, mgr, interface, vlanid): |
2566 | - confstr = cmd_no_vlan_int_snippet % (interface, vlanid) |
2567 | - confstr = exec_conf_prefix + confstr + exec_conf_postfix |
2568 | - print confstr |
2569 | + """ |
2570 | + Enables trunk mode vlan access an interface on Nexus Switch given |
2571 | + VLANID |
2572 | + """ |
2573 | + confstr = snipp.CMD_NO_VLAN_INT_SNIPPET % (interface, vlanid) |
2574 | + confstr = self.create_xml_snippet(confstr) |
2575 | + LOG.debug("NexusDriver: %s" % confstr) |
2576 | mgr.edit_config(target='running', config=confstr) |
2577 | |
2578 | def create_vlan(self, vlan_name, vlan_id, nexus_host, nexus_user, |
2579 | - nexus_password, nexus_interface): |
2580 | - #TODO (Edgar) Move the SSH port to the configuration file |
2581 | - with self.nxos_connect(nexus_host, 22, nexus_user, |
2582 | - nexus_password) as m: |
2583 | - self.enable_vlan(m, vlan_id, vlan_name) |
2584 | - self.enable_vlan_on_trunk_int(m, nexus_interface, vlan_id) |
2585 | + nexus_password, nexus_interface, nexus_ssh_port): |
2586 | + """ |
2587 | + Creates a VLAN and Enable on trunk mode an interface on Nexus Switch |
2588 | + given the VLAN ID and Name and Interface Number |
2589 | + """ |
2590 | + with self.nxos_connect(nexus_host, int(nexus_ssh_port), nexus_user, |
2591 | + nexus_password) as man: |
2592 | + self.enable_vlan(man, vlan_id, vlan_name) |
2593 | + self.enable_vlan_on_trunk_int(man, nexus_interface, vlan_id) |
2594 | |
2595 | def delete_vlan(self, vlan_id, nexus_host, nexus_user, |
2596 | - nexus_password, nexus_interface): |
2597 | - with self.nxos_connect(nexus_host, 22, nexus_user, |
2598 | - nexus_password) as m: |
2599 | - self.disable_vlan(m, vlan_id) |
2600 | - self.disable_switch_port(m, nexus_interface) |
2601 | + nexus_password, nexus_interface, nexus_ssh_port): |
2602 | + """ |
2603 | + Delete a VLAN and Disables trunk mode an interface on Nexus Switch |
2604 | + given the VLAN ID and Interface Number |
2605 | + """ |
2606 | + with self.nxos_connect(nexus_host, int(nexus_ssh_port), nexus_user, |
2607 | + nexus_password) as man: |
2608 | + self.disable_vlan(man, vlan_id) |
2609 | + self.disable_switch_port(man, nexus_interface) |
2610 | |
2611 | === modified file 'quantum/plugins/cisco/nexus/cisco_nexus_plugin.py' |
2612 | --- quantum/plugins/cisco/nexus/cisco_nexus_plugin.py 2011-08-07 11:58:50 +0000 |
2613 | +++ quantum/plugins/cisco/nexus/cisco_nexus_plugin.py 2011-08-23 20:09:26 +0000 |
2614 | @@ -17,14 +17,15 @@ |
2615 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
2616 | # @author: Edgar Magana, Cisco Systems, Inc. |
2617 | # |
2618 | +""" |
2619 | +PlugIn for Nexus OS driver |
2620 | +""" |
2621 | import logging as LOG |
2622 | |
2623 | from quantum.common import exceptions as exc |
2624 | from quantum.common import utils |
2625 | from quantum.plugins.cisco.common import cisco_constants as const |
2626 | from quantum.plugins.cisco.common import cisco_credentials as cred |
2627 | -from quantum.plugins.cisco.common import cisco_exceptions as cexc |
2628 | -from quantum.plugins.cisco.common import cisco_utils as cutil |
2629 | from quantum.plugins.cisco.l2device_plugin_base import L2DevicePluginBase |
2630 | from quantum.plugins.cisco.nexus import cisco_nexus_configuration as conf |
2631 | |
2632 | @@ -33,16 +34,22 @@ |
2633 | |
2634 | |
2635 | class NexusPlugin(L2DevicePluginBase): |
2636 | + """ |
2637 | + Nexus PLugIn Main Class |
2638 | + """ |
2639 | _networks = {} |
2640 | |
2641 | def __init__(self): |
2642 | + """ |
2643 | + Extracts the configuration parameters from the configuration file |
2644 | + """ |
2645 | self._client = utils.import_object(conf.NEXUS_DRIVER) |
2646 | LOG.debug("Loaded driver %s\n" % conf.NEXUS_DRIVER) |
2647 | - #TODO (Edgar) Using just one Nexus 7K Switch and Port |
2648 | self._nexus_ip = conf.NEXUS_IP_ADDRESS |
2649 | self._nexus_username = cred.Store.getUsername(conf.NEXUS_IP_ADDRESS) |
2650 | self._nexus_password = cred.Store.getPassword(conf.NEXUS_IP_ADDRESS) |
2651 | self._nexus_port = conf.NEXUS_PORT |
2652 | + self._nexus_ssh_port = conf.NEXUS_SSH_PORT |
2653 | |
2654 | def get_all_networks(self, tenant_id): |
2655 | """ |
2656 | @@ -61,7 +68,8 @@ |
2657 | """ |
2658 | LOG.debug("NexusPlugin:create_network() called\n") |
2659 | self._client.create_vlan(vlan_name, str(vlan_id), self._nexus_ip, |
2660 | - self._nexus_username, self._nexus_password, self._nexus_port) |
2661 | + self._nexus_username, self._nexus_password, self._nexus_port, |
2662 | + self._nexus_ssh_port) |
2663 | |
2664 | new_net_dict = {const.NET_ID: net_id, |
2665 | const.NET_NAME: net_name, |
2666 | @@ -81,7 +89,8 @@ |
2667 | vlan_id = self._get_vlan_id_for_network(tenant_id, net_id) |
2668 | if net: |
2669 | self._client.delete_vlan(str(vlan_id), self._nexus_ip, |
2670 | - self._nexus_username, self._nexus_password, self._nexus_port) |
2671 | + self._nexus_username, self._nexus_password, self._nexus_port, |
2672 | + self._nexus_ssh_port) |
2673 | self._networks.pop(net_id) |
2674 | return net |
2675 | # Network not found |
2676 | @@ -100,7 +109,6 @@ |
2677 | Updates the symbolic name belonging to a particular |
2678 | Virtual Network. |
2679 | """ |
2680 | - #TODO (Edgar) We need to add an update method in the Nexus Driver |
2681 | LOG.debug("NexusPlugin:rename_network() called\n") |
2682 | network = self._get_network(tenant_id, net_id) |
2683 | network[const.NET_NAME] = new_name |
2684 | @@ -157,11 +165,17 @@ |
2685 | LOG.debug("NexusPlugin:unplug_interface() called\n") |
2686 | |
2687 | def _get_vlan_id_for_network(self, tenant_id, network_id): |
2688 | + """ |
2689 | + Obtain the VLAN ID given the Network ID |
2690 | + """ |
2691 | net = self._get_network(tenant_id, network_id) |
2692 | vlan_id = net[const.NET_VLAN_ID] |
2693 | return vlan_id |
2694 | |
2695 | def _get_network(self, tenant_id, network_id): |
2696 | + """ |
2697 | + Gets the NETWORK ID |
2698 | + """ |
2699 | network = self._networks.get(network_id) |
2700 | if not network: |
2701 | raise exc.NetworkNotFound(net_id=network_id) |
2702 | |
2703 | === added file 'quantum/plugins/cisco/nexus/cisco_nexus_snippets.py' |
2704 | --- quantum/plugins/cisco/nexus/cisco_nexus_snippets.py 1970-01-01 00:00:00 +0000 |
2705 | +++ quantum/plugins/cisco/nexus/cisco_nexus_snippets.py 2011-08-23 20:09:26 +0000 |
2706 | @@ -0,0 +1,156 @@ |
2707 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
2708 | +# |
2709 | +# Copyright 2011 Cisco Systems, Inc. All rights reserved. |
2710 | +# |
2711 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
2712 | +# not use this file except in compliance with the License. You may obtain |
2713 | +# a copy of the License at |
2714 | +# |
2715 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2716 | +# |
2717 | +# Unless required by applicable law or agreed to in writing, software |
2718 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
2719 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
2720 | +# License for the specific language governing permissions and limitations |
2721 | +# under the License. |
2722 | +# |
2723 | +# @author: Edgar Magana, Cisco Systems, Inc. |
2724 | + |
2725 | +""" |
2726 | +Nexus-OS XML-based configuration snippets |
2727 | +""" |
2728 | + |
2729 | +import logging as LOG |
2730 | + |
2731 | +from quantum.plugins.cisco.common import cisco_constants as const |
2732 | + |
2733 | +LOG.basicConfig(level=LOG.WARN) |
2734 | +LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
2735 | + |
2736 | + |
2737 | +# The following are standard strings, messages used to communicate with Nexus, |
2738 | +EXEC_CONF_SNIPPET = """ |
2739 | + <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> |
2740 | + <configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> |
2741 | + <__XML__MODE__exec_configure>%s |
2742 | + </__XML__MODE__exec_configure> |
2743 | + </configure> |
2744 | + </config> |
2745 | +""" |
2746 | + |
2747 | + |
2748 | +CMD_VLAN_CONF_SNIPPET = """ |
2749 | + <vlan> |
2750 | + <vlan-id-create-delete> |
2751 | + <__XML__PARAM_value>%s</__XML__PARAM_value> |
2752 | + <__XML__MODE_vlan> |
2753 | + <name> |
2754 | + <vlan-name>%s</vlan-name> |
2755 | + </name> |
2756 | + <state> |
2757 | + <vstate>active</vstate> |
2758 | + </state> |
2759 | + <no> |
2760 | + <shutdown/> |
2761 | + </no> |
2762 | + </__XML__MODE_vlan> |
2763 | + </vlan-id-create-delete> |
2764 | + </vlan> |
2765 | +""" |
2766 | + |
2767 | +CMD_NO_VLAN_CONF_SNIPPET = """ |
2768 | + <no> |
2769 | + <vlan> |
2770 | + <vlan-id-create-delete> |
2771 | + <__XML__PARAM_value>%s</__XML__PARAM_value> |
2772 | + </vlan-id-create-delete> |
2773 | + </vlan> |
2774 | + </no> |
2775 | +""" |
2776 | + |
2777 | +CMD_VLAN_INT_SNIPPET = """ |
2778 | + <interface> |
2779 | + <ethernet> |
2780 | + <interface>%s</interface> |
2781 | + <__XML__MODE_if-ethernet-switch> |
2782 | + <switchport></switchport>import logging as LOG |
2783 | + <switchport> |
2784 | + <trunk> |
2785 | + <allowed> |
2786 | + <vlan> |
2787 | + <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2788 | + <allow-vlans>%s</allow-vlans> |
2789 | + </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2790 | + </vlan> |
2791 | + </allowed> |
2792 | + </trunk> |
2793 | + </switchport> |
2794 | + </__XML__MODE_if-ethernet-switch> |
2795 | + </ethernet> |
2796 | + </interface> |
2797 | +""" |
2798 | + |
2799 | +CMD_PORT_TRUNK = """ |
2800 | + <interface> |
2801 | + <ethernet> |
2802 | + <interface>%s</interface> |
2803 | + <__XML__MODE_if-ethernet-switch> |
2804 | + <switchport></switchport> |
2805 | + <switchport> |
2806 | + <mode> |
2807 | + <trunk> |
2808 | + </trunk> |
2809 | + </mode> |
2810 | + </switchport> |
2811 | + </__XML__MODE_if-ethernet-switch>C: 1: Missing docstring |
2812 | + </ethernet> |
2813 | + </interface> |
2814 | +""" |
2815 | + |
2816 | +CMD_NO_SWITCHPORT = """ |
2817 | + <interface> |
2818 | + <ethernet> |
2819 | + <interface>%s</interface> |
2820 | + <__XML__MODE_if-ethernet-switch> |
2821 | + <no> |
2822 | + <switchport> |
2823 | + </switchport> |
2824 | + </no> |
2825 | + </__XML__MODE_if-ethernet-switch> |
2826 | + </ethernet> |
2827 | + </interface> |
2828 | +""" |
2829 | + |
2830 | + |
2831 | +CMD_NO_VLAN_INT_SNIPPET = """ |
2832 | + <interface> |
2833 | + <ethernet>C: 1: Missing docstring |
2834 | + <interface>%s</interface> |
2835 | + <__XML__MODE_if-ethernet-switch> |
2836 | + <switchport></switchport> |
2837 | + <no> |
2838 | + <switchport> |
2839 | + <trunk> |
2840 | + <allowed> |
2841 | + <vlan> |
2842 | + <__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2843 | + <allow-vlans>%s</allow-vlans> |
2844 | + </__XML__BLK_Cmd_switchport_trunk_allowed_allow-vlans> |
2845 | + </vlan> |
2846 | + </allowed> |
2847 | + </trunk> |
2848 | + </switchport> |
2849 | + </no> |
2850 | + </__XML__MODE_if-ethernet-switch> |
2851 | + </ethernet> |
2852 | + </interface> |
2853 | +""" |
2854 | + |
2855 | + |
2856 | +FILTER_SHOW_VLAN_BRIEF_SNIPPET = """ |
2857 | + <show xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> |
2858 | + <vlan> |
2859 | + <brief/> |
2860 | + </vlan> |
2861 | + </show> |
2862 | +""" |
2863 | |
2864 | === modified file 'quantum/plugins/cisco/run_tests.py' |
2865 | --- quantum/plugins/cisco/run_tests.py 2011-08-08 07:23:44 +0000 |
2866 | +++ quantum/plugins/cisco/run_tests.py 2011-08-23 20:09:26 +0000 |
2867 | @@ -16,50 +16,34 @@ |
2868 | # See the License for the specific language governing permissions and |
2869 | # limitations under the License. |
2870 | |
2871 | -# Colorizer Code is borrowed from Twisted: |
2872 | -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. |
2873 | -# |
2874 | -# Permission is hereby granted, free of charge, to any person obtaining |
2875 | -# a copy of this software and associated documentation files (the |
2876 | -# "Software"), to deal in the Software without restriction, including |
2877 | -# without limitation the rights to use, copy, modify, merge, publish, |
2878 | -# distribute, sublicense, and/or sell copies of the Software, and to |
2879 | -# permit persons to whom the Software is furnished to do so, subject to |
2880 | -# the following conditions: |
2881 | -# |
2882 | -# The above copyright notice and this permission notice shall be |
2883 | -# included in all copies or substantial portions of the Software. |
2884 | -# |
2885 | -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
2886 | -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
2887 | -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
2888 | -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
2889 | -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
2890 | -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
2891 | -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
2892 | - |
2893 | -"""Unittest runner for quantum |
2894 | + |
2895 | +"""Unittest runner for quantum Cisco plugin |
2896 | + |
2897 | +This file should be run from the top dir in the quantum directory |
2898 | |
2899 | To run all test:: |
2900 | - python run_tests.py |
2901 | + python quantum/plugins/cisco/run_tests.py |
2902 | |
2903 | To run all unit tests:: |
2904 | - python run_tests.py unit |
2905 | + python quantum/plugins/cisco/run_tests.py quantum.plugins.cisco.tests.unit |
2906 | |
2907 | To run all functional tests:: |
2908 | - python run_tests.py functional |
2909 | + python quantum/plugins/cisco/run_tests.py functional |
2910 | |
2911 | To run a single unit test:: |
2912 | - python run_tests.py unit.test_stores:TestSwiftBackend.test_get |
2913 | + python quantum/plugins/cisco/run_tests.py \ |
2914 | + quantum.plugins.cisco.tests.unit.test_stores:TestSwiftBackend.test_get |
2915 | |
2916 | To run a single functional test:: |
2917 | - python run_tests.py functional.test_service:TestController.test_create |
2918 | + python quantum/plugins/cisco/run_tests.py \ |
2919 | + quantum.plugins.cisco.tests.functional.test_service \ |
2920 | + :TestController.test_create |
2921 | |
2922 | To run a single unit test module:: |
2923 | - python run_tests.py unit.test_stores |
2924 | + python quantum/plugins/cisco/run_tests.py unit.test_stores |
2925 | |
2926 | To run a single functional test module:: |
2927 | - python run_tests.py functional.test_stores |
2928 | + python quantum/plugins/cisco/run_tests.py functional.test_stores |
2929 | """ |
2930 | |
2931 | import gettext |
2932 | @@ -69,233 +53,37 @@ |
2933 | import sys |
2934 | |
2935 | from nose import config |
2936 | -from nose import result |
2937 | -from nose import core |
2938 | - |
2939 | - |
2940 | -class _AnsiColorizer(object): |
2941 | - """ |
2942 | - A colorizer is an object that loosely wraps around a stream, allowing |
2943 | - callers to write text to the stream in a particular color. |
2944 | - |
2945 | - Colorizer classes must implement C{supported()} and C{write(text, color)}. |
2946 | - """ |
2947 | - _colors = dict(black=30, red=31, green=32, yellow=33, |
2948 | - blue=34, magenta=35, cyan=36, white=37) |
2949 | - |
2950 | - def __init__(self, stream): |
2951 | - self.stream = stream |
2952 | - |
2953 | - def supported(cls, stream=sys.stdout): |
2954 | - """ |
2955 | - A class method that returns True if the current platform supports |
2956 | - coloring terminal output using this method. Returns False otherwise. |
2957 | - """ |
2958 | - if not stream.isatty(): |
2959 | - return False # auto color only on TTYs |
2960 | - try: |
2961 | - import curses |
2962 | - except ImportError: |
2963 | - return False |
2964 | - else: |
2965 | - try: |
2966 | - try: |
2967 | - return curses.tigetnum("colors") > 2 |
2968 | - except curses.error: |
2969 | - curses.setupterm() |
2970 | - return curses.tigetnum("colors") > 2 |
2971 | - except: |
2972 | - raise |
2973 | - # guess false in case of error |
2974 | - return False |
2975 | - supported = classmethod(supported) |
2976 | - |
2977 | - def write(self, text, color): |
2978 | - """ |
2979 | - Write the given text to the stream in the given color. |
2980 | - |
2981 | - @param text: Text to be written to the stream. |
2982 | - |
2983 | - @param color: A string label for a color. e.g. 'red', 'white'. |
2984 | - """ |
2985 | - color = self._colors[color] |
2986 | - self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) |
2987 | - |
2988 | - |
2989 | -class _Win32Colorizer(object): |
2990 | - """ |
2991 | - See _AnsiColorizer docstring. |
2992 | - """ |
2993 | - def __init__(self, stream): |
2994 | - from win32console import GetStdHandle, STD_OUT_HANDLE, \ |
2995 | - FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \ |
2996 | - FOREGROUND_INTENSITY |
2997 | - red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, |
2998 | - FOREGROUND_BLUE, FOREGROUND_INTENSITY) |
2999 | - self.stream = stream |
3000 | - self.screenBuffer = GetStdHandle(STD_OUT_HANDLE) |
3001 | - self._colors = { |
3002 | - 'normal': red | green | blue, |
3003 | - 'red': red | bold, |
3004 | - 'green': green | bold, |
3005 | - 'blue': blue | bold, |
3006 | - 'yellow': red | green | bold, |
3007 | - 'magenta': red | blue | bold, |
3008 | - 'cyan': green | blue | bold, |
3009 | - 'white': red | green | blue | bold} |
3010 | - |
3011 | - def supported(cls, stream=sys.stdout): |
3012 | - try: |
3013 | - import win32console |
3014 | - screenBuffer = win32console.GetStdHandle( |
3015 | - win32console.STD_OUT_HANDLE) |
3016 | - except ImportError: |
3017 | - return False |
3018 | - import pywintypes |
3019 | - try: |
3020 | - screenBuffer.SetConsoleTextAttribute( |
3021 | - win32console.FOREGROUND_RED | |
3022 | - win32console.FOREGROUND_GREEN | |
3023 | - win32console.FOREGROUND_BLUE) |
3024 | - except pywintypes.error: |
3025 | - return False |
3026 | - else: |
3027 | - return True |
3028 | - supported = classmethod(supported) |
3029 | - |
3030 | - def write(self, text, color): |
3031 | - color = self._colors[color] |
3032 | - self.screenBuffer.SetConsoleTextAttribute(color) |
3033 | - self.stream.write(text) |
3034 | - self.screenBuffer.SetConsoleTextAttribute(self._colors['normal']) |
3035 | - |
3036 | - |
3037 | -class _NullColorizer(object): |
3038 | - """ |
3039 | - See _AnsiColorizer docstring. |
3040 | - """ |
3041 | - def __init__(self, stream): |
3042 | - self.stream = stream |
3043 | - |
3044 | - def supported(cls, stream=sys.stdout): |
3045 | - return True |
3046 | - supported = classmethod(supported) |
3047 | - |
3048 | - def write(self, text, color): |
3049 | - self.stream.write(text) |
3050 | - |
3051 | - |
3052 | -class QuantumTestResult(result.TextTestResult): |
3053 | - def __init__(self, *args, **kw): |
3054 | - result.TextTestResult.__init__(self, *args, **kw) |
3055 | - self._last_case = None |
3056 | - self.colorizer = None |
3057 | - # NOTE(vish, tfukushima): reset stdout for the terminal check |
3058 | - stdout = sys.__stdout__ |
3059 | - for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: |
3060 | - if colorizer.supported(): |
3061 | - self.colorizer = colorizer(self.stream) |
3062 | - break |
3063 | - sys.stdout = stdout |
3064 | - |
3065 | - def getDescription(self, test): |
3066 | - return str(test) |
3067 | - |
3068 | - # NOTE(vish, tfukushima): copied from unittest with edit to add color |
3069 | - def addSuccess(self, test): |
3070 | - unittest.TestResult.addSuccess(self, test) |
3071 | - if self.showAll: |
3072 | - self.colorizer.write("OK", 'green') |
3073 | - self.stream.writeln() |
3074 | - elif self.dots: |
3075 | - self.stream.write('.') |
3076 | - self.stream.flush() |
3077 | - |
3078 | - # NOTE(vish, tfukushima): copied from unittest with edit to add color |
3079 | - def addFailure(self, test, err): |
3080 | - unittest.TestResult.addFailure(self, test, err) |
3081 | - if self.showAll: |
3082 | - self.colorizer.write("FAIL", 'red') |
3083 | - self.stream.writeln() |
3084 | - elif self.dots: |
3085 | - self.stream.write('F') |
3086 | - self.stream.flush() |
3087 | - |
3088 | - # NOTE(vish, tfukushima): copied from unittest with edit to add color |
3089 | - def addError(self, test, err): |
3090 | - """Overrides normal addError to add support for errorClasses. |
3091 | - If the exception is a registered class, the error will be added |
3092 | - to the list for that class, not errors. |
3093 | - """ |
3094 | - stream = getattr(self, 'stream', None) |
3095 | - ec, ev, tb = err |
3096 | - try: |
3097 | - exc_info = self._exc_info_to_string(err, test) |
3098 | - except TypeError: |
3099 | - # This is for compatibility with Python 2.3. |
3100 | - exc_info = self._exc_info_to_string(err) |
3101 | - for cls, (storage, label, isfail) in self.errorClasses.items(): |
3102 | - if result.isclass(ec) and issubclass(ec, cls): |
3103 | - if isfail: |
3104 | - test.passwd = False |
3105 | - storage.append((test, exc_info)) |
3106 | - # Might get patched into a streamless result |
3107 | - if stream is not None: |
3108 | - if self.showAll: |
3109 | - message = [label] |
3110 | - detail = result._exception_details(err[1]) |
3111 | - if detail: |
3112 | - message.append(detail) |
3113 | - stream.writeln(": ".join(message)) |
3114 | - elif self.dots: |
3115 | - stream.write(label[:1]) |
3116 | - return |
3117 | - self.errors.append((test, exc_info)) |
3118 | - test.passed = False |
3119 | - if stream is not None: |
3120 | - if self.showAll: |
3121 | - self.colorizer.write("ERROR", 'red') |
3122 | - self.stream.writeln() |
3123 | - elif self.dots: |
3124 | - stream.write('E') |
3125 | - |
3126 | - def startTest(self, test): |
3127 | - unittest.TestResult.startTest(self, test) |
3128 | - current_case = test.test.__class__.__name__ |
3129 | - |
3130 | - if self.showAll: |
3131 | - if current_case != self._last_case: |
3132 | - self.stream.writeln(current_case) |
3133 | - self._last_case = current_case |
3134 | - |
3135 | - self.stream.write( |
3136 | - ' %s' % str(test.test._testMethodName).ljust(60)) |
3137 | - self.stream.flush() |
3138 | - |
3139 | - |
3140 | -class QuantumTestRunner(core.TextTestRunner): |
3141 | - def _makeResult(self): |
3142 | - return QuantumTestResult(self.stream, |
3143 | - self.descriptions, |
3144 | - self.verbosity, |
3145 | - self.config) |
3146 | - |
3147 | + |
3148 | +sys.path.append(os.getcwd()) |
3149 | + |
3150 | +from quantum.common.test_lib import run_tests, test_config |
3151 | |
3152 | if __name__ == '__main__': |
3153 | - # Set up test logger. |
3154 | - logger = logging.getLogger() |
3155 | - hdlr = logging.StreamHandler() |
3156 | - formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') |
3157 | - hdlr.setFormatter(formatter) |
3158 | - logger.addHandler(hdlr) |
3159 | - logger.setLevel(logging.DEBUG) |
3160 | + exit_status = False |
3161 | + |
3162 | + # if a single test case was specified, |
3163 | + # we should only invoked the tests once |
3164 | + invoke_once = len(sys.argv) > 1 |
3165 | + |
3166 | + cwd = os.getcwd() |
3167 | |
3168 | working_dir = os.path.abspath("tests") |
3169 | c = config.Config(stream=sys.stdout, |
3170 | env=os.environ, |
3171 | verbosity=3, |
3172 | workingDir=working_dir) |
3173 | - runner = QuantumTestRunner(stream=c.stream, |
3174 | - verbosity=c.verbosity, |
3175 | - config=c) |
3176 | - sys.exit(not core.run(config=c, testRunner=runner)) |
3177 | + exit_status = run_tests(c) |
3178 | + |
3179 | + if invoke_once: |
3180 | + sys.exit(0) |
3181 | + |
3182 | + os.chdir(cwd) |
3183 | + |
3184 | + working_dir = os.path.abspath("quantum/plugins/cisco/tests") |
3185 | + c = config.Config(stream=sys.stdout, |
3186 | + env=os.environ, |
3187 | + verbosity=3, |
3188 | + workingDir=working_dir) |
3189 | + exit_status = exit_status or run_tests(c) |
3190 | + |
3191 | + sys.exit(exit_status) |
3192 | |
3193 | === added file 'quantum/plugins/cisco/tests/unit/test_database.py' |
3194 | --- quantum/plugins/cisco/tests/unit/test_database.py 1970-01-01 00:00:00 +0000 |
3195 | +++ quantum/plugins/cisco/tests/unit/test_database.py 2011-08-23 20:09:26 +0000 |
3196 | @@ -0,0 +1,840 @@ |
3197 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
3198 | + |
3199 | +# Copyright 2011, Cisco Systems, Inc. |
3200 | +# |
3201 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
3202 | +# not use this file except in compliance with the License. You may obtain |
3203 | +# a copy of the License at |
3204 | +# |
3205 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3206 | +# |
3207 | +# Unless required by applicable law or agreed to in writing, software |
3208 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
3209 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
3210 | +# License for the specific language governing permissions and limitations |
3211 | +# under the License. |
3212 | +# @author: Rohit Agarwalla, Cisco Systems, Inc. |
3213 | + |
3214 | +""" |
3215 | +test_database.py is an independent test suite |
3216 | +that tests the database api method calls |
3217 | +""" |
3218 | +import logging as LOG |
3219 | +import unittest |
3220 | + |
3221 | +from quantum.plugins.cisco.common import cisco_constants as const |
3222 | + |
3223 | +import quantum.plugins.cisco.db.api as db |
3224 | +import quantum.plugins.cisco.db.l2network_db as l2network_db |
3225 | + |
3226 | + |
3227 | +LOG.getLogger(const.LOGGER_COMPONENT_NAME) |
3228 | + |
3229 | + |
3230 | +class L2networkDB(object): |
3231 | + """Class conisting of methods to call L2network db methods""" |
3232 | + def get_all_vlan_bindings(self): |
3233 | + """Get all vlan binding into a list of dict""" |
3234 | + vlans = [] |
3235 | + try: |
3236 | + for vlan_bind in l2network_db.get_all_vlan_bindings(): |
3237 | + LOG.debug("Getting vlan bindings for vlan: %s" % \ |
3238 | + vlan_bind.vlan_id) |
3239 | + vlan_dict = {} |
3240 | + vlan_dict["vlan-id"] = str(vlan_bind.vlan_id) |
3241 | + vlan_dict["vlan-name"] = vlan_bind.vlan_name |
3242 | + vlan_dict["net-id"] = str(vlan_bind.network_id) |
3243 | + vlans.append(vlan_dict) |
3244 | + except Exception, exc: |
3245 | + LOG.error("Failed to get all vlan bindings: %s" % str(exc)) |
3246 | + return vlans |
3247 | + |
3248 | + def get_vlan_binding(self, network_id): |
3249 | + """Get a vlan binding""" |
3250 | + vlan = [] |
3251 | + try: |
3252 | + for vlan_bind in l2network_db.get_vlan_binding(network_id): |
3253 | + LOG.debug("Getting vlan binding for vlan: %s" \ |
3254 | + % vlan_bind.vlan_id) |
3255 | + vlan_dict = {} |
3256 | + vlan_dict["vlan-id"] = str(vlan_bind.vlan_id) |
3257 | + vlan_dict["vlan-name"] = vlan_bind.vlan_name |
3258 | + vlan_dict["net-id"] = str(vlan_bind.network_id) |
3259 | + vlan.append(vlan_dict) |
3260 | + except Exception, exc: |
3261 | + LOG.error("Failed to get vlan binding: %s" % str(exc)) |
3262 | + return vlan |
3263 | + |
3264 | + def create_vlan_binding(self, vlan_id, vlan_name, network_id): |
3265 | + """Create a vlan binding""" |
3266 | + vlan_dict = {} |
3267 | + try: |
3268 | + res = l2network_db.add_vlan_binding(vlan_id, vlan_name, network_id) |
3269 | + LOG.debug("Created vlan binding for vlan: %s" % res.vlan_id) |
3270 | + vlan_dict["vlan-id"] = str(res.vlan_id) |
3271 | + vlan_dict["vlan-name"] = res.vlan_name |
3272 | + vlan_dict["net-id"] = str(res.network_id) |
3273 | + return vlan_dict |
3274 | + except Exception, exc: |
3275 | + LOG.error("Failed to create vlan binding: %s" % str(exc)) |
3276 | + |
3277 | + def delete_vlan_binding(self, network_id): |
3278 | + """Delete a vlan binding""" |
3279 | + try: |
3280 | + res = l2network_db.remove_vlan_binding(network_id) |
3281 | + LOG.debug("Deleted vlan binding for vlan: %s" % res.vlan_id) |
3282 | + vlan_dict = {} |
3283 | + vlan_dict["vlan-id"] = str(res.vlan_id) |
3284 | + return vlan_dict |
3285 | + except Exception, exc: |
3286 | + raise Exception("Failed to delete vlan binding: %s" % str(exc)) |
3287 | + |
3288 | + def update_vlan_binding(self, network_id, vlan_id, vlan_name): |
3289 | + """Update a vlan binding""" |
3290 | + try: |
3291 | + res = l2network_db.update_vlan_binding(network_id, vlan_id, \ |
3292 | + vlan_name) |
3293 | + LOG.debug("Updating vlan binding for vlan: %s" % res.vlan_id) |
3294 | + vlan_dict = {} |
3295 | + vlan_dict["vlan-id"] = str(res.vlan_id) |
3296 | + vlan_dict["vlan-name"] = res.vlan_name |
3297 | + vlan_dict["net-id"] = str(res.network_id) |
3298 | + return vlan_dict |
3299 | + except Exception, exc: |
3300 | + raise Exception("Failed to update vlan binding: %s" % str(exc)) |
3301 | + |
3302 | + def get_all_portprofiles(self): |
3303 | + """Get all portprofiles""" |
3304 | + pps = [] |
3305 | + try: |
3306 | + for portprof in l2network_db.get_all_portprofiles(): |
3307 | + LOG.debug("Getting port profile : %s" % portprof.uuid) |
3308 | + pp_dict = {} |
3309 | + pp_dict["portprofile-id"] = str(portprof.uuid) |
3310 | + pp_dict["portprofile-name"] = portprof.name |
3311 | + pp_dict["vlan-id"] = str(portprof.vlan_id) |
3312 | + pp_dict["qos"] = portprof.qos |
3313 | + pps.append(pp_dict) |
3314 | + except Exception, exc: |
3315 | + LOG.error("Failed to get all port profiles: %s" % str(exc)) |
3316 | + return pps |
3317 | + |
3318 | + def get_portprofile(self, tenant_id, pp_id): |
3319 | + """Get a portprofile""" |
3320 | + pp_list = [] |
3321 | + try: |
3322 | + for portprof in l2network_db.get_portprofile(tenant_id, pp_id): |
3323 | + LOG.debug("Getting port profile : %s" % portprof.uuid) |
3324 | + pp_dict = {} |
3325 | + pp_dict["portprofile-id"] = str(portprof.uuid) |
3326 | + pp_dict["portprofile-name"] = portprof.name |
3327 | + pp_dict["vlan-id"] = str(portprof.vlan_id) |
3328 | + pp_dict["qos"] = portprof.qos |
3329 | + pp_list.append(pp_dict) |
3330 | + except Exception, exc: |
3331 | + LOG.error("Failed to get port profile: %s" % str(exc)) |
3332 | + return pp |
3333 | + |
3334 | + def create_portprofile(self, tenant_id, name, vlan_id, qos): |
3335 | + """Create a portprofile""" |
3336 | + pp_dict = {} |
3337 | + try: |
3338 | + res = l2network_db.add_portprofile(tenant_id, name, vlan_id, qos) |
3339 | + LOG.debug("Created port profile: %s" % res.uuid) |
3340 | + pp_dict["portprofile-id"] = str(res.uuid) |
3341 | + pp_dict["portprofile-name"] = res.name |
3342 | + pp_dict["vlan-id"] = str(res.vlan_id) |
3343 | + pp_dict["qos"] = res.qos |
3344 | + return pp_dict |
3345 | + except Exception, exc: |
3346 | + LOG.error("Failed to create port profile: %s" % str(exc)) |
3347 | + |
3348 | + def delete_portprofile(self, tenant_id, pp_id): |
3349 | + """Delete a portprofile""" |
3350 | + try: |
3351 | + res = l2network_db.remove_portprofile(tenant_id, pp_id) |
3352 | + LOG.debug("Deleted port profile : %s" % res.uuid) |
3353 | + pp_dict = {} |
3354 | + pp_dict["pp-id"] = str(res.uuid) |
3355 | + return pp_dict |
3356 | + except Exception, exc: |
3357 | + raise Exception("Failed to delete port profile: %s" % str(exc)) |
3358 | + |
3359 | + def update_portprofile(self, tenant_id, pp_id, name, vlan_id, qos): |
3360 | + """Update a portprofile""" |
3361 | + try: |
3362 | + res = l2network_db.update_portprofile(tenant_id, pp_id, name, |
3363 | + vlan_id, qos) |
3364 | + LOG.debug("Updating port profile : %s" % res.uuid) |
3365 | + pp_dict = {} |
3366 | + pp_dict["portprofile-id"] = str(res.uuid) |
3367 | + pp_dict["portprofile-name"] = res.name |
3368 | + pp_dict["vlan-id"] = str(res.vlan_id) |
3369 | + pp_dict["qos"] = res.qos |
3370 | + return pp_dict |
3371 | + except Exception, exc: |
3372 | + raise Exception("Failed to update port profile: %s" % str(exc)) |
3373 | + |
3374 | + def get_all_pp_bindings(self): |
3375 | + """Get all portprofile bindings""" |
3376 | + pp_bindings = [] |
3377 | + try: |
3378 | + for pp_bind in l2network_db.get_all_pp_bindings(): |
3379 | + LOG.debug("Getting port profile binding: %s" % \ |
3380 | + pp_bind.portprofile_id) |
3381 | + ppbinding_dict = {} |
3382 | + ppbinding_dict["portprofile-id"] = str(pp_bind.portprofile_id) |
3383 | + ppbinding_dict["port-id"] = str(pp_bind.port_id) |
3384 | + ppbinding_dict["tenant-id"] = pp_bind.tenant_id |
3385 | + ppbinding_dict["default"] = pp_bind.default |
3386 | + pp_bindings.append(ppbinding_dict) |
3387 | + except Exception, exc: |
3388 | + LOG.error("Failed to get all port profiles: %s" % str(exc)) |
3389 | + return pp_bindings |
3390 | + |
3391 | + def get_pp_binding(self, tenant_id, pp_id): |
3392 | + """Get a portprofile binding""" |
3393 | + pp_binding = [] |
3394 | + try: |
3395 | + for pp_bind in l2network_db.get_pp_binding(tenant_id, pp_id): |
3396 | + LOG.debug("Getting port profile binding: %s" % \ |
3397 | + pp_bind.portprofile_id) |
3398 | + ppbinding_dict = {} |
3399 | + ppbinding_dict["portprofile-id"] = str(pp_bind.portprofile_id) |
3400 | + ppbinding_dict["port-id"] = str(pp_bind.port_id) |
3401 | + ppbinding_dict["tenant-id"] = pp_bind.tenant_id |
3402 | + ppbinding_dict["default"] = pp_bind.default |
3403 | + pp_binding.append(ppbinding_dict) |
3404 | + except Exception, exc: |
3405 | + LOG.error("Failed to get port profile binding: %s" % str(exc)) |
3406 | + return pp_binding |
3407 | + |
3408 | + def create_pp_binding(self, tenant_id, port_id, pp_id, default): |
3409 | + """Add a portprofile binding""" |
3410 | + ppbinding_dict = {} |
3411 | + try: |
3412 | + res = l2network_db.add_pp_binding(tenant_id, port_id, pp_id, \ |
3413 | + default) |
3414 | + LOG.debug("Created port profile binding: %s" % res.portprofile_id) |
3415 | + ppbinding_dict["portprofile-id"] = str(res.portprofile_id) |
3416 | + ppbinding_dict["port-id"] = str(res.port_id) |
3417 | + ppbinding_dict["tenant-id"] = res.tenant_id |
3418 | + ppbinding_dict["default"] = res.default |
3419 | + return ppbinding_dict |
3420 | + except Exception, exc: |
3421 | + LOG.error("Failed to create port profile binding: %s" % str(exc)) |
3422 | + |
3423 | + def delete_pp_binding(self, tenant_id, port_id, pp_id): |
3424 | + """Delete a portprofile binding""" |
3425 | + try: |
3426 | + res = l2network_db.remove_pp_binding(tenant_id, port_id, pp_id) |
3427 | + LOG.debug("Deleted port profile binding : %s" % res.portprofile_id) |
3428 | + ppbinding_dict = {} |
3429 | + ppbinding_dict["portprofile-id"] = str(res.portprofile_id) |
3430 | + return ppbinding_dict |
3431 | + except Exception, exc: |
3432 | + raise Exception("Failed to delete port profile: %s" % str(exc)) |
3433 | + |
3434 | + def update_pp_binding(self, tenant_id, pp_id, newtenant_id, \ |
3435 | + port_id, default): |
3436 | + """Update portprofile binding""" |
3437 | + try: |
3438 | + res = l2network_db.update_pp_binding(tenant_id, pp_id, |
3439 | + newtenant_id, port_id, default) |
3440 | + LOG.debug("Updating port profile binding: %s" % res.portprofile_id) |
3441 | + ppbinding_dict = {} |
3442 | + ppbinding_dict["portprofile-id"] = str(res.portprofile_id) |
3443 | + ppbinding_dict["port-id"] = str(res.port_id) |
3444 | + ppbinding_dict["tenant-id"] = res.tenant_id |
3445 | + ppbinding_dict["default"] = res.default |
3446 | + return ppbinding_dict |
3447 | + except Exception, exc: |
3448 | + raise Exception("Failed to update portprofile binding:%s" \ |
3449 | + % str(exc)) |
3450 | + |
3451 | + |
3452 | +class QuantumDB(object): |
3453 | + """Class conisting of methods to call Quantum db methods""" |
3454 | + def get_all_networks(self, tenant_id): |
3455 | + """Get all networks""" |
3456 | + nets = [] |
3457 | + try: |
3458 | + for net in db.network_list(tenant_id): |
3459 | + LOG.debug("Getting network: %s" % net.uuid) |
3460 | + net_dict = {} |
3461 | + net_dict["tenant-id"] = net.tenant_id |
3462 | + net_dict["net-id"] = str(net.uuid) |
3463 | + net_dict["net-name"] = net.name |
3464 | + nets.append(net_dict) |
3465 | + except Exception, exc: |
3466 | + LOG.error("Failed to get all networks: %s" % str(exc)) |
3467 | + return nets |
3468 | + |
3469 | + def get_network(self, network_id): |
3470 | + """Get a network""" |
3471 | + net = [] |
3472 | + try: |
3473 | + for net in db.network_get(network_id): |
3474 | + LOG.debug("Getting network: %s" % net.uuid) |
3475 | + net_dict = {} |
3476 | + net_dict["tenant-id"] = net.tenant_id |
3477 | + net_dict["net-id"] = str(net.uuid) |
3478 | + net_dict["net-name"] = net.name |
3479 | + net.append(net_dict) |
3480 | + except Exception, exc: |
3481 | + LOG.error("Failed to get network: %s" % str(exc)) |
3482 | + return net |
3483 | + |
3484 | + def create_network(self, tenant_id, net_name): |
3485 | + """Create a network""" |
3486 | + net_dict = {} |
3487 | + try: |
3488 | + res = db.network_create(tenant_id, net_name) |
3489 | + LOG.debug("Created network: %s" % res.uuid) |
3490 | + net_dict["tenant-id"] = res.tenant_id |
3491 | + net_dict["net-id"] = str(res.uuid) |
3492 | + net_dict["net-name"] = res.name |
3493 | + return net_dict |
3494 | + except Exception, exc: |
3495 | + LOG.error("Failed to create network: %s" % str(exc)) |
3496 | + |
3497 | + def delete_network(self, net_id): |
3498 | + """Delete a network""" |
3499 | + try: |
3500 | + net = db.network_destroy(net_id) |
3501 | + LOG.debug("Deleted network: %s" % net.uuid) |
3502 | + net_dict = {} |
3503 | + net_dict["net-id"] = str(net.uuid) |
3504 | + return net_dict |
3505 | + except Exception, exc: |
3506 | + raise Exception("Failed to delete port: %s" % str(exc)) |
3507 | + |
3508 | + def rename_network(self, tenant_id, net_id, new_name): |
3509 | + """Rename a network""" |
3510 | + try: |
3511 | + net = db.network_rename(tenant_id, net_id, new_name) |
3512 | + LOG.debug("Renamed network: %s" % net.uuid) |
3513 | + net_dict = {} |
3514 | + net_dict["net-id"] = str(net.uuid) |
3515 | + net_dict["net-name"] = net.name |
3516 | + return net_dict |
3517 | + except Exception, exc: |
3518 | + raise Exception("Failed to rename network: %s" % str(exc)) |
3519 | + |
3520 | + def get_all_ports(self, net_id): |
3521 | + """Get all ports""" |
3522 | + ports = [] |
3523 | + try: |
3524 | + for port in db.port_list(net_id): |
3525 | + LOG.debug("Getting port: %s" % port.uuid) |
3526 | + port_dict = {} |
3527 | + port_dict["port-id"] = str(port.uuid) |
3528 | + port_dict["net-id"] = str(port.network_id) |
3529 | + port_dict["int-id"] = port.interface_id |
3530 | + port_dict["state"] = port.state |
3531 | + port_dict["net"] = port.network |
3532 | + ports.append(port_dict) |
3533 | + return ports |
3534 | + except Exception, exc: |
3535 | + LOG.error("Failed to get all ports: %s" % str(exc)) |
3536 | + |
3537 | + def get_port(self, net_id, port_id): |
3538 | + """Get a port""" |
3539 | + port_list = [] |
3540 | + port = db.port_get(net_id, port_id) |
3541 | + try: |
3542 | + LOG.debug("Getting port: %s" % port.uuid) |
3543 | + port_dict = {} |
3544 | + port_dict["port-id"] = str(port.uuid) |
3545 | + port_dict["net-id"] = str(port.network_id) |
3546 | + port_dict["int-id"] = port.interface_id |
3547 | + port_dict["state"] = port.state |
3548 | + port_list.append(port_dict) |
3549 | + return port_list |
3550 | + except Exception, exc: |
3551 | + LOG.error("Failed to get port: %s" % str(exc)) |
3552 | + |
3553 | + def create_port(self, net_id): |
3554 | + """Add a port""" |
3555 | + port_dict = {} |
3556 | + try: |
3557 | + port = db.port_create(net_id) |
3558 | + LOG.debug("Creating port %s" % port.uuid) |
3559 | + port_dict["port-id"] = str(port.uuid) |
3560 | + port_dict["net-id"] = str(port.network_id) |
3561 | + port_dict["int-id"] = port.interface_id |
3562 | + port_dict["state"] = port.state |
3563 | + return port_dict |
3564 | + except Exception, exc: |
3565 | + LOG.error("Failed to create port: %s" % str(exc)) |
3566 | + |
3567 | + def delete_port(self, net_id, port_id): |
3568 | + """Delete a port""" |
3569 | + try: |
3570 | + port = db.port_destroy(net_id, port_id) |
3571 | + LOG.debug("Deleted port %s" % port.uuid) |
3572 | + port_dict = {} |
3573 | + port_dict["port-id"] = str(port.uuid) |
3574 | + return port_dict |
3575 | + except Exception, exc: |
3576 | + raise Exception("Failed to delete port: %s" % str(exc)) |
3577 | + |
3578 | + def update_port(self, net_id, port_id, port_state): |
3579 | + """Update a port""" |
3580 | + try: |
3581 | + port = db.port_set_state(net_id, port_id, port_state) |
3582 | + LOG.debug("Updated port %s" % port.uuid) |
3583 | + port_dict = {} |
3584 | + port_dict["port-id"] = str(port.uuid) |
3585 | + port_dict["net-id"] = str(port.network_id) |
3586 | + port_dict["int-id"] = port.interface_id |
3587 | + port_dict["state"] = port.state |
3588 | + return port_dict |
3589 | + except Exception, exc: |
3590 | + raise Exception("Failed to update port state: %s" % str(exc)) |
3591 | + |
3592 | + def plug_interface(self, net_id, port_id, int_id): |
3593 | + """Plug interface to a port""" |
3594 | + try: |
3595 | + port = db.port_set_attachment(net_id, port_id, int_id) |
3596 | + LOG.debug("Attached interface to port %s" % port.uuid) |
3597 | + port_dict = {} |
3598 | + port_dict["port-id"] = str(port.uuid) |
3599 | + port_dict["net-id"] = str(port.network_id) |
3600 | + port_dict["int-id"] = port.interface_id |
3601 | + port_dict["state"] = port.state |
3602 | + return port_dict |
3603 | + except Exception, exc: |
3604 | + raise Exception("Failed to plug interface: %s" % str(exc)) |
3605 | + |
3606 | + def unplug_interface(self, net_id, port_id): |
3607 | + """Unplug interface to a port""" |
3608 | + try: |
3609 | + port = db.port_unset_attachment(net_id, port_id) |
3610 | + LOG.debug("Detached interface from port %s" % port.uuid) |
3611 | + port_dict = {} |
3612 | + port_dict["port-id"] = str(port.uuid) |
3613 | + port_dict["net-id"] = str(port.network_id) |
3614 | + port_dict["int-id"] = port.interface_id |
3615 | + port_dict["state"] = port.state |
3616 | + return port_dict |
3617 | + except Exception, exc: |
3618 | + raise Exception("Failed to unplug interface: %s" % str(exc)) |
3619 | + |
3620 | + |
3621 | +class L2networkDBTest(unittest.TestCase): |
3622 | + """Class conisting of L2network DB unit tests""" |
3623 | + def setUp(self): |
3624 | + """Setup for tests""" |
3625 | + l2network_db.initialize() |
3626 | + self.dbtest = L2networkDB() |
3627 | + self.quantum = QuantumDB() |
3628 | + LOG.debug("Setup") |
3629 | + |
3630 | + def tearDown(self): |
3631 | + """Tear Down""" |
3632 | + db.clear_db() |
3633 | + |
3634 | + def testa_create_vlanbinding(self): |
3635 | + """test add vlan binding""" |
3636 | + net1 = self.quantum.create_network("t1", "netid1") |
3637 | + vlan1 = self.dbtest.create_vlan_binding(10, "vlan1", net1["net-id"]) |
3638 | + self.assertTrue(vlan1["vlan-id"] == "10") |
3639 | + self.teardown_vlanbinding() |
3640 | + self.teardown_network() |
3641 | + |
3642 | + def testb_getall_vlanbindings(self): |
3643 | + """test get all vlan binding""" |
3644 | + net1 = self.quantum.create_network("t1", "netid1") |
3645 | + net2 = self.quantum.create_network("t1", "netid2") |
3646 | + vlan1 = self.dbtest.create_vlan_binding(10, "vlan1", net1["net-id"]) |
3647 | + self.assertTrue(vlan1["vlan-id"] == "10") |
3648 | + vlan2 = self.dbtest.create_vlan_binding(20, "vlan2", net2["net-id"]) |
3649 | + self.assertTrue(vlan2["vlan-id"] == "20") |
3650 | + vlans = self.dbtest.get_all_vlan_bindings() |
3651 | + count = 0 |
3652 | + for vlan in vlans: |
3653 | + if "vlan" in vlan["vlan-name"]: |
3654 | + count += 1 |
3655 | + self.assertTrue(count == 2) |
3656 | + self.teardown_vlanbinding() |
3657 | + self.teardown_network() |
3658 | + |
3659 | + def testc_delete_vlanbinding(self): |
3660 | + """test delete vlan binding""" |
3661 | + net1 = self.quantum.create_network("t1", "netid1") |
3662 | + vlan1 = self.dbtest.create_vlan_binding(10, "vlan1", net1["net-id"]) |
3663 | + self.assertTrue(vlan1["vlan-id"] == "10") |
3664 | + self.dbtest.delete_vlan_binding(net1["net-id"]) |
3665 | + vlans = self.dbtest.get_all_vlan_bindings() |
3666 | + count = 0 |
3667 | + for vlan in vlans: |
3668 | + if "vlan " in vlan["vlan-name"]: |
3669 | + count += 1 |
3670 | + self.assertTrue(count == 0) |
3671 | + self.teardown_vlanbinding() |
3672 | + self.teardown_network() |
3673 | + |
3674 | + def testd_update_vlanbinding(self): |
3675 | + """test update vlan binding""" |
3676 | + net1 = self.quantum.create_network("t1", "netid1") |
3677 | + vlan1 = self.dbtest.create_vlan_binding(10, "vlan1", net1["net-id"]) |
3678 | + self.assertTrue(vlan1["vlan-id"] == "10") |
3679 | + vlan1 = self.dbtest.update_vlan_binding(net1["net-id"], 11, "newvlan1") |
3680 | + vlans = self.dbtest.get_all_vlan_bindings() |
3681 | + count = 0 |
3682 | + for vlan in vlans: |
3683 | + if "new" in vlan["vlan-name"]: |
3684 | + count += 1 |
3685 | + self.assertTrue(count == 1) |
3686 | + self.teardown_vlanbinding() |
3687 | + self.teardown_network() |
3688 | + |
3689 | + def teste_create_portprofile(self): |
3690 | + """test add port profile""" |
3691 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3692 | + self.assertTrue(pp1["portprofile-name"] == "portprofile1") |
3693 | + self.teardown_portprofile() |
3694 | + self.teardown_network() |
3695 | + |
3696 | + def testf_getall_portprofile(self): |
3697 | + """test get all portprofiles""" |
3698 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3699 | + self.assertTrue(pp1["portprofile-name"] == "portprofile1") |
3700 | + pp2 = self.dbtest.create_portprofile("t1", "portprofile2", 20, "qos2") |
3701 | + self.assertTrue(pp2["portprofile-name"] == "portprofile2") |
3702 | + pps = self.dbtest.get_all_portprofiles() |
3703 | + count = 0 |
3704 | + for pprofile in pps: |
3705 | + if "portprofile" in pprofile["portprofile-name"]: |
3706 | + count += 1 |
3707 | + self.assertTrue(count == 2) |
3708 | + self.teardown_portprofile() |
3709 | + |
3710 | + def testg_delete_portprofile(self): |
3711 | + """test delete portprofile""" |
3712 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3713 | + self.assertTrue(pp1["portprofile-name"] == "portprofile1") |
3714 | + self.dbtest.delete_portprofile("t1", pp1["portprofile-id"]) |
3715 | + pps = self.dbtest.get_all_portprofiles() |
3716 | + count = 0 |
3717 | + for pprofile in pps: |
3718 | + if "portprofile " in pprofile["portprofile-name"]: |
3719 | + count += 1 |
3720 | + self.assertTrue(count == 0) |
3721 | + self.teardown_portprofile() |
3722 | + |
3723 | + def testh_update_portprofile(self): |
3724 | + """test update portprofile""" |
3725 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3726 | + self.assertTrue(pp1["portprofile-name"] == "portprofile1") |
3727 | + pp1 = self.dbtest.update_portprofile("t1", pp1["portprofile-id"], \ |
3728 | + "newportprofile1", 20, "qos2") |
3729 | + pps = self.dbtest.get_all_portprofiles() |
3730 | + count = 0 |
3731 | + for pprofile in pps: |
3732 | + if "new" in pprofile["portprofile-name"]: |
3733 | + count += 1 |
3734 | + self.assertTrue(count == 1) |
3735 | + self.teardown_portprofile() |
3736 | + |
3737 | + def testi_create_portprofilebinding(self): |
3738 | + """test create portprofile binding""" |
3739 | + net1 = self.quantum.create_network("t1", "netid1") |
3740 | + port1 = self.quantum.create_port(net1["net-id"]) |
3741 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3742 | + pp_binding1 = self.dbtest.create_pp_binding("t1", port1["port-id"], \ |
3743 | + pp1["portprofile-id"], "0") |
3744 | + self.assertTrue(pp_binding1["tenant-id"] == "t1") |
3745 | + self.teardown_portprofilebinding() |
3746 | + self.teardown_port() |
3747 | + self.teardown_network() |
3748 | + self.teardown_portprofile() |
3749 | + |
3750 | + def testj_getall_portprofilebinding(self): |
3751 | + """test get all portprofile binding""" |
3752 | + net1 = self.quantum.create_network("t1", "netid1") |
3753 | + port1 = self.quantum.create_port(net1["net-id"]) |
3754 | + port2 = self.quantum.create_port(net1["net-id"]) |
3755 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3756 | + pp2 = self.dbtest.create_portprofile("t1", "portprofile2", 20, "qos2") |
3757 | + pp_binding1 = self.dbtest.create_pp_binding("t1", port1["port-id"], \ |
3758 | + pp1["portprofile-id"], "0") |
3759 | + self.assertTrue(pp_binding1["tenant-id"] == "t1") |
3760 | + pp_binding2 = self.dbtest.create_pp_binding("t1", port2["port-id"], \ |
3761 | + pp2["portprofile-id"], "0") |
3762 | + self.assertTrue(pp_binding2["tenant-id"] == "t1") |
3763 | + pp_bindings = self.dbtest.get_all_pp_bindings() |
3764 | + count = 0 |
3765 | + for pp_bind in pp_bindings: |
3766 | + if "t1" in pp_bind["tenant-id"]: |
3767 | + count += 1 |
3768 | + self.assertTrue(count == 2) |
3769 | + self.teardown_portprofilebinding() |
3770 | + self.teardown_port() |
3771 | + self.teardown_network() |
3772 | + self.teardown_portprofile() |
3773 | + |
3774 | + def testk_delete_portprofilebinding(self): |
3775 | + """test delete portprofile binding""" |
3776 | + net1 = self.quantum.create_network("t1", "netid1") |
3777 | + port1 = self.quantum.create_port(net1["net-id"]) |
3778 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3779 | + pp_binding1 = self.dbtest.create_pp_binding("t1", port1["port-id"], \ |
3780 | + pp1["portprofile-id"], "0") |
3781 | + self.assertTrue(pp_binding1["tenant-id"] == "t1") |
3782 | + self.dbtest.delete_pp_binding("t1", port1["port-id"], \ |
3783 | + pp_binding1["portprofile-id"]) |
3784 | + pp_bindings = self.dbtest.get_all_pp_bindings() |
3785 | + count = 0 |
3786 | + for pp_bind in pp_bindings: |
3787 | + if "t1 " in pp_bind["tenant-id"]: |
3788 | + count += 1 |
3789 | + self.assertTrue(count == 0) |
3790 | + self.teardown_portprofilebinding() |
3791 | + self.teardown_port() |
3792 | + self.teardown_network() |
3793 | + self.teardown_portprofile() |
3794 | + |
3795 | + def testl_update_portprofilebinding(self): |
3796 | + """test update portprofile binding""" |
3797 | + net1 = self.quantum.create_network("t1", "netid1") |
3798 | + port1 = self.quantum.create_port(net1["net-id"]) |
3799 | + pp1 = self.dbtest.create_portprofile("t1", "portprofile1", 10, "qos1") |
3800 | + pp_binding1 = self.dbtest.create_pp_binding("t1", port1["port-id"], \ |
3801 | + pp1["portprofile-id"], "0") |
3802 | + self.assertTrue(pp_binding1["tenant-id"] == "t1") |
3803 | + pp_binding1 = self.dbtest.update_pp_binding("t1", \ |
3804 | + pp1["portprofile-id"], "newt1", port1["port-id"], "1") |
3805 | + pp_bindings = self.dbtest.get_all_pp_bindings() |
3806 | + count = 0 |
3807 | + for pp_bind in pp_bindings: |
3808 | + if "new" in pp_bind["tenant-id"]: |
3809 | + count += 1 |
3810 | + self.assertTrue(count == 1) |
3811 | + self.teardown_portprofilebinding() |
3812 | + self.teardown_port() |
3813 | + self.teardown_network() |
3814 | + self.teardown_portprofile() |
3815 | + |
3816 | + def testm_test_vlanids(self): |
3817 | + """test vlanid methods""" |
3818 | + l2network_db.create_vlanids() |
3819 | + vlanids = l2network_db.get_all_vlanids() |
3820 | + self.assertTrue(len(vlanids) > 0) |
3821 | + vlanid = l2network_db.reserve_vlanid() |
3822 | + used = l2network_db.is_vlanid_used(vlanid) |
3823 | + self.assertTrue(used == True) |
3824 | + used = l2network_db.release_vlanid(vlanid) |
3825 | + self.assertTrue(used == False) |
3826 | + self.teardown_vlanid() |
3827 | + |
3828 | + def teardown_network(self): |
3829 | + """tearDown Network table""" |
3830 | + LOG.debug("Tearing Down Network") |
3831 | + nets = self.quantum.get_all_networks("t1") |
3832 | + for net in nets: |
3833 | + netid = net["net-id"] |
3834 | + self.quantum.delete_network(netid) |
3835 | + |
3836 | + def teardown_port(self): |
3837 | + """tearDown Port table""" |
3838 | + LOG.debug("Tearing Down Port") |
3839 | + nets = self.quantum.get_all_networks("t1") |
3840 | + for net in nets: |
3841 | + netid = net["net-id"] |
3842 | + ports = self.quantum.get_all_ports(netid) |
3843 | + for port in ports: |
3844 | + portid = port["port-id"] |
3845 | + self.quantum.delete_port(netid, portid) |
3846 | + |
3847 | + def teardown_vlanbinding(self): |
3848 | + """tearDown VlanBinding table""" |
3849 | + LOG.debug("Tearing Down Vlan Binding") |
3850 | + vlans = self.dbtest.get_all_vlan_bindings() |
3851 | + for vlan in vlans: |
3852 | + netid = vlan["net-id"] |
3853 | + self.dbtest.delete_vlan_binding(netid) |
3854 | + |
3855 | + def teardown_portprofile(self): |
3856 | + """tearDown PortProfile table""" |
3857 | + LOG.debug("Tearing Down Port Profile") |
3858 | + pps = self.dbtest.get_all_portprofiles() |
3859 | + for pprofile in pps: |
3860 | + ppid = pprofile["portprofile-id"] |
3861 | + self.dbtest.delete_portprofile("t1", ppid) |
3862 | + |
3863 | + def teardown_portprofilebinding(self): |
3864 | + """tearDown PortProfileBinding table""" |
3865 | + LOG.debug("Tearing Down Port Profile Binding") |
3866 | + pp_bindings = self.dbtest.get_all_pp_bindings() |
3867 | + for pp_binding in pp_bindings: |
3868 | + ppid = pp_binding["portprofile-id"] |
3869 | + portid = pp_binding["port-id"] |
3870 | + self.dbtest.delete_pp_binding("t1", portid, ppid) |
3871 | + |
3872 | + def teardown_vlanid(self): |
3873 | + """tearDown VlanID table""" |
3874 | + LOG.debug("Tearing Down Vlan IDs") |
3875 | + vlanids = l2network_db.get_all_vlanids() |
3876 | + for vlanid in vlanids: |
3877 | + vlan_id = vlanid["vlan_id"] |
3878 | + l2network_db.delete_vlanid(vlan_id) |
3879 | + |
3880 | + |
3881 | +class QuantumDBTest(unittest.TestCase): |
3882 | + """Class conisting of Quantum DB unit tests""" |
3883 | + def setUp(self): |
3884 | + """Setup for tests""" |
3885 | + l2network_db.initialize() |
3886 | + self.dbtest = QuantumDB() |
3887 | + self.tenant_id = "t1" |
3888 | + LOG.debug("Setup") |
3889 | + |
3890 | + def tearDown(self): |
3891 | + """Tear Down""" |
3892 | + db.clear_db() |
3893 | + |
3894 | + def testa_create_network(self): |
3895 | + """test to create network""" |
3896 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3897 | + self.assertTrue(net1["net-name"] == "plugin_test1") |
3898 | + self.teardown_network_port() |
3899 | + |
3900 | + def testb_get_networks(self): |
3901 | + """test to get all networks""" |
3902 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3903 | + self.assertTrue(net1["net-name"] == "plugin_test1") |
3904 | + net2 = self.dbtest.create_network(self.tenant_id, "plugin_test2") |
3905 | + self.assertTrue(net2["net-name"] == "plugin_test2") |
3906 | + nets = self.dbtest.get_all_networks(self.tenant_id) |
3907 | + count = 0 |
3908 | + for net in nets: |
3909 | + if "plugin_test" in net["net-name"]: |
3910 | + count += 1 |
3911 | + self.assertTrue(count == 2) |
3912 | + self.teardown_network_port() |
3913 | + |
3914 | + def testc_delete_network(self): |
3915 | + """test to delete network""" |
3916 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3917 | + self.assertTrue(net1["net-name"] == "plugin_test1") |
3918 | + self.dbtest.delete_network(net1["net-id"]) |
3919 | + nets = self.dbtest.get_all_networks(self.tenant_id) |
3920 | + count = 0 |
3921 | + for net in nets: |
3922 | + if "plugin_test1" in net["net-name"]: |
3923 | + count += 1 |
3924 | + self.assertTrue(count == 0) |
3925 | + self.teardown_network_port() |
3926 | + |
3927 | + def testd_rename_network(self): |
3928 | + """test to rename network""" |
3929 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3930 | + self.assertTrue(net1["net-name"] == "plugin_test1") |
3931 | + net = self.dbtest.rename_network(self.tenant_id, net1["net-id"], |
3932 | + "plugin_test1_renamed") |
3933 | + self.assertTrue(net["net-name"] == "plugin_test1_renamed") |
3934 | + self.teardown_network_port() |
3935 | + |
3936 | + def teste_create_port(self): |
3937 | + """test to create port""" |
3938 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3939 | + port = self.dbtest.create_port(net1["net-id"]) |
3940 | + self.assertTrue(port["net-id"] == net1["net-id"]) |
3941 | + ports = self.dbtest.get_all_ports(net1["net-id"]) |
3942 | + count = 0 |
3943 | + for por in ports: |
3944 | + count += 1 |
3945 | + self.assertTrue(count == 1) |
3946 | + self.teardown_network_port() |
3947 | + |
3948 | + def testf_delete_port(self): |
3949 | + """test to delete port""" |
3950 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3951 | + port = self.dbtest.create_port(net1["net-id"]) |
3952 | + self.assertTrue(port["net-id"] == net1["net-id"]) |
3953 | + ports = self.dbtest.get_all_ports(net1["net-id"]) |
3954 | + count = 0 |
3955 | + for por in ports: |
3956 | + count += 1 |
3957 | + self.assertTrue(count == 1) |
3958 | + for por in ports: |
3959 | + self.dbtest.delete_port(net1["net-id"], por["port-id"]) |
3960 | + ports = self.dbtest.get_all_ports(net1["net-id"]) |
3961 | + count = 0 |
3962 | + for por in ports: |
3963 | + count += 1 |
3964 | + self.assertTrue(count == 0) |
3965 | + self.teardown_network_port() |
3966 | + |
3967 | + def testg_plug_unplug_interface(self): |
3968 | + """test to plug/unplug interface""" |
3969 | + net1 = self.dbtest.create_network(self.tenant_id, "plugin_test1") |
3970 | + port1 = self.dbtest.create_port(net1["net-id"]) |
3971 | + self.dbtest.plug_interface(net1["net-id"], port1["port-id"], "vif1.1") |
3972 | + port = self.dbtest.get_port(net1["net-id"], port1["port-id"]) |
3973 | + self.assertTrue(port[0]["int-id"] == "vif1.1") |
3974 | + self.dbtest.unplug_interface(net1["net-id"], port1["port-id"]) |
3975 | + port = self.dbtest.get_port(net1["net-id"], port1["port-id"]) |
3976 | + self.assertTrue(port[0]["int-id"] == None) |
3977 | + self.teardown_network_port() |
3978 | + |
3979 | + def testh_joined_test(self): |
3980 | + """test to get network and port""" |
3981 | + net1 = self.dbtest.create_network("t1", "net1") |
3982 | + port1 = self.dbtest.create_port(net1["net-id"]) |
3983 | + self.assertTrue(port1["net-id"] == net1["net-id"]) |
3984 | + port2 = self.dbtest.create_port(net1["net-id"]) |
3985 | + self.assertTrue(port2["net-id"] == net1["net-id"]) |
3986 | + ports = self.dbtest.get_all_ports(net1["net-id"]) |
3987 | + for port in ports: |
3988 | + net = port["net"] |
3989 | + LOG.debug("Port id %s Net id %s" % (port["port-id"], net.uuid)) |
3990 | + self.teardown_joined_test() |
3991 | + |
3992 | + def teardown_network_port(self): |
3993 | + """tearDown for Network and Port table""" |
3994 | + networks = self.dbtest.get_all_networks(self.tenant_id) |
3995 | + for net in networks: |
3996 | + netid = net["net-id"] |
3997 | + name = net["net-name"] |
3998 | + if "plugin_test" in name: |
3999 | + ports = self.dbtest.get_all_ports(netid) |
4000 | + for por in ports: |
4001 | + self.dbtest.delete_port(netid, por["port-id"]) |
4002 | + self.dbtest.delete_network(netid) |
4003 | + |
4004 | + def teardown_joined_test(self): |
4005 | + """tearDown for joined Network and Port test""" |
4006 | + LOG.debug("Tearing Down Network and Ports") |
4007 | + nets = self.dbtest.get_all_networks("t1") |
4008 | + for net in nets: |
4009 | + netid = net["net-id"] |
4010 | + ports = self.dbtest.get_all_ports(netid) |
4011 | + for port in ports: |
4012 | + self.dbtest.delete_port(port["net-id"], port["port-id"]) |
4013 | + self.dbtest.delete_network(netid) |
4014 | + |
4015 | +""" |
4016 | +if __name__ == "__main__": |
4017 | + usagestr = "Usage: %prog [OPTIONS] <command> [args]" |
4018 | + parser = OptionParser(usage=usagestr) |
4019 | + parser.add_option("-v", "--verbose", dest="verbose", |
4020 | + action="store_true", default=False, help="turn on verbose logging") |
4021 | + |
4022 | + options, args = parser.parse_args() |
4023 | + |
4024 | + if options.verbose: |
4025 | + LOG.basicConfig(level=LOG.DEBUG) |
4026 | + else: |
4027 | + LOG.basicConfig(level=LOG.WARN) |
4028 | + |
4029 | + l2network_db.initialize() |
4030 | + |
4031 | + # Run the tests |
4032 | + suite = unittest.TestLoader().loadTestsFromTestCase(QuantumDBTest) |
4033 | + unittest.TextTestRunner(verbosity=2).run(suite) |
4034 | + suite = unittest.TestLoader().loadTestsFromTestCase(L2networkDBTest) |
4035 | + unittest.TextTestRunner(verbosity=2).run(suite) |
4036 | +""" |
4037 | |
4038 | === modified file 'quantum/plugins/cisco/tests/unit/test_l2networkApi.py' |
4039 | --- quantum/plugins/cisco/tests/unit/test_l2networkApi.py 2011-08-08 07:23:44 +0000 |
4040 | +++ quantum/plugins/cisco/tests/unit/test_l2networkApi.py 2011-08-23 20:09:26 +0000 |
4041 | @@ -24,6 +24,8 @@ |
4042 | from quantum.plugins.cisco.common import cisco_exceptions as cexc |
4043 | from quantum.plugins.cisco import l2network_plugin |
4044 | from quantum.plugins.cisco import l2network_plugin_configuration as conf |
4045 | +from quantum.plugins.cisco.db import api as db |
4046 | +from quantum.plugins.cisco.db import l2network_db as cdb |
4047 | |
4048 | LOG = logging.getLogger('quantum.tests.test_core_api_func') |
4049 | |
4050 | @@ -47,6 +49,8 @@ |
4051 | network_name = self.network_name |
4052 | new_net_dict = self._l2network_plugin.create_network( |
4053 | tenant_id, network_name) |
4054 | + net = db.network_get(new_net_dict[const.NET_ID]) |
4055 | + self.assertEqual(net[const.NETWORKNAME], network_name) |
4056 | self.assertEqual(new_net_dict[const.NET_NAME], network_name) |
4057 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4058 | LOG.debug("test_create_network - END") |
4059 | @@ -64,6 +68,8 @@ |
4060 | tenant_id, self.network_name) |
4061 | delete_net_dict = self._l2network_plugin.delete_network( |
4062 | tenant_id, new_net_dict[const.NET_ID]) |
4063 | + self.assertRaises(exc.NetworkNotFound, db.network_get, |
4064 | + new_net_dict[const.NET_ID]) |
4065 | self.assertEqual( |
4066 | new_net_dict[const.NET_ID], delete_net_dict[const.NET_ID]) |
4067 | LOG.debug("test_delete_network - END") |
4068 | @@ -117,6 +123,8 @@ |
4069 | tenant_id, self.network_name) |
4070 | result_net_dict = self._l2network_plugin.get_network_details( |
4071 | tenant_id, new_net_dict[const.NET_ID]) |
4072 | + net = db.network_get(new_net_dict[const.NET_ID]) |
4073 | + self.assertEqual(net[const.UUID], new_net_dict[const.NET_ID]) |
4074 | self.assertEqual( |
4075 | new_net_dict[const.NET_ID], result_net_dict[const.NET_ID]) |
4076 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4077 | @@ -152,6 +160,8 @@ |
4078 | tenant_id, self.network_name) |
4079 | rename_net_dict = self._l2network_plugin.rename_network( |
4080 | tenant_id, new_net_dict[const.NET_ID], new_name) |
4081 | + net = db.network_get(new_net_dict[const.NET_ID]) |
4082 | + self.assertEqual(net[const.NETWORKNAME], new_name) |
4083 | self.assertEqual(new_name, rename_net_dict[const.NET_NAME]) |
4084 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4085 | LOG.debug("test_rename_network - END") |
4086 | @@ -184,9 +194,18 @@ |
4087 | tenant_id, 'test_net2') |
4088 | net_list = self._l2network_plugin.get_all_networks(tenant_id) |
4089 | net_temp_list = [new_net_dict, new_net_dict2] |
4090 | + networks_list = db.network_list(tenant_id) |
4091 | + new_networks_list = [] |
4092 | + for network in networks_list: |
4093 | + new_network_dict = self._make_net_dict(network[const.UUID], |
4094 | + network[const.NETWORKNAME], |
4095 | + []) |
4096 | + new_networks_list.append(new_network_dict) |
4097 | self.assertEqual(len(net_list), 2) |
4098 | self.assertTrue(net_list[0] in net_temp_list) |
4099 | self.assertTrue(net_list[1] in net_temp_list) |
4100 | + self.assertTrue(new_networks_list[0] in net_temp_list) |
4101 | + self.assertTrue(new_networks_list[1] in net_temp_list) |
4102 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4103 | self.tearDownNetwork(tenant_id, new_net_dict2[const.NET_ID]) |
4104 | LOG.debug("test_list_networks - END") |
4105 | @@ -206,9 +225,20 @@ |
4106 | port_list = self._l2network_plugin.get_all_ports( |
4107 | tenant_id, new_net_dict[const.NET_ID]) |
4108 | port_temp_list = [port_dict, port_dict2] |
4109 | + network = db.network_get(new_net_dict[const.NET_ID]) |
4110 | + ports_list = network[const.NETWORKPORTS] |
4111 | + ports_on_net = [] |
4112 | + for port in ports_list: |
4113 | + new_port = self._make_port_dict(port[const.UUID], |
4114 | + port[const.PORTSTATE], |
4115 | + port[const.NETWORKID], |
4116 | + port[const.INTERFACEID]) |
4117 | + ports_on_net.append(new_port) |
4118 | self.assertEqual(len(port_list), 2) |
4119 | self.assertTrue(port_list[0] in port_temp_list) |
4120 | self.assertTrue(port_list[1] in port_temp_list) |
4121 | + self.assertTrue(ports_on_net[0] in port_temp_list) |
4122 | + self.assertTrue(ports_on_net[1] in port_temp_list) |
4123 | |
4124 | self.tearDownPortOnly(tenant_id, new_net_dict[const.NET_ID], |
4125 | port_dict[const.PORT_ID]) |
4126 | @@ -227,7 +257,12 @@ |
4127 | tenant_id, self.network_name) |
4128 | port_dict = self._l2network_plugin.create_port( |
4129 | tenant_id, new_net_dict[const.NET_ID], port_state) |
4130 | + port = db.port_get(new_net_dict[const.NET_ID], |
4131 | + port_dict[const.PORT_ID]) |
4132 | self.assertEqual(port_dict[const.PORT_STATE], port_state) |
4133 | + self.assertEqual(port_dict[const.NET_ID], new_net_dict[const.NET_ID]) |
4134 | + self.assertEqual(port[const.PORTSTATE], port_state) |
4135 | + self.assertEqual(port[const.NETWORKID], new_net_dict[const.NET_ID]) |
4136 | self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID], |
4137 | port_dict[const.PORT_ID]) |
4138 | LOG.debug("test_create_port - END") |
4139 | @@ -263,8 +298,11 @@ |
4140 | delete_port_dict = self._l2network_plugin.delete_port( |
4141 | tenant_id, new_net_dict[const.NET_ID], |
4142 | port_dict[const.PORT_ID]) |
4143 | + self.assertRaises(exc.PortNotFound, db.port_get, |
4144 | + new_net_dict[const.NET_ID], port_dict[const.PORT_ID]) |
4145 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4146 | - self.assertEqual(delete_port_dict, None) |
4147 | + self.assertEqual(delete_port_dict[const.PORT_ID], |
4148 | + port_dict[const.PORT_ID]) |
4149 | LOG.debug("test_delete_port - END") |
4150 | |
4151 | def test_delete_port_networkDNE(self, tenant_id='test_tenant', |
4152 | @@ -327,6 +365,9 @@ |
4153 | update_port_dict = self._l2network_plugin.update_port( |
4154 | tenant_id, new_net_dict[const.NET_ID], |
4155 | port_dict[const.PORT_ID], port_state) |
4156 | + new_port = db.port_get(new_net_dict[const.NET_ID], |
4157 | + port_dict[const.PORT_ID]) |
4158 | + self.assertEqual(new_port[const.PORTSTATE], port_state) |
4159 | self.assertEqual(update_port_dict[const.PORT_STATE], port_state) |
4160 | self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID], |
4161 | port_dict[const.PORT_ID]) |
4162 | @@ -341,7 +382,7 @@ |
4163 | LOG.debug("test_update_port_networkDNE - START") |
4164 | self.assertRaises(exc.NetworkNotFound, |
4165 | self._l2network_plugin.update_port, tenant_id, |
4166 | - net_id, port_id, self.port_state) |
4167 | + net_id, port_id, const.PORT_UP) |
4168 | LOG.debug("test_update_port_networkDNE - END") |
4169 | |
4170 | def test_update_portDNE(self, tenant_id='test_tenant', port_id='p0005'): |
4171 | @@ -354,7 +395,7 @@ |
4172 | tenant_id, self.network_name) |
4173 | self.assertRaises( |
4174 | exc.PortNotFound, self._l2network_plugin.update_port, tenant_id, |
4175 | - new_net_dict[const.NET_ID], port_id, self.port_state) |
4176 | + new_net_dict[const.NET_ID], port_id, const.PORT_UP) |
4177 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4178 | LOG.debug("test_update_portDNE - END") |
4179 | |
4180 | @@ -371,6 +412,9 @@ |
4181 | get_port_dict = self._l2network_plugin.get_port_details( |
4182 | tenant_id, new_net_dict[const.NET_ID], |
4183 | port_dict[const.PORT_ID]) |
4184 | + port = db.port_get(new_net_dict[const.NET_ID], |
4185 | + port_dict[const.PORT_ID]) |
4186 | + self.assertEqual(port[const.PORTSTATE], self.port_state) |
4187 | self.assertEqual(get_port_dict[const.PORT_STATE], self.port_state) |
4188 | self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID], |
4189 | port_dict[const.PORT_ID]) |
4190 | @@ -416,10 +460,9 @@ |
4191 | self._l2network_plugin.plug_interface( |
4192 | tenant_id, new_net_dict[const.NET_ID], |
4193 | port_dict[const.PORT_ID], remote_interface) |
4194 | - self.assertEqual( |
4195 | - self._l2network_plugin._networks[new_net_dict[const.NET_ID]] |
4196 | - [const.NET_PORTS][port_dict[const.PORT_ID]] |
4197 | - [const.ATTACHMENT], remote_interface) |
4198 | + port = db.port_get(new_net_dict[const.NET_ID], |
4199 | + port_dict[const.PORT_ID]) |
4200 | + self.assertEqual(port[const.INTERFACEID], remote_interface) |
4201 | self.tearDownNetworkPortInterface( |
4202 | tenant_id, new_net_dict[const.NET_ID], |
4203 | port_dict[const.PORT_ID]) |
4204 | @@ -470,7 +513,7 @@ |
4205 | self._l2network_plugin.plug_interface( |
4206 | tenant_id, new_net_dict[const.NET_ID], |
4207 | port_dict[const.PORT_ID], remote_interface) |
4208 | - self.assertRaises(exc.AlreadyAttached, |
4209 | + self.assertRaises(exc.PortInUse, |
4210 | self._l2network_plugin.plug_interface, tenant_id, |
4211 | new_net_dict[const.NET_ID], |
4212 | port_dict[const.PORT_ID], remote_interface) |
4213 | @@ -496,9 +539,9 @@ |
4214 | self._l2network_plugin.unplug_interface( |
4215 | tenant_id, new_net_dict[const.NET_ID], |
4216 | port_dict[const.PORT_ID]) |
4217 | - self.assertEqual(self._l2network_plugin._networks |
4218 | - [new_net_dict[const.NET_ID]][const.NET_PORTS] |
4219 | - [port_dict[const.PORT_ID]][const.ATTACHMENT], None) |
4220 | + port = db.port_get(new_net_dict[const.NET_ID], |
4221 | + port_dict[const.PORT_ID]) |
4222 | + self.assertEqual(port[const.INTERFACEID], None) |
4223 | self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID], |
4224 | port_dict[const.PORT_ID]) |
4225 | LOG.debug("test_unplug_interface - END") |
4226 | @@ -533,7 +576,7 @@ |
4227 | LOG.debug("test_unplug_interface_portDNE - END") |
4228 | |
4229 | def test_create_portprofile(self, net_tenant_id=None, |
4230 | - net_profile_name=None, net_vlan_id=None): |
4231 | + net_profile_name=None, net_qos=None): |
4232 | """ |
4233 | Tests creation of a port-profile |
4234 | """ |
4235 | @@ -548,19 +591,16 @@ |
4236 | profile_name = net_profile_name |
4237 | else: |
4238 | profile_name = self.profile_name |
4239 | - if net_vlan_id: |
4240 | - vlan_id = net_vlan_id |
4241 | + if net_qos: |
4242 | + qos = net_qos |
4243 | else: |
4244 | - vlan_id = self.vlan_id |
4245 | + qos = self.qos |
4246 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4247 | - tenant_id, profile_name, vlan_id) |
4248 | + tenant_id, profile_name, qos) |
4249 | port_profile_id = port_profile_dict['profile-id'] |
4250 | - self.assertEqual( |
4251 | - self._l2network_plugin._portprofiles[port_profile_id]['vlan-id'], |
4252 | - vlan_id) |
4253 | - self.assertEqual( |
4254 | - self._l2network_plugin._portprofiles[port_profile_id] |
4255 | - ['profile-name'], profile_name) |
4256 | + port_profile = cdb.get_portprofile(tenant_id, port_profile_id) |
4257 | + self.assertEqual(port_profile[const.PPNAME], profile_name) |
4258 | + self.assertEqual(port_profile[const.PPQOS], qos) |
4259 | self.tearDownPortProfile(tenant_id, port_profile_id) |
4260 | LOG.debug("test_create_portprofile - tenant id: %s - END", |
4261 | net_tenant_id) |
4262 | @@ -577,10 +617,10 @@ |
4263 | else: |
4264 | tenant_id = self.tenant_id |
4265 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4266 | - tenant_id, self.profile_name, self.vlan_id) |
4267 | + tenant_id, self.profile_name, self.qos) |
4268 | port_profile_id = port_profile_dict['profile-id'] |
4269 | self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id) |
4270 | - self.assertEqual(self._l2network_plugin._portprofiles, {}) |
4271 | + self.assertRaises(Exception, cdb.get_portprofile, port_profile_id) |
4272 | LOG.debug("test_delete_portprofile - tenant id: %s - END", |
4273 | net_tenant_id) |
4274 | |
4275 | @@ -604,15 +644,23 @@ |
4276 | |
4277 | LOG.debug("test_delete_portprofileAssociated - START") |
4278 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4279 | - tenant_id, self.profile_name, self.vlan_id) |
4280 | + tenant_id, self.profile_name, self.qos) |
4281 | port_profile_id = port_profile_dict['profile-id'] |
4282 | + new_net_dict = self._l2network_plugin.create_network( |
4283 | + tenant_id, 'test_network') |
4284 | + port_dict = self._l2network_plugin.create_port( |
4285 | + tenant_id, new_net_dict[const.NET_ID], 'const.PORT_UP') |
4286 | self._l2network_plugin.associate_portprofile( |
4287 | - tenant_id, self.net_id, self.port_id, port_profile_id) |
4288 | + tenant_id, new_net_dict[const.NET_ID], |
4289 | + port_dict[const.PORT_ID], port_profile_id) |
4290 | self.assertRaises(cexc.PortProfileInvalidDelete, |
4291 | self._l2network_plugin.delete_portprofile, |
4292 | tenant_id, port_profile_id) |
4293 | - self.tearDownAssociatePortProfile(tenant_id, self.net_id, |
4294 | - self.port_id, port_profile_id) |
4295 | + self.tearDownAssociatePortProfile( |
4296 | + tenant_id, new_net_dict[const.NET_ID], |
4297 | + port_dict[const.PORT_ID], port_profile_id) |
4298 | + self.tearDownNetworkPort(tenant_id, new_net_dict[const.NET_ID], |
4299 | + port_dict[const.PORT_ID]) |
4300 | LOG.debug("test_delete_portprofileAssociated - END") |
4301 | |
4302 | def test_list_portprofile(self, tenant_id='test_tenant'): |
4303 | @@ -622,24 +670,30 @@ |
4304 | |
4305 | LOG.debug("test_list_portprofile - tenant id: %s - START", tenant_id) |
4306 | profile_name2 = tenant_id + '_port_profile2' |
4307 | - vlan_id2 = tenant_id + '201' |
4308 | + qos2 = tenant_id + 'qos2' |
4309 | port_profile_dict1 = self._l2network_plugin.create_portprofile( |
4310 | - tenant_id, self.profile_name, self.vlan_id) |
4311 | + tenant_id, self.profile_name, self.qos) |
4312 | port_profile_dict2 = self._l2network_plugin.create_portprofile( |
4313 | - tenant_id, profile_name2, vlan_id2) |
4314 | + tenant_id, profile_name2, qos2) |
4315 | port_profile_id1 = port_profile_dict1['profile-id'] |
4316 | port_profile_id2 = port_profile_dict2['profile-id'] |
4317 | list_all_portprofiles = self._l2network_plugin.get_all_portprofiles( |
4318 | tenant_id) |
4319 | - self.assertEqual(self._l2network_plugin._portprofiles |
4320 | - [port_profile_id1]['vlan-id'], self.vlan_id) |
4321 | - self.assertEqual(self._l2network_plugin._portprofiles |
4322 | - [port_profile_id1]['profile-name'], self.profile_name) |
4323 | - self.assertEqual(self._l2network_plugin._portprofiles |
4324 | - [port_profile_id2]['vlan-id'], vlan_id2) |
4325 | - self.assertEqual(self._l2network_plugin._portprofiles |
4326 | - [port_profile_id2]['profile-name'], profile_name2) |
4327 | - LOG.debug("test_create_portprofile - tenant id: %s - END", tenant_id) |
4328 | + port_profile_list = [port_profile_dict1, port_profile_dict2] |
4329 | + pplist = cdb.get_all_portprofiles() |
4330 | + new_pplist = [] |
4331 | + for pp in pplist: |
4332 | + new_pp = self._make_portprofile_dict(tenant_id, |
4333 | + pp[const.UUID], |
4334 | + pp[const.PPNAME], |
4335 | + pp[const.PPQOS]) |
4336 | + new_pplist.append(new_pp) |
4337 | + self.assertTrue(new_pplist[0] in port_profile_list) |
4338 | + self.assertTrue(new_pplist[1] in port_profile_list) |
4339 | + self.tearDownPortProfile(tenant_id, port_profile_id1) |
4340 | + self.tearDownPortProfile(tenant_id, port_profile_id2) |
4341 | + |
4342 | + LOG.debug("test_list_portprofile - tenant id: %s - END", tenant_id) |
4343 | |
4344 | def test_show_portprofile(self, net_tenant_id=None): |
4345 | """ |
4346 | @@ -652,12 +706,15 @@ |
4347 | else: |
4348 | tenant_id = self.tenant_id |
4349 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4350 | - tenant_id, self.profile_name, self.vlan_id) |
4351 | + tenant_id, self.profile_name, self.qos) |
4352 | port_profile_id = port_profile_dict['profile-id'] |
4353 | result_port_profile = self._l2network_plugin.get_portprofile_details( |
4354 | tenant_id, port_profile_id) |
4355 | - self.assertEqual(result_port_profile[const.PROFILE_VLAN_ID], |
4356 | - self.vlan_id) |
4357 | + port_profile = cdb.get_portprofile(tenant_id, port_profile_id) |
4358 | + self.assertEqual(port_profile[const.PPQOS], self.qos) |
4359 | + self.assertEqual(port_profile[const.PPNAME], self.profile_name) |
4360 | + self.assertEqual(result_port_profile[const.PROFILE_QOS], |
4361 | + self.qos) |
4362 | self.assertEqual(result_port_profile[const.PROFILE_NAME], |
4363 | self.profile_name) |
4364 | self.tearDownPortProfile(tenant_id, port_profile_id) |
4365 | @@ -670,7 +727,7 @@ |
4366 | """ |
4367 | |
4368 | LOG.debug("test_show_portprofileDNE - START") |
4369 | - self.assertRaises(cexc.PortProfileNotFound, |
4370 | + self.assertRaises(Exception, |
4371 | self._l2network_plugin.get_portprofile_details, |
4372 | tenant_id, profile_id) |
4373 | LOG.debug("test_show_portprofileDNE - END") |
4374 | @@ -683,10 +740,12 @@ |
4375 | |
4376 | LOG.debug("test_rename_portprofile - START") |
4377 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4378 | - tenant_id, self.profile_name, self.vlan_id) |
4379 | + tenant_id, self.profile_name, self.qos) |
4380 | port_profile_id = port_profile_dict['profile-id'] |
4381 | result_port_profile_dict = self._l2network_plugin.rename_portprofile( |
4382 | tenant_id, port_profile_id, new_profile_name) |
4383 | + port_profile = cdb.get_portprofile(tenant_id, port_profile_id) |
4384 | + self.assertEqual(port_profile[const.PPNAME], new_profile_name) |
4385 | self.assertEqual(result_port_profile_dict[const.PROFILE_NAME], |
4386 | new_profile_name) |
4387 | self.tearDownPortProfile(tenant_id, port_profile_id) |
4388 | @@ -705,23 +764,32 @@ |
4389 | tenant_id, profile_id, new_profile_name) |
4390 | LOG.debug("test_rename_portprofileDNE - END") |
4391 | |
4392 | - def test_associate_portprofile(self, tenant_id='test_tenant', |
4393 | - net_id='0005', port_id='p00005'): |
4394 | + def test_associate_portprofile(self, tenant_id='test_tenant'): |
4395 | """ |
4396 | Tests association of a port-profile |
4397 | """ |
4398 | |
4399 | LOG.debug("test_associate_portprofile - START") |
4400 | + new_net_dict = self._l2network_plugin.create_network( |
4401 | + tenant_id, self.network_name) |
4402 | + port_dict = self._l2network_plugin.create_port( |
4403 | + tenant_id, new_net_dict[const.NET_ID], |
4404 | + self.port_state) |
4405 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4406 | - tenant_id, self.profile_name, self.vlan_id) |
4407 | + tenant_id, self.profile_name, self.qos) |
4408 | port_profile_id = port_profile_dict['profile-id'] |
4409 | self._l2network_plugin.associate_portprofile( |
4410 | - tenant_id, net_id, port_id, port_profile_id) |
4411 | - self.assertEqual( |
4412 | - self._l2network_plugin._portprofiles[port_profile_id] |
4413 | - [const.PROFILE_ASSOCIATIONS][0], port_id) |
4414 | - self.tearDownAssociatePortProfile(tenant_id, net_id, |
4415 | - port_id, port_profile_id) |
4416 | + tenant_id, new_net_dict[const.NET_ID], |
4417 | + port_dict[const.PORT_ID], port_profile_id) |
4418 | + port_profile_associate = cdb.get_pp_binding(tenant_id, port_profile_id) |
4419 | + self.assertEqual(port_profile_associate[const.PORTID], |
4420 | + port_dict[const.PORT_ID]) |
4421 | + self.tearDownAssociatePortProfile( |
4422 | + tenant_id, new_net_dict[const.NET_ID], |
4423 | + port_dict[const.PORT_ID], port_profile_id) |
4424 | + self.tearDownNetworkPort( |
4425 | + tenant_id, new_net_dict[const.NET_ID], |
4426 | + port_dict[const.PORT_ID]) |
4427 | LOG.debug("test_associate_portprofile - END") |
4428 | |
4429 | def test_associate_portprofileDNE(self, tenant_id='test_tenant', |
4430 | @@ -738,22 +806,32 @@ |
4431 | LOG.debug("test_associate_portprofileDNE - END") |
4432 | |
4433 | def test_disassociate_portprofile(self, tenant_id='test_tenant', |
4434 | - net_id='0005', port_id='p00005'): |
4435 | + ): |
4436 | """ |
4437 | Tests disassociation of a port-profile |
4438 | """ |
4439 | |
4440 | LOG.debug("test_disassociate_portprofile - START") |
4441 | + new_net_dict = self._l2network_plugin.create_network( |
4442 | + tenant_id, self.network_name) |
4443 | + port_dict = self._l2network_plugin.create_port( |
4444 | + tenant_id, new_net_dict[const.NET_ID], |
4445 | + self.port_state) |
4446 | port_profile_dict = self._l2network_plugin.create_portprofile( |
4447 | - tenant_id, self.profile_name, self.vlan_id) |
4448 | + tenant_id, self.profile_name, self.qos) |
4449 | port_profile_id = port_profile_dict['profile-id'] |
4450 | - self._l2network_plugin.associate_portprofile(tenant_id, net_id, |
4451 | - port_id, port_profile_id) |
4452 | + self._l2network_plugin.associate_portprofile( |
4453 | + tenant_id, new_net_dict[const.NET_ID], |
4454 | + port_dict[const.PORT_ID], port_profile_id) |
4455 | self._l2network_plugin.disassociate_portprofile( |
4456 | - tenant_id, net_id, port_id, port_profile_id) |
4457 | - self.assertEqual(self._l2network_plugin._portprofiles |
4458 | - [port_profile_id][const.PROFILE_ASSOCIATIONS], []) |
4459 | + tenant_id, new_net_dict[const.NET_ID], |
4460 | + port_dict[const.PORT_ID], port_profile_id) |
4461 | + port_profile_associate = cdb.get_pp_binding(tenant_id, port_profile_id) |
4462 | + self.assertEqual(port_profile_associate, []) |
4463 | self.tearDownPortProfile(tenant_id, port_profile_id) |
4464 | + self.tearDownNetworkPort( |
4465 | + tenant_id, new_net_dict[const.NET_ID], |
4466 | + port_dict[const.PORT_ID]) |
4467 | LOG.debug("test_disassociate_portprofile - END") |
4468 | |
4469 | def test_disassociate_portprofileDNE(self, tenant_id='test_tenant', |
4470 | @@ -768,24 +846,7 @@ |
4471 | tenant_id, net_id, port_id, profile_id) |
4472 | LOG.debug("test_disassociate_portprofileDNE - END") |
4473 | |
4474 | -# def test_disassociate_portprofile_Unassociated |
4475 | - |
4476 | - def test_get_tenant(self, net_tenant_id=None): |
4477 | - """ |
4478 | - Tests get tenant |
4479 | - """ |
4480 | - |
4481 | - LOG.debug("test_get_tenant - START") |
4482 | - if net_tenant_id: |
4483 | - tenant_id = net_tenant_id |
4484 | - else: |
4485 | - tenant_id = self.tenant_id |
4486 | - tenant_dict = self._l2network_plugin._get_tenant(tenant_id) |
4487 | - self.assertEqual(tenant_dict[const.TENANT_ID], tenant_id) |
4488 | - self.assertEqual(tenant_dict[const.TENANT_NAME], tenant_id) |
4489 | - LOG.debug("test_get_tenant - END") |
4490 | - |
4491 | - def test_get_vlan_name(self, net_tenant_id=None, vlan_name="NewVlan", |
4492 | + def test_get_vlan_name(self, net_tenant_id=None, vlan_id="NewVlan", |
4493 | vlan_prefix=conf.VLAN_NAME_PREFIX): |
4494 | """ |
4495 | Tests get vlan name |
4496 | @@ -797,8 +858,8 @@ |
4497 | else: |
4498 | tenant_id = self.tenant_id |
4499 | result_vlan_name = self._l2network_plugin._get_vlan_name(tenant_id, |
4500 | - vlan_name) |
4501 | - expected_output = vlan_prefix + tenant_id + "-" + vlan_name |
4502 | + vlan_id) |
4503 | + expected_output = vlan_prefix + vlan_id |
4504 | self.assertEqual(result_vlan_name, expected_output) |
4505 | LOG.debug("test_get_vlan_name - END") |
4506 | |
4507 | @@ -823,39 +884,11 @@ |
4508 | port_state) |
4509 | LOG.debug("test_validate_port_state - END") |
4510 | |
4511 | - def test_validate_attachment(self, net_tenant_id=None, |
4512 | - remote_interface_id="new_interface"): |
4513 | - """ |
4514 | - Tests validate attachment |
4515 | - """ |
4516 | - |
4517 | - LOG.debug("test_validate_attachment - START") |
4518 | - if net_tenant_id: |
4519 | - tenant_id = net_tenant_id |
4520 | - else: |
4521 | - tenant_id = self.tenant_id |
4522 | - net_name = self.network_name |
4523 | - new_network_dict = self._l2network_plugin.create_network(tenant_id, |
4524 | - net_name) |
4525 | - network_id = new_network_dict[const.NET_ID] |
4526 | - new_port_dict = self._l2network_plugin.create_port(tenant_id, |
4527 | - network_id) |
4528 | - port_id = new_port_dict[const.PORT_ID] |
4529 | - self._l2network_plugin.plug_interface( |
4530 | - tenant_id, new_network_dict[const.NET_ID], port_id, |
4531 | - remote_interface_id) |
4532 | - self.assertRaises(exc.AlreadyAttached, |
4533 | - self._l2network_plugin._validate_attachment, |
4534 | - tenant_id, network_id, port_id, remote_interface_id) |
4535 | - self.tearDownNetworkPortInterface( |
4536 | - tenant_id, new_network_dict[const.NET_ID], port_id) |
4537 | - LOG.debug("test_validate_attachment - END") |
4538 | - |
4539 | def setUp(self): |
4540 | self.tenant_id = "test_tenant" |
4541 | self.network_name = "test_network" |
4542 | self.profile_name = "test_tenant_port_profile" |
4543 | - self.vlan_id = "test_tenant_vlanid300" |
4544 | + self.qos = "test_qos" |
4545 | self.port_state = const.PORT_UP |
4546 | self.net_id = '00005' |
4547 | self.port_id = 'p0005' |
4548 | @@ -865,6 +898,10 @@ |
4549 | """ |
4550 | Clean up functions after the tests |
4551 | """ |
4552 | + def tearDown(self): |
4553 | + """Clear the test environment""" |
4554 | + # Remove database contents |
4555 | + db.clear_db() |
4556 | |
4557 | def tearDownNetwork(self, tenant_id, network_dict_id): |
4558 | self._l2network_plugin.delete_network(tenant_id, network_dict_id) |
4559 | @@ -885,8 +922,41 @@ |
4560 | def tearDownPortProfile(self, tenant_id, port_profile_id): |
4561 | self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id) |
4562 | |
4563 | + def tearDownPortProfileBinding(self, tenant_id, port_profile_id): |
4564 | + self._l2network_plugin.delete_portprofile(tenant_id, port_profile_id) |
4565 | + |
4566 | def tearDownAssociatePortProfile(self, tenant_id, net_id, port_id, |
4567 | port_profile_id): |
4568 | self._l2network_plugin.disassociate_portprofile( |
4569 | tenant_id, net_id, port_id, port_profile_id) |
4570 | self.tearDownPortProfile(tenant_id, port_profile_id) |
4571 | + |
4572 | + def _make_net_dict(self, net_id, net_name, ports): |
4573 | + res = {const.NET_ID: net_id, const.NET_NAME: net_name} |
4574 | + res[const.NET_PORTS] = ports |
4575 | + return res |
4576 | + |
4577 | + def _make_port_dict(self, port_id, port_state, net_id, attachment): |
4578 | + res = {const.PORT_ID: port_id, const.PORT_STATE: port_state} |
4579 | + res[const.NET_ID] = net_id |
4580 | + res[const.ATTACHMENT] = attachment |
4581 | + return res |
4582 | + |
4583 | + def _make_portprofile_dict(self, tenant_id, profile_id, profile_name, |
4584 | + qos): |
4585 | + profile_associations = self._make_portprofile_assc_list( |
4586 | + tenant_id, profile_id) |
4587 | + res = {const.PROFILE_ID: str(profile_id), |
4588 | + const.PROFILE_NAME: profile_name, |
4589 | + const.PROFILE_ASSOCIATIONS: profile_associations, |
4590 | + const.PROFILE_VLAN_ID: None, |
4591 | + const.PROFILE_QOS: qos} |
4592 | + return res |
4593 | + |
4594 | + def _make_portprofile_assc_list(self, tenant_id, profile_id): |
4595 | + plist = cdb.get_pp_binding(tenant_id, profile_id) |
4596 | + assc_list = [] |
4597 | + for port in plist: |
4598 | + assc_list.append(port[const.PORTID]) |
4599 | + |
4600 | + return assc_list |
4601 | |
4602 | === modified file 'quantum/plugins/cisco/tests/unit/test_nexus_plugin.py' |
4603 | --- quantum/plugins/cisco/tests/unit/test_nexus_plugin.py 2011-08-08 07:23:44 +0000 |
4604 | +++ quantum/plugins/cisco/tests/unit/test_nexus_plugin.py 2011-08-23 20:09:26 +0000 |
4605 | @@ -259,11 +259,10 @@ |
4606 | self.tearDownNetwork(tenant_id, new_net_dict[const.NET_ID]) |
4607 | LOG.debug("test_get_vlan_id_for_network - END") |
4608 | |
4609 | - """ |
4610 | + def tearDownNetwork(self, tenant_id, network_dict_id): |
4611 | + """ |
4612 | Clean up functions after the tests |
4613 | - """ |
4614 | - |
4615 | - def tearDownNetwork(self, tenant_id, network_dict_id): |
4616 | + """ |
4617 | self._cisco_nexus_plugin.delete_network(tenant_id, network_dict_id) |
4618 | |
4619 | # def test_create_network(self): |
4620 | |
4621 | === modified file 'quantum/plugins/cisco/tests/unit/test_ucs_driver.py' |
4622 | --- quantum/plugins/cisco/tests/unit/test_ucs_driver.py 2011-08-08 07:23:44 +0000 |
4623 | +++ quantum/plugins/cisco/tests/unit/test_ucs_driver.py 2011-08-23 20:09:26 +0000 |
4624 | @@ -24,13 +24,13 @@ |
4625 | |
4626 | LOG = logging.getLogger('quantum.tests.test_ucs_driver') |
4627 | |
4628 | -create_vlan_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4629 | +CREATE_VLAN_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4630 | "inHierarchical=\"true\"> <inConfigs><pair key=\"fabric/lan/net-New Vlan\"> "\ |
4631 | "<fabricVlan defaultNet=\"no\" dn=\"fabric/lan/net-New Vlan\" id=\"200\" "\ |
4632 | "name=\"New Vlan\" status=\"created\"></fabricVlan> </pair> </inConfigs> "\ |
4633 | "</configConfMos>" |
4634 | |
4635 | -create_profile_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4636 | +CREATE_PROFILE_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4637 | "inHierarchical=\"true\"> <inConfigs><pair key=\"fabric/lan/profiles/vnic-"\ |
4638 | "New Profile\"> <vnicProfile descr=\"Profile created by Cisco OpenStack "\ |
4639 | "Quantum Plugin\" dn=\"fabric/lan/profiles/vnic-New Profile\" maxPorts="\ |
4640 | @@ -39,7 +39,7 @@ |
4641 | "name=\"New Vlan\" rn=\"if-New Vlan\" > </vnicEtherIf> </vnicProfile> "\ |
4642 | "</pair> </inConfigs> </configConfMos>" |
4643 | |
4644 | -change_vlan_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4645 | +CHANGE_VLAN_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4646 | "inHierarchical=\"true\"> <inConfigs><pair key=\""\ |
4647 | "fabric/lan/profiles/vnic-New Profile\"> <vnicProfile descr=\"Profile "\ |
4648 | "created by Cisco OpenStack Quantum Plugin\" "\ |
4649 | @@ -50,18 +50,18 @@ |
4650 | "<vnicEtherIf defaultNet=\"yes\" name=\"New Vlan\" rn=\"if-New Vlan\" > "\ |
4651 | "</vnicEtherIf> </vnicProfile> </pair></inConfigs> </configConfMos>" |
4652 | |
4653 | -delete_vlan_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4654 | +DELETE_VLAN_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4655 | "inHierarchical=\"true\"> <inConfigs><pair key=\"fabric/lan/net-New Vlan\"> "\ |
4656 | "<fabricVlan dn=\"fabric/lan/net-New Vlan\" status=\"deleted\"> "\ |
4657 | "</fabricVlan> </pair> </inConfigs></configConfMos>" |
4658 | |
4659 | -delete_profile_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4660 | +DELETE_PROFILE_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4661 | "inHierarchical=\"false\"> <inConfigs><pair key=\""\ |
4662 | "fabric/lan/profiles/vnic-New Profile\"> <vnicProfile "\ |
4663 | "dn=\"fabric/lan/profiles/vnic-New Profile\" status=\"deleted\"> "\ |
4664 | "</vnicProfile></pair> </inConfigs> </configConfMos>" |
4665 | |
4666 | -associate_profile_output = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4667 | +ASSOCIATE_PROFILE_OUTPUT = "<configConfMos cookie=\"cookie_placeholder\" "\ |
4668 | "inHierarchical=\"true\"> <inConfigs> <pair key="\ |
4669 | "\"fabric/lan/profiles/vnic-New Profile/cl-New Profile Client\">"\ |
4670 | " <vmVnicProfCl dcName=\".*\" descr=\"\" dn=\"fabric/lan/profiles/vnic-"\ |
4671 | @@ -73,83 +73,86 @@ |
4672 | class TestUCSDriver(unittest.TestCase): |
4673 | |
4674 | def setUp(self): |
4675 | - self._ucsmDriver = cisco_ucs_network_driver.CiscoUCSMDriver() |
4676 | + self.ucsm_driver = cisco_ucs_network_driver.CiscoUCSMDriver() |
4677 | self.vlan_name = 'New Vlan' |
4678 | self.vlan_id = '200' |
4679 | self.profile_name = 'New Profile' |
4680 | self.old_vlan_name = 'Old Vlan' |
4681 | self.profile_client_name = 'New Profile Client' |
4682 | |
4683 | - def test_create_vlan_post_data(self, expected_output=create_vlan_output): |
4684 | + def test_create_vlan_post_data(self, expected_output=CREATE_VLAN_OUTPUT): |
4685 | """ |
4686 | Tests creation of vlan post Data |
4687 | """ |
4688 | |
4689 | LOG.debug("test_create_vlan") |
4690 | - vlan_details = self._ucsmDriver._create_vlan_post_data( |
4691 | + vlan_details = self.ucsm_driver._create_vlan_post_data( |
4692 | self.vlan_name, self.vlan_id) |
4693 | self.assertEqual(vlan_details, expected_output) |
4694 | LOG.debug("test_create_vlan - END") |
4695 | |
4696 | def test_create_profile_post_data( |
4697 | - self, expected_output=create_profile_output): |
4698 | + self, expected_output=CREATE_PROFILE_OUTPUT): |
4699 | """ |
4700 | Tests creation of profile post Data |
4701 | """ |
4702 | |
4703 | LOG.debug("test_create_profile_post_data - START") |
4704 | - profile_details = self._ucsmDriver._create_profile_post_data( |
4705 | + profile_details = self.ucsm_driver._create_profile_post_data( |
4706 | self.profile_name, self.vlan_name) |
4707 | self.assertEqual(profile_details, expected_output) |
4708 | LOG.debug("test_create_profile_post - END") |
4709 | |
4710 | - def test_change_vlan_in_profile_post_data( |
4711 | - self, expected_output=change_vlan_output): |
4712 | + def test_change_vlan_profile_data( |
4713 | + self, expected_output=CHANGE_VLAN_OUTPUT): |
4714 | """ |
4715 | Tests creation of change vlan in profile post Data |
4716 | """ |
4717 | |
4718 | LOG.debug("test_create_profile_post_data - START") |
4719 | - profile_details = self._ucsmDriver._change_vlan_in_profile_post_data( |
4720 | + profile_details = self.ucsm_driver._change_vlaninprof_post_data( |
4721 | self.profile_name, self.old_vlan_name, self.vlan_name) |
4722 | self.assertEqual(profile_details, expected_output) |
4723 | LOG.debug("test_create_profile_post - END") |
4724 | |
4725 | - def test_delete_vlan_post_data(self, expected_output=delete_vlan_output): |
4726 | - LOG.debug("test_create_profile_post_data - START") |
4727 | + def test_delete_vlan_post_data(self, expected_output=DELETE_VLAN_OUTPUT): |
4728 | """ |
4729 | Tests deletion of vlan post Data |
4730 | """ |
4731 | |
4732 | - vlan_details = self._ucsmDriver._create_vlan_post_data( |
4733 | + LOG.debug("test_create_profile_post_data - START") |
4734 | + |
4735 | + self.ucsm_driver._create_vlan_post_data( |
4736 | self.vlan_name, self.vlan_id) |
4737 | - vlan_delete_details = self._ucsmDriver._delete_vlan_post_data( |
4738 | + vlan_delete_details = self.ucsm_driver._delete_vlan_post_data( |
4739 | self.vlan_name) |
4740 | self.assertEqual(vlan_delete_details, expected_output) |
4741 | LOG.debug("test_create_profile_post - END") |
4742 | |
4743 | def test_delete_profile_post_data( |
4744 | - self, expected_output=delete_profile_output): |
4745 | + self, expected_output=DELETE_PROFILE_OUTPUT): |
4746 | """ |
4747 | Tests deletion of profile post Data |
4748 | """ |
4749 | |
4750 | LOG.debug("test_create_profile_post_data - START") |
4751 | - profile_details = self._ucsmDriver._create_profile_post_data( |
4752 | + #profile_details = self.ucsm_driver._create_profile_post_data( |
4753 | + # self.profile_name, self.vlan_name) |
4754 | + self.ucsm_driver._create_profile_post_data( |
4755 | self.profile_name, self.vlan_name) |
4756 | - profile_delete_details = self._ucsmDriver._delete_profile_post_data( |
4757 | + profile_delete_details = self.ucsm_driver._delete_profile_post_data( |
4758 | self.profile_name) |
4759 | self.assertEqual(profile_delete_details, expected_output) |
4760 | LOG.debug("test_create_profile_post - END") |
4761 | |
4762 | - def test_create_profile_client_post_data( |
4763 | - self, expected_output=associate_profile_output): |
4764 | + def test_create_profile_client_data( |
4765 | + self, expected_output=ASSOCIATE_PROFILE_OUTPUT): |
4766 | """ |
4767 | Tests creation of profile client post Data |
4768 | """ |
4769 | |
4770 | - LOG.debug("test_create_profile_client_post_data - START") |
4771 | - profile_details = self._ucsmDriver._create_profile_client_post_data( |
4772 | + LOG.debug("test_create_profile_client_data - START") |
4773 | + profile_details = self.ucsm_driver._create_pclient_post_data( |
4774 | self.profile_name, self.profile_client_name) |
4775 | self.assertEqual(profile_details, expected_output) |
4776 | LOG.debug("test_create_profile_post - END") |
4777 | @@ -160,6 +163,6 @@ |
4778 | """ |
4779 | |
4780 | LOG.debug("test_get_next_dynamic_nic - START") |
4781 | - dynamic_nic_id = self._ucsmDriver._get_next_dynamic_nic() |
4782 | + dynamic_nic_id = self.ucsm_driver._get_next_dynamic_nic() |
4783 | self.assertTrue(len(dynamic_nic_id) > 0) |
4784 | LOG.debug("test_get_next_dynamic_nic - END") |
4785 | |
4786 | === modified file 'quantum/plugins/cisco/tests/unit/test_ucs_plugin.py' |
4787 | --- quantum/plugins/cisco/tests/unit/test_ucs_plugin.py 2011-08-08 07:23:44 +0000 |
4788 | +++ quantum/plugins/cisco/tests/unit/test_ucs_plugin.py 2011-08-23 20:09:26 +0000 |
4789 | @@ -32,7 +32,7 @@ |
4790 | |
4791 | self.tenant_id = "test_tenant_cisco12" |
4792 | self.net_name = "test_network_cisco12" |
4793 | - self.net_id = 000007 |
4794 | + self.net_id = 000011 |
4795 | self.vlan_name = "q-" + str(self.net_id) + "vlan" |
4796 | self.vlan_id = 266 |
4797 | self.port_id = "4" |
4798 | @@ -238,12 +238,12 @@ |
4799 | self.assertEqual(new_port_profile[const.PROFILE_NAME], profile_name) |
4800 | self.tearDownNetworkPort(self.tenant_id, self.net_id, self.port_id) |
4801 | |
4802 | - def _test_get_port_details_state_down(self, port_state): |
4803 | + def _test_show_port_state_down(self, port_state): |
4804 | """ |
4805 | Tests whether user is able to retrieve a remote interface |
4806 | that is attached to this particular port when port state is down. |
4807 | """ |
4808 | - LOG.debug("UCSVICTestPlugin:_test_get_port_details_state_down()" + |
4809 | + LOG.debug("UCSVICTestPlugin:_test_show_port_state_down()" + |
4810 | "called\n") |
4811 | self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name, |
4812 | self.net_id, self.vlan_name, |
4813 | @@ -268,8 +268,8 @@ |
4814 | def test_get_port_details_state_up(self): |
4815 | self._test_get_port_details_state_up(const.PORT_UP) |
4816 | |
4817 | - def test_get_port_details_state_down(self): |
4818 | - self._test_get_port_details_state_down(const.PORT_DOWN) |
4819 | + def test_show_port_state_down(self): |
4820 | + self._test_show_port_state_down(const.PORT_DOWN) |
4821 | |
4822 | def test_create_port_profile(self): |
4823 | LOG.debug("UCSVICTestPlugin:test_create_port_profile() called\n") |
4824 | @@ -313,7 +313,6 @@ |
4825 | self.tenant_id, self.net_id, self.port_id) |
4826 | self.assertEqual(port[const.ATTACHMENT], remote_interface_id) |
4827 | port_profile = port[const.PORT_PROFILE] |
4828 | - profile_name = port_profile[const.PROFILE_NAME] |
4829 | new_vlan_name = self._cisco_ucs_plugin._get_vlan_name_for_network( |
4830 | self.tenant_id, self.net_id) |
4831 | new_vlan_id = self._cisco_ucs_plugin._get_vlan_id_for_network( |
4832 | @@ -346,7 +345,6 @@ |
4833 | self.tenant_id, self.net_id, self.port_id) |
4834 | self.assertEqual(port[const.ATTACHMENT], None) |
4835 | port_profile = port[const.PORT_PROFILE] |
4836 | - profile_name = port_profile[const.PROFILE_NAME] |
4837 | self.assertEqual(port_profile[const.PROFILE_VLAN_NAME], |
4838 | conf.DEFAULT_VLAN_NAME) |
4839 | self.assertEqual(port_profile[const.PROFILE_VLAN_ID], |
4840 | @@ -394,12 +392,12 @@ |
4841 | def test_get_network_NetworkNotFound(self): |
4842 | self.assertRaises(exc.NetworkNotFound, |
4843 | self._cisco_ucs_plugin._get_network, |
4844 | - *(self.tenant_id, self.net_id)) |
4845 | + self.tenant_id, self.net_id) |
4846 | |
4847 | def test_delete_network_NetworkNotFound(self): |
4848 | self.assertRaises(exc.NetworkNotFound, |
4849 | self._cisco_ucs_plugin.delete_network, |
4850 | - *(self.tenant_id, self.net_id)) |
4851 | + self.tenant_id, self.net_id) |
4852 | |
4853 | def test_delete_port_PortInUse(self): |
4854 | self._test_delete_port_PortInUse("4") |
4855 | @@ -414,7 +412,7 @@ |
4856 | self.port_id, |
4857 | remote_interface_id) |
4858 | self.assertRaises(exc.PortInUse, self._cisco_ucs_plugin.delete_port, |
4859 | - *(self.tenant_id, self.net_id, self.port_id)) |
4860 | + self.tenant_id, self.net_id, self.port_id) |
4861 | self.tearDownNetworkPortInterface(self.tenant_id, self.net_id, |
4862 | self.port_id) |
4863 | |
4864 | @@ -423,7 +421,7 @@ |
4865 | self.net_id, self.vlan_name, |
4866 | self.vlan_id) |
4867 | self.assertRaises(exc.PortNotFound, self._cisco_ucs_plugin.delete_port, |
4868 | - *(self.tenant_id, self.net_id, self.port_id)) |
4869 | + self.tenant_id, self.net_id, self.port_id) |
4870 | self.tearDownNetwork(self.tenant_id, self.net_id) |
4871 | |
4872 | def test_plug_interface_PortInUse(self): |
4873 | @@ -441,16 +439,16 @@ |
4874 | self.port_id, |
4875 | remote_interface_id1) |
4876 | self.assertRaises(exc.PortInUse, self._cisco_ucs_plugin.plug_interface, |
4877 | - *(self.tenant_id, self.net_id, self.port_id, |
4878 | - remote_interface_id2)) |
4879 | + self.tenant_id, self.net_id, self.port_id, |
4880 | + remote_interface_id2) |
4881 | self.tearDownNetworkPortInterface(self.tenant_id, self.net_id, |
4882 | self.port_id) |
4883 | |
4884 | - def test_validate_attachment_AlreadyAttached(self): |
4885 | + def test_attachment_exists(self): |
4886 | LOG.debug("UCSVICTestPlugin:testValidateAttachmentAlreadyAttached") |
4887 | - self._test_validate_attachment_AlreadyAttached("4") |
4888 | + self._test_attachment_exists("4") |
4889 | |
4890 | - def _test_validate_attachment_AlreadyAttached(self, remote_interface_id): |
4891 | + def _test_attachment_exists(self, remote_interface_id): |
4892 | LOG.debug("UCSVICTestPlugin:_test_validate_attachmentAlreadyAttached") |
4893 | self._cisco_ucs_plugin.create_network(self.tenant_id, self.net_name, |
4894 | self.net_id, self.vlan_name, |
4895 | @@ -461,8 +459,8 @@ |
4896 | self.port_id, |
4897 | remote_interface_id) |
4898 | self.assertRaises( |
4899 | - exc.AlreadyAttached, self._cisco_ucs_plugin._validate_attachment, |
4900 | - *(self.tenant_id, self.net_id, self.port_id, remote_interface_id)) |
4901 | + exc.PortInUse, self._cisco_ucs_plugin._validate_attachment, |
4902 | + self.tenant_id, self.net_id, self.port_id, remote_interface_id) |
4903 | self.tearDownNetworkPortInterface(self.tenant_id, self.net_id, |
4904 | self.port_id) |
4905 | |
4906 | |
4907 | === modified file 'quantum/plugins/cisco/ucs/__init__.py' |
4908 | --- quantum/plugins/cisco/ucs/__init__.py 2011-07-31 19:04:01 +0000 |
4909 | +++ quantum/plugins/cisco/ucs/__init__.py 2011-08-23 20:09:26 +0000 |
4910 | @@ -1,3 +1,4 @@ |
4911 | +""" |
4912 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4913 | # |
4914 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
4915 | @@ -16,3 +17,4 @@ |
4916 | # |
4917 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
4918 | # |
4919 | +""" |
4920 | |
4921 | === modified file 'quantum/plugins/cisco/ucs/cisco_getvif.py' |
4922 | --- quantum/plugins/cisco/ucs/cisco_getvif.py 2011-08-14 01:28:02 +0000 |
4923 | +++ quantum/plugins/cisco/ucs/cisco_getvif.py 2011-08-23 20:09:26 +0000 |
4924 | @@ -1,3 +1,4 @@ |
4925 | +""" |
4926 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4927 | # |
4928 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
4929 | @@ -16,11 +17,13 @@ |
4930 | # |
4931 | # @author: Rohit Agarwalla, Cisco Systems Inc. |
4932 | # |
4933 | -import sys |
4934 | +""" |
4935 | + |
4936 | import subprocess |
4937 | |
4938 | |
4939 | def get_next_dynic(argv=[]): |
4940 | + """Get the next available dynamic nic on this host""" |
4941 | cmd = ["ifconfig", "-a"] |
4942 | f_cmd_output = subprocess.Popen(cmd, stdout=subprocess.PIPE).\ |
4943 | communicate()[0] |
4944 | |
4945 | === modified file 'quantum/plugins/cisco/ucs/cisco_ucs_configuration.py' |
4946 | --- quantum/plugins/cisco/ucs/cisco_ucs_configuration.py 2011-08-14 01:28:02 +0000 |
4947 | +++ quantum/plugins/cisco/ucs/cisco_ucs_configuration.py 2011-08-23 20:09:26 +0000 |
4948 | @@ -1,3 +1,4 @@ |
4949 | +""" |
4950 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4951 | # |
4952 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
4953 | @@ -16,6 +17,7 @@ |
4954 | # |
4955 | # @author: Sumit Naiksatam, Cisco Systems, Inc. |
4956 | # |
4957 | +""" |
4958 | |
4959 | import os |
4960 | |
4961 | @@ -23,15 +25,15 @@ |
4962 | |
4963 | CONF_FILE = "../conf/ucs.ini" |
4964 | |
4965 | -cp = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
4966 | +CP = confp.CiscoConfigParser(os.path.dirname(os.path.realpath(__file__)) \ |
4967 | + "/" + CONF_FILE) |
4968 | |
4969 | -section = cp['UCSM'] |
4970 | -UCSM_IP_ADDRESS = section['ip_address'] |
4971 | -DEFAULT_VLAN_NAME = section['default_vlan_name'] |
4972 | -DEFAULT_VLAN_ID = section['default_vlan_id'] |
4973 | -MAX_UCSM_PORT_PROFILES = section['max_ucsm_port_profiles'] |
4974 | -PROFILE_NAME_PREFIX = section['profile_name_prefix'] |
4975 | +SECTION = CP['UCSM'] |
4976 | +UCSM_IP_ADDRESS = SECTION['ip_address'] |
4977 | +DEFAULT_VLAN_NAME = SECTION['default_vlan_name'] |
4978 | +DEFAULT_VLAN_ID = SECTION['default_vlan_id'] |
4979 | +MAX_UCSM_PORT_PROFILES = SECTION['max_ucsm_port_profiles'] |
4980 | +PROFILE_NAME_PREFIX = SECTION['profile_name_prefix'] |
4981 | |
4982 | -section = cp['DRIVER'] |
4983 | -UCSM_DRIVER = section['name'] |
4984 | +SECTION = CP['DRIVER'] |
4985 | +UCSM_DRIVER = SECTION['name'] |
4986 | |
4987 | === modified file 'quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py' |
4988 | --- quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py 2011-08-14 01:28:02 +0000 |
4989 | +++ quantum/plugins/cisco/ucs/cisco_ucs_network_driver.py 2011-08-23 20:09:26 +0000 |
4990 | @@ -1,3 +1,4 @@ |
4991 | +""" |
4992 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 |
4993 | # |
4994 | # Copyright 2011 Cisco Systems, Inc. All rights reserved. |
4995 | @@ -17,15 +18,14 @@ |
4996 | # @author: Sumit Naiksatam, Cisco Systems Inc. |
4997 | # |
4998 | """ |
4999 | + |
5000 | +""" |
Hi Sumit/Rohit,
I apologise for the "needs fixing" without a proper review, but it seems your branch has several conflict with trunk!