Merge "Remove List events API from Cisco N1kv Neutron"

This commit is contained in:
Jenkins 2014-04-25 05:57:06 +00:00 committed by Gerrit Code Review
commit 48e9a73f64
5 changed files with 120 additions and 61 deletions

View File

@ -852,6 +852,13 @@ def get_policy_profile(db_session, id):
raise c_exc.PolicyProfileIdNotFound(profile_id=id)
def get_policy_profiles():
"""Retrieve all policy profiles."""
db_session = db.get_session()
with db_session.begin(subtransactions=True):
return db_session.query(n1kv_models_v2.PolicyProfile)
def create_profile_binding(db_session, tenant_id, profile_id, profile_type):
"""Create Network/Policy Profile association with a tenant."""
db_session = db_session or db.get_session()

View File

@ -156,18 +156,6 @@ class Client(object):
"""
return self._get(self.port_profiles_path)
def list_events(self, event_type=None, epoch=None):
"""
Fetch all events of event_type from the VSM.
:param event_type: type of event to be listed.
:param epoch: timestamp after which the events occurred to be listed.
:returns: XML string
"""
if event_type:
self.events_path = self.events_path + '?type=' + event_type
return self._get(self.events_path)
def create_bridge_domain(self, network, overlay_subtype):
"""
Create a bridge domain on VSM.

View File

@ -154,15 +154,13 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
"""
LOG.debug(_('_setup_vsm'))
self.agent_vsm = True
# Retrieve all the policy profiles from VSM.
self._populate_policy_profiles()
# Continue to poll VSM for any create/delete of policy profiles.
# Poll VSM for create/delete of policy profile.
eventlet.spawn(self._poll_policy_profiles)
def _poll_policy_profiles(self):
"""Start a green thread to pull policy profiles from VSM."""
while True:
self._poll_policies(event_type='port_profile')
self._populate_policy_profiles()
eventlet.sleep(int(c_conf.CISCO_N1K.poll_duration))
def _populate_policy_profiles(self):
@ -177,53 +175,35 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
try:
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_port_profiles()
LOG.debug(_('_populate_policy_profiles %s'), policy_profiles)
vsm_profiles = {}
plugin_profiles = {}
# Fetch policy profiles from VSM
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.ID and c_const.NAME in profile:
profile_id = profile[c_const.PROPERTIES][c_const.ID]
profile_name = profile[c_const.
PROPERTIES][c_const.NAME]
self._add_policy_profile(profile_name, profile_id)
profile_name = (profile[c_const.PROPERTIES].
get(c_const.NAME, None))
profile_id = (profile[c_const.PROPERTIES].
get(c_const.ID, None))
if profile_id and profile_name:
vsm_profiles[profile_id] = profile_name
# Fetch policy profiles previously populated
for profile in n1kv_db_v2.get_policy_profiles():
plugin_profiles[profile.id] = profile.name
vsm_profiles_set = set(vsm_profiles)
plugin_profiles_set = set(plugin_profiles)
# Update database if the profile sets differ.
if vsm_profiles_set ^ plugin_profiles_set:
# Add profiles in database if new profiles were created in VSM
for pid in vsm_profiles_set - plugin_profiles_set:
self._add_policy_profile(vsm_profiles[pid], pid)
# Delete profiles from database if profiles were deleted in VSM
for pid in plugin_profiles_set - vsm_profiles_set:
self._delete_policy_profile(pid)
self._remove_all_fake_policy_profiles()
except (cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
LOG.warning(_('No policy profile populated from VSM'))
def _poll_policies(self, event_type=None, epoch=None, tenant_id=None):
"""
Poll for Policy Profiles from Cisco Nexus1000V for any update/delete.
"""
LOG.debug(_('_poll_policies'))
try:
n1kvclient = n1kv_client.Client()
policy_profiles = n1kvclient.list_events(event_type, epoch)
if policy_profiles:
for profile in policy_profiles['body'][c_const.SET]:
if c_const.NAME in profile:
# Extract commands from the events XML.
cmd = profile[c_const.PROPERTIES]['cmd']
cmds = cmd.split(';')
cmdwords = cmds[1].split()
profile_name = profile[c_const.
PROPERTIES][c_const.NAME]
# Delete the policy profile from db if deleted on VSM
if 'no' in cmdwords[0]:
p = self._get_policy_profile_by_name(profile_name)
if p:
self._delete_policy_profile(p['id'])
# Add policy profile to neutron DB idempotently
elif c_const.ID in profile[c_const.PROPERTIES]:
profile_id = profile[c_const.
PROPERTIES][c_const.ID]
self._add_policy_profile(
profile_name, profile_id, tenant_id)
# Replace tenant-id for profile bindings with admin's tenant-id
self._remove_all_fake_policy_profiles()
except (cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed):
LOG.warning(_('No policy profile updated from VSM'))
def _extend_network_dict_provider(self, context, network):
"""Add extended network parameters."""
binding = n1kv_db_v2.get_network_binding(context.session,

View File

@ -18,7 +18,7 @@
# @author: Sourabh Patwardhan, Cisco Systems Inc.
from neutron.openstack.common import log as logging
from neutron.plugins.cisco.common import cisco_exceptions
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.n1kv.n1kv_client import Client as n1kv_client
LOG = logging.getLogger(__name__)
@ -36,15 +36,26 @@ class TestClient(n1kv_client):
def __init__(self, **kwargs):
self.broken = False
self.inject_params = False
self.total_profiles = 2
super(TestClient, self).__init__()
def _get_total_profiles(self):
return self.total_profiles
def _do_request(self, method, action, body=None, headers=None):
if self.broken:
raise cisco_exceptions.VSMError(reason='VSM:Internal Server Error')
raise c_exc.VSMError(reason='VSM:Internal Server Error')
if self.inject_params and body:
body['invalidKey'] = 'catchMeIfYouCan'
if method == 'POST':
return _validate_resource(action, body)
elif method == 'GET':
if 'virtual-port-profile' in action:
profiles = _policy_profile_generator_xml(
self._get_total_profiles())
return self._deserialize(profiles, 200)
else:
raise c_exc.VSMError(reason='VSM:Internal Server Error')
class TestClientInvalidRequest(TestClient):
@ -62,10 +73,33 @@ def _validate_resource(action, body=None):
if 'vm-network' in action and 'port' not in action:
vmnetwork_set = set(_resource_metadata['vmnetwork'])
if body_set - vmnetwork_set:
raise cisco_exceptions.VSMError(reason='Invalid Request')
raise c_exc.VSMError(reason='Invalid Request')
elif 'port' in action:
port_set = set(_resource_metadata['port'])
if body_set - port_set:
raise cisco_exceptions.VSMError(reason='Invalid Request')
raise c_exc.VSMError(reason='Invalid Request')
else:
return
def _policy_profile_generator_xml(total_profiles):
"""
Generate policy profile response in XML format.
:param total_profiles: integer representing total number of profiles to
return
"""
xml = ["""<?xml version="1.0" encoding="utf-8"?>
<set name="virtual_port_profile_set">"""]
template = (
'<instance name="%(num)d"'
' url="/api/n1k/virtual-port-profile/%(num)s">'
'<properties>'
'<id>00000000-0000-0000-0000-00000000000%(num)s</id>'
'<name>pp-%(num)s</name>'
'</properties>'
'</instance>'
)
xml.extend(template % {'num': n} for n in range(1, total_profiles + 1))
xml.append("</set>")
return ''.join(xml)

View File

@ -25,6 +25,7 @@ from neutron.api.v2 import attributes
from neutron import context
import neutron.db.api as db
from neutron.extensions import portbindings
from neutron import manager
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.db import n1kv_db_v2
from neutron.plugins.cisco.db import network_db_v2 as cdb
@ -69,7 +70,7 @@ class FakeResponse(object):
def _fake_setup_vsm(self):
"""Fake establish Communication with Cisco Nexus1000V VSM."""
self.agent_vsm = True
self._poll_policies(event_type="port_profile")
self._populate_policy_profiles()
class NetworkProfileTestExtensionManager(object):
@ -506,6 +507,55 @@ class TestN1kvPorts(test_plugin.TestPortsV2,
client_patch.stop()
class TestN1kvPolicyProfiles(N1kvPluginTestCase):
def test_populate_policy_profile(self):
client_patch = patch(n1kv_client.__name__ + ".Client",
new=fake_client.TestClient)
client_patch.start()
instance = n1kv_neutron_plugin.N1kvNeutronPluginV2()
instance._populate_policy_profiles()
db_session = db.get_session()
profile = n1kv_db_v2.get_policy_profile(
db_session, '00000000-0000-0000-0000-000000000001')
self.assertEqual('pp-1', profile['name'])
client_patch.stop()
def test_populate_policy_profile_delete(self):
# Patch the Client class with the TestClient class
with patch(n1kv_client.__name__ + ".Client",
new=fake_client.TestClient):
# Patch the _get_total_profiles() method to return a custom value
with patch(fake_client.__name__ +
'.TestClient._get_total_profiles') as obj_inst:
# Return 3 policy profiles
obj_inst.return_value = 3
plugin = manager.NeutronManager.get_plugin()
plugin._populate_policy_profiles()
db_session = db.get_session()
profile = n1kv_db_v2.get_policy_profile(
db_session, '00000000-0000-0000-0000-000000000001')
# Verify that DB contains only 3 policy profiles
self.assertEqual('pp-1', profile['name'])
profile = n1kv_db_v2.get_policy_profile(
db_session, '00000000-0000-0000-0000-000000000002')
self.assertEqual('pp-2', profile['name'])
profile = n1kv_db_v2.get_policy_profile(
db_session, '00000000-0000-0000-0000-000000000003')
self.assertEqual('pp-3', profile['name'])
self.assertRaises(c_exc.PolicyProfileIdNotFound,
n1kv_db_v2.get_policy_profile,
db_session,
'00000000-0000-0000-0000-000000000004')
# Return 2 policy profiles
obj_inst.return_value = 2
plugin._populate_policy_profiles()
# Verify that the third policy profile is deleted
self.assertRaises(c_exc.PolicyProfileIdNotFound,
n1kv_db_v2.get_policy_profile,
db_session,
'00000000-0000-0000-0000-000000000003')
class TestN1kvNetworks(test_plugin.TestNetworksV2,
N1kvPluginTestCase):