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()
"""
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.
"""
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):
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,
# @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__)
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):
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)
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
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):
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):