Merge "ML2 Cisco Nexus MD: Remove unnecessary Cisco nexus DB"

This commit is contained in:
Jenkins 2014-04-18 15:33:24 +00:00 committed by Gerrit Code Review
commit a49750702c
9 changed files with 66 additions and 424 deletions

View File

@ -0,0 +1,59 @@
# Copyright 2014 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
"""Remove ML2 Cisco Credentials DB
Revision ID: 4eca4a84f08a
Revises: 33c3db036fe4
Create Date: 2014-04-10 19:32:46.697189
"""
# revision identifiers, used by Alembic.
revision = '4eca4a84f08a'
down_revision = '33c3db036fe4'
# Change to ['*'] if this migration applies to all plugins
migration_for_plugins = [
'neutron.plugins.ml2.plugin.Ml2Plugin'
]
from alembic import op
import sqlalchemy as sa
from neutron.db import migration
def upgrade(active_plugins=None, options=None):
if not migration.should_run(active_plugins, migration_for_plugins):
return
op.drop_table('cisco_ml2_credentials')
def downgrade(active_plugins=None, options=None):
if not migration.should_run(active_plugins, migration_for_plugins):
return
op.create_table(
'cisco_ml2_credentials',
sa.Column('credential_id', sa.string(length=255), nullable=True),
sa.Column('tenant_id', sa.string(length=255), nullable=False),
sa.Column('credential_name', sa.string(length=255), nullable=False),
sa.Column('user_name', sa.string(length=255), nullable=True),
sa.Column('password', sa.string(length=255), nullable=True),
sa.PrimaryKeyConstraint('tenant_id', 'credential_name')
)

View File

@ -1 +1 @@
33c3db036fe4
4eca4a84f08a

View File

@ -1,71 +0,0 @@
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from neutron.plugins.ml2.drivers.cisco.nexus import config
from neutron.plugins.ml2.drivers.cisco.nexus import constants as const
from neutron.plugins.ml2.drivers.cisco.nexus import exceptions as cexc
from neutron.plugins.ml2.drivers.cisco.nexus import network_db_v2 as cdb
TENANT = const.NETWORK_ADMIN
class Store(object):
"""ML2 Cisco Mechanism Driver Credential Store."""
@staticmethod
def initialize():
_nexus_dict = config.ML2MechCiscoConfig.nexus_dict
for ipaddr, keyword in _nexus_dict.keys():
if keyword == const.USERNAME:
try:
cdb.add_credential(TENANT, ipaddr,
_nexus_dict[ipaddr, const.USERNAME],
_nexus_dict[ipaddr, const.PASSWORD])
except cexc.CredentialAlreadyExists:
# We are quietly ignoring this, since it only happens
# if this class module is loaded more than once, in which
# case, the credentials are already populated
pass
@staticmethod
def put_credential(cred_name, username, password):
"""Set the username and password."""
cdb.add_credential(TENANT, cred_name, username, password)
@staticmethod
def get_username(cred_name):
"""Get the username."""
credential = cdb.get_credential_name(TENANT, cred_name)
return credential[const.CREDENTIAL_USERNAME]
@staticmethod
def get_password(cred_name):
"""Get the password."""
credential = cdb.get_credential_name(TENANT, cred_name)
return credential[const.CREDENTIAL_PASSWORD]
@staticmethod
def get_credential(cred_name):
"""Get the username and password."""
credential = cdb.get_credential_name(TENANT, cred_name)
return {const.USERNAME: credential[const.CREDENTIAL_USERNAME],
const.PASSWORD: credential[const.CREDENTIAL_PASSWORD]}
@staticmethod
def delete_credential(cred_name):
"""Delete a credential."""
cdb.remove_credential(TENANT, cred_name)

View File

@ -25,7 +25,6 @@ from neutron.openstack.common import log as logging
from neutron.plugins.common import constants as p_const
from neutron.plugins.ml2 import driver_api as api
from neutron.plugins.ml2.drivers.cisco.nexus import config as conf
from neutron.plugins.ml2.drivers.cisco.nexus import credentials_v2 as cred
from neutron.plugins.ml2.drivers.cisco.nexus import exceptions as excep
from neutron.plugins.ml2.drivers.cisco.nexus import nexus_db_v2 as nxos_db
from neutron.plugins.ml2.drivers.cisco.nexus import nexus_network_driver
@ -45,12 +44,8 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
self._nexus_switches = conf.ML2MechCiscoConfig.nexus_dict
LOG.debug(_("nexus_switches found = %s"), self._nexus_switches)
self.credentials = {}
self.driver = nexus_network_driver.CiscoNexusDriver()
# Initialize credential store after database initialization.
cred.Store.initialize()
def _valid_network_segment(self, segment):
return (cfg.CONF.ml2_cisco.managed_physical_network is None or
cfg.CONF.ml2_cisco.managed_physical_network ==

View File

@ -1,116 +0,0 @@
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from sqlalchemy.orm import exc
from neutron.db import api as db
from neutron.openstack.common import log as logging
from neutron.openstack.common import uuidutils
from neutron.plugins.ml2.drivers.cisco.nexus import constants as const
from neutron.plugins.ml2.drivers.cisco.nexus import exceptions as c_exc
from neutron.plugins.ml2.drivers.cisco.nexus import network_models_v2
from neutron.plugins.ml2.drivers.cisco.nexus import nexus_models_v2 # noqa
LOG = logging.getLogger(__name__)
def get_all_credentials(tenant_id):
"""Lists all the creds for a tenant."""
session = db.get_session()
return (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).all())
def get_credential(tenant_id, credential_id):
"""Lists the creds for given a cred_id and tenant_id."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).
filter_by(credential_id=credential_id).one())
return cred
except exc.NoResultFound:
raise c_exc.CredentialNotFound(credential_id=credential_id,
tenant_id=tenant_id)
def get_credential_name(tenant_id, credential_name):
"""Lists the creds for given a cred_name and tenant_id."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).
filter_by(credential_name=credential_name).one())
return cred
except exc.NoResultFound:
raise c_exc.CredentialNameNotFound(credential_name=credential_name,
tenant_id=tenant_id)
def add_credential(tenant_id, credential_name, user_name, password):
"""Adds a qos to tenant association."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).
filter_by(credential_name=credential_name).one())
raise c_exc.CredentialAlreadyExists(credential_name=credential_name,
tenant_id=tenant_id)
except exc.NoResultFound:
cred = network_models_v2.Credential(
credential_id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
credential_name=credential_name,
user_name=user_name,
password=password)
session.add(cred)
session.flush()
return cred
def remove_credential(tenant_id, credential_id):
"""Removes a credential from a tenant."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).
filter_by(credential_id=credential_id).one())
session.delete(cred)
session.flush()
return cred
except exc.NoResultFound:
pass
def update_credential(tenant_id, credential_id,
new_user_name=None, new_password=None):
"""Updates a credential for a tenant."""
session = db.get_session()
try:
cred = (session.query(network_models_v2.Credential).
filter_by(tenant_id=tenant_id).
filter_by(credential_id=credential_id).one())
if new_user_name:
cred[const.CREDENTIAL_USERNAME] = new_user_name
if new_password:
cred[const.CREDENTIAL_PASSWORD] = new_password
session.merge(cred)
session.flush()
return cred
except exc.NoResultFound:
raise c_exc.CredentialNotFound(credential_id=credential_id,
tenant_id=tenant_id)

View File

@ -1,31 +0,0 @@
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import sqlalchemy as sa
from neutron.db import model_base
class Credential(model_base.BASEV2):
"""Represents credentials for a tenant to control Cisco switches."""
__tablename__ = 'cisco_ml2_credentials'
credential_id = sa.Column(sa.String(255))
tenant_id = sa.Column(sa.String(255), primary_key=True)
credential_name = sa.Column(sa.String(255), primary_key=True)
user_name = sa.Column(sa.String(255))
password = sa.Column(sa.String(255))

View File

@ -22,7 +22,6 @@ from neutron.openstack.common import importutils
from neutron.openstack.common import log as logging
from neutron.plugins.ml2.drivers.cisco.nexus import config as conf
from neutron.plugins.ml2.drivers.cisco.nexus import constants as const
from neutron.plugins.ml2.drivers.cisco.nexus import credentials_v2 as cred
from neutron.plugins.ml2.drivers.cisco.nexus import exceptions as cexc
from neutron.plugins.ml2.drivers.cisco.nexus import nexus_db_v2
from neutron.plugins.ml2.drivers.cisco.nexus import nexus_snippets as snipp
@ -35,7 +34,6 @@ class CiscoNexusDriver(object):
def __init__(self):
self.ncclient = None
self.nexus_switches = conf.ML2MechCiscoConfig.nexus_dict
self.credentials = {}
self.connections = {}
def _import_ncclient(self):
@ -77,20 +75,6 @@ class CiscoNexusDriver(object):
# the original ncclient exception.
raise cexc.NexusConfigFailed(config=config, exc=e)
def get_credential(self, nexus_ip):
"""Return credential information for a given Nexus IP address.
If credential doesn't exist then also add to local dictionary.
"""
if nexus_ip not in self.credentials:
nexus_username = cred.Store.get_username(nexus_ip)
nexus_password = cred.Store.get_password(nexus_ip)
self.credentials[nexus_ip] = {
const.USERNAME: nexus_username,
const.PASSWORD: nexus_password
}
return self.credentials[nexus_ip]
def nxos_connect(self, nexus_host):
"""Make SSH connection to the Nexus Switch."""
if getattr(self.connections.get(nexus_host), 'connected', None):
@ -99,9 +83,8 @@ class CiscoNexusDriver(object):
if not self.ncclient:
self.ncclient = self._import_ncclient()
nexus_ssh_port = int(self.nexus_switches[nexus_host, 'ssh_port'])
nexus_creds = self.get_credential(nexus_host)
nexus_user = nexus_creds[const.USERNAME]
nexus_password = nexus_creds[const.PASSWORD]
nexus_user = self.nexus_switches[nexus_host, const.USERNAME]
nexus_password = self.nexus_switches[nexus_host, const.PASSWORD]
try:
man = self.ncclient.connect(host=nexus_host,
port=nexus_ssh_port,

View File

@ -1,167 +0,0 @@
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
import testtools
from neutron.db import api as db
from neutron.plugins.ml2.drivers.cisco.nexus import exceptions
from neutron.plugins.ml2.drivers.cisco.nexus import network_db_v2
from neutron.tests import base
class CiscoNetworkCredentialDbTest(base.BaseTestCase):
"""Unit tests for Cisco ML2 mechanism driver credentials database."""
CredObj = collections.namedtuple('CredObj',
'tenant_id cred_name user_name pwd')
def setUp(self):
super(CiscoNetworkCredentialDbTest, self).setUp()
db.configure_db()
self.addCleanup(db.clear_db)
def _cred_test_obj(self, tenant_num, cred_num):
"""Create a Credential test object from a pair of numbers."""
tenant_id = 'tenant_%s' % tenant_num
cred_name = 'credential_%s_%s' % (tenant_num, cred_num)
user_name = 'user_%s_%s' % (tenant_num, cred_num)
pwd = 'password_%s_%s' % (tenant_num, cred_num)
return self.CredObj(tenant_id, cred_name, user_name, pwd)
def _assert_cred_equal(self, db_cred, test_cred):
"""Assert that a database credential matches a credential test obj."""
self.assertEqual(db_cred.tenant_id, test_cred.tenant_id)
self.assertEqual(db_cred.credential_name, test_cred.cred_name)
self.assertEqual(db_cred.user_name, test_cred.user_name)
self.assertEqual(db_cred.password, test_cred.pwd)
def _get_credential(self, db_cred):
"""Lists credentials that match a credential's tenant and cred IDs."""
return network_db_v2.get_credential(db_cred.tenant_id,
db_cred.credential_id)
def _get_credential_name(self, db_cred):
"""Lists credentials that match a cred's tenant ID and cred name."""
return network_db_v2.get_credential_name(db_cred.tenant_id,
db_cred.credential_name)
def _add_credential(self, test_cred):
"""Adds a credential to the database."""
return network_db_v2.add_credential(test_cred.tenant_id,
test_cred.cred_name,
test_cred.user_name,
test_cred.pwd)
def _remove_credential(self, db_cred):
"""Removes a credential from the database."""
return network_db_v2.remove_credential(db_cred.tenant_id,
db_cred.credential_id)
def _update_credential(self, db_cred, new_user_name=None,
new_password=None):
"""Updates a credential with a new user name and password."""
return network_db_v2.update_credential(db_cred.tenant_id,
db_cred.credential_id,
new_user_name,
new_password)
def test_credential_add_remove(self):
"""Tests add and removal of credential to/from the database."""
cred11 = self._cred_test_obj(1, 1)
cred = self._add_credential(cred11)
self._assert_cred_equal(cred, cred11)
cred = self._remove_credential(cred)
self._assert_cred_equal(cred, cred11)
cred = self._remove_credential(cred)
self.assertIsNone(cred)
def test_credential_add_dup(self):
"""Tests addition of a duplicate credential to the database."""
cred22 = self._cred_test_obj(2, 2)
cred = self._add_credential(cred22)
self._assert_cred_equal(cred, cred22)
with testtools.ExpectedException(exceptions.CredentialAlreadyExists):
self._add_credential(cred22)
cred = self._remove_credential(cred)
self._assert_cred_equal(cred, cred22)
cred = self._remove_credential(cred)
self.assertIsNone(cred)
def test_credential_get(self):
"""Tests get of credentials by tenant ID and credential ID."""
cred11 = self._cred_test_obj(1, 1)
cred11_db = self._add_credential(cred11)
cred21 = self._cred_test_obj(2, 1)
cred21_db = self._add_credential(cred21)
cred22 = self._cred_test_obj(2, 2)
cred22_db = self._add_credential(cred22)
cred = self._get_credential(cred11_db)
self._assert_cred_equal(cred, cred11)
cred = self._get_credential(cred21_db)
self._assert_cred_equal(cred, cred21)
cred = self._get_credential(cred22_db)
self._assert_cred_equal(cred, cred22)
with testtools.ExpectedException(exceptions.CredentialNotFound):
network_db_v2.get_credential("dummyTenantId", "dummyCredentialId")
cred_all_t1 = network_db_v2.get_all_credentials(cred11.tenant_id)
self.assertEqual(len(cred_all_t1), 1)
cred_all_t2 = network_db_v2.get_all_credentials(cred21.tenant_id)
self.assertEqual(len(cred_all_t2), 2)
def test_credential_get_name(self):
"""Tests get of credential by tenant ID and credential name."""
cred11 = self._cred_test_obj(1, 1)
cred11_db = self._add_credential(cred11)
cred21 = self._cred_test_obj(2, 1)
cred21_db = self._add_credential(cred21)
cred22 = self._cred_test_obj(2, 2)
cred22_db = self._add_credential(cred22)
self.assertNotEqual(cred11_db.credential_id, cred21_db.credential_id)
self.assertNotEqual(cred11_db.credential_id, cred22_db.credential_id)
self.assertNotEqual(cred21_db.credential_id, cred22_db.credential_id)
cred = self._get_credential_name(cred11_db)
self._assert_cred_equal(cred, cred11)
cred = self._get_credential_name(cred21_db)
self._assert_cred_equal(cred, cred21)
cred = self._get_credential_name(cred22_db)
self._assert_cred_equal(cred, cred22)
with testtools.ExpectedException(exceptions.CredentialNameNotFound):
network_db_v2.get_credential_name("dummyTenantId",
"dummyCredentialName")
def test_credential_update(self):
"""Tests update of a credential with a new user name and password."""
cred11 = self._cred_test_obj(1, 1)
cred11_db = self._add_credential(cred11)
self._update_credential(cred11_db)
new_user_name = "new user name"
new_pwd = "new password"
new_credential = self._update_credential(
cred11_db, new_user_name, new_pwd)
expected_cred = self.CredObj(
cred11.tenant_id, cred11.cred_name, new_user_name, new_pwd)
self._assert_cred_equal(new_credential, expected_cred)
new_credential = self._get_credential(cred11_db)
self._assert_cred_equal(new_credential, expected_cred)
with testtools.ExpectedException(exceptions.CredentialNotFound):
network_db_v2.update_credential(
"dummyTenantId", "dummyCredentialId", new_user_name, new_pwd)

View File

@ -121,17 +121,6 @@ class TestCiscoNexusDevice(base.BaseTestCase):
VLAN_ID_PC),
}
test_credentials = {
NEXUS_IP_ADDRESS: {
constants.USERNAME: 'admin',
constants.PASSWORD: 'pass1234'
},
NEXUS_IP_ADDRESS_PC: {
constants.USERNAME: 'admin',
constants.PASSWORD: 'password'
},
}
def setUp(self):
"""Sets up mock ncclient, and switch and credentials dictionaries."""
super(TestCiscoNexusDevice, self).setUp()
@ -154,12 +143,13 @@ class TestCiscoNexusDevice(base.BaseTestCase):
host_name)] = nexus_port
mech_instance._nexus_switches[(ip_addr,
'ssh_port')] = NEXUS_SSH_PORT
mech_instance._nexus_switches[(ip_addr,
constants.USERNAME)] = 'admin'
mech_instance._nexus_switches[(ip_addr,
constants.PASSWORD)] = 'password'
mech_instance.driver.nexus_switches = (
mech_instance._nexus_switches)
mech_instance.driver.credentials = (
TestCiscoNexusDevice.test_credentials)
db.configure_db()
mock.patch.object(mech_cisco_nexus.CiscoNexusMechanismDriver,