]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Update Cisco N1KV plugin to VSM REST api calls
authorAbhishek Raut <abhraut@cisco.com>
Thu, 3 Oct 2013 06:32:02 +0000 (23:32 -0700)
committerAbhishek Raut <abhraut@cisco.com>
Wed, 16 Oct 2013 01:01:08 +0000 (18:01 -0700)
Modify the existing REST calls from the plugin to VSM to update the
attributes and use UUIDs as index, instead of string names, for all
the resources.

Change-Id: Icb4950ea7c6f036e9a25ee79e3f5fe30d40f47de
Closes-Bug: 1233802

neutron/plugins/cisco/common/cisco_constants.py
neutron/plugins/cisco/db/n1kv_db_v2.py
neutron/plugins/cisco/extensions/n1kv_profile.py
neutron/plugins/cisco/extensions/network_profile.py
neutron/plugins/cisco/n1kv/n1kv_client.py
neutron/plugins/cisco/n1kv/n1kv_neutron_plugin.py
neutron/tests/unit/cisco/n1kv/test_n1kv_plugin.py

index ca2b8b8ddb4c04243dafe9343f9a47af630da806..3b0d59b056277f36615737a980f3cf1c10e0144a 100644 (file)
@@ -105,6 +105,7 @@ MAPPING = 'mapping'
 SEGMENTS = 'segments'
 SEGMENT = 'segment'
 BRIDGE_DOMAIN_SUFFIX = '_bd'
+LOGICAL_NETWORK_SUFFIX = '_log_net'
 ENCAPSULATION_PROFILE_SUFFIX = '_profile'
 
 UUID_LENGTH = 36
index 8fe347de77f143eba54fb2b89404ae9f09c0247e..7cf36d0d09642cc2fe41541195f0b08d2e8cfce2 100644 (file)
@@ -849,6 +849,7 @@ def create_network_profile(db_session, network_profile):
             kwargs["multicast_ip_range"] = network_profile[
                 "multicast_ip_range"]
             kwargs["segment_range"] = network_profile["segment_range"]
+            kwargs["sub_type"] = network_profile["sub_type"]
         elif network_profile["segment_type"] == c_const.NETWORK_TYPE_TRUNK:
             kwargs["sub_type"] = network_profile["sub_type"]
         net_profile = n1kv_models_v2.NetworkProfile(**kwargs)
index fdf89e2a3862587ce59414dda242443abda641b2..58287b09883c98a0e22e7d367a453c4af974747e 100644 (file)
@@ -30,7 +30,7 @@ MEMBER_SEGMENTS = 'n1kv:member_segments'
 
 EXTENDED_ATTRIBUTES_2_0 = {
     'networks': {
-        PROFILE_ID: {'allow_post': True, 'allow_put': True,
+        PROFILE_ID: {'allow_post': True, 'allow_put': False,
                      'validate': {'type:regex': attributes.UUID_PATTERN},
                      'default': attributes.ATTR_NOT_SPECIFIED,
                      'is_visible': True},
@@ -48,7 +48,7 @@ EXTENDED_ATTRIBUTES_2_0 = {
                           'is_visible': True},
     },
     'ports': {
-        PROFILE_ID: {'allow_post': True, 'allow_put': True,
+        PROFILE_ID: {'allow_post': True, 'allow_put': False,
                      'validate': {'type:regex': attributes.UUID_PATTERN},
                      'default': attributes.ATTR_NOT_SPECIFIED,
                      'is_visible': True}
index aef5c925f9dcbe229bad83d294e3ec025c478d07..64795c1062042d30ef11d6a46fb3278a4673814b 100644 (file)
@@ -32,20 +32,18 @@ RESOURCE_ATTRIBUTE_MAP = {
                'is_visible': True},
         'name': {'allow_post': True, 'allow_put': True,
                  'is_visible': True, 'default': ''},
-        'segment_type': {'allow_post': True, 'allow_put': True,
+        'segment_type': {'allow_post': True, 'allow_put': False,
                          'is_visible': True, 'default': ''},
-        'sub_type': {'allow_post': True, 'allow_put': True,
+        'sub_type': {'allow_post': True, 'allow_put': False,
                      'is_visible': True,
                      'default': attributes.ATTR_NOT_SPECIFIED},
         'segment_range': {'allow_post': True, 'allow_put': True,
                           'is_visible': True, 'default': ''},
-        'sub_type': {'allow_post': True, 'allow_put': True,
-                     'is_visible': True, 'default': ''},
         'multicast_ip_range': {'allow_post': True, 'allow_put': True,
                                'is_visible': True, 'default': '0.0.0.0'},
         'multicast_ip_index': {'allow_post': False, 'allow_put': False,
                                'is_visible': False, 'default': '0'},
-        'physical_network': {'allow_post': True, 'allow_put': True,
+        'physical_network': {'allow_post': True, 'allow_put': False,
                              'is_visible': True, 'default': ''},
         'tenant_id': {'allow_post': True, 'allow_put': False,
                       'is_visible': False, 'default': ''},
index 1334b161aca1b0e7518f36f87ca6eb709bb610f1..f6efd6b5e009e767a51b18a87117bc85f8b9a191 100644 (file)
@@ -126,11 +126,8 @@ class Client(object):
 
     # Define paths for the URI where the client connects for HTTP requests.
     port_profiles_path = "/virtual-port-profile"
-    network_segments_path = "/network-segment"
     network_segment_path = "/network-segment/%s"
-    network_segment_pools_path = "/network-segment-pool"
     network_segment_pool_path = "/network-segment-pool/%s"
-    ip_pools_path = "/ip-pool-template"
     ip_pool_path = "/ip-pool-template/%s"
     ports_path = "/kvm/vm-network/%s/ports"
     port_path = "/kvm/vm-network/%s/ports/%s"
@@ -138,7 +135,6 @@ class Client(object):
     vm_network_path = "/kvm/vm-network/%s"
     bridge_domains_path = "/kvm/bridge-domain"
     bridge_domain_path = "/kvm/bridge-domain/%s"
-    logical_networks_path = "/logical-network"
     logical_network_path = "/logical-network/%s"
     events_path = "/kvm/events"
     clusters_path = "/cluster"
@@ -179,9 +175,10 @@ class Client(object):
         :param network: network dict
         :param overlay_subtype: string representing subtype of overlay network
         """
-        body = {'name': network['name'] + c_const.BRIDGE_DOMAIN_SUFFIX,
+        body = {'name': network['id'] + c_const.BRIDGE_DOMAIN_SUFFIX,
                 'segmentId': network[providernet.SEGMENTATION_ID],
-                'subType': overlay_subtype}
+                'subType': overlay_subtype,
+                'tenantId': network['tenant_id']}
         if overlay_subtype == c_const.NETWORK_SUBTYPE_NATIVE_VXLAN:
             body['groupIp'] = network[n1kv_profile.MULTICAST_IP]
         return self._post(self.bridge_domains_path,
@@ -193,7 +190,7 @@ class Client(object):
 
         :param name: name of the bridge domain to be deleted
         """
-        return self._delete(self.bridge_domain_path % (name))
+        return self._delete(self.bridge_domain_path % name)
 
     def create_network_segment(self, network, network_profile):
         """
@@ -202,14 +199,15 @@ class Client(object):
         :param network: network dict
         :param network_profile: network profile dict
         """
-        body = {'name': network['name'],
+        body = {'publishName': network['name'],
+                'description': network['name'],
                 'id': network['id'],
-                'mode': 'access',
-                'networkSegmentPool': network_profile['name'], }
+                'tenantId': network['tenant_id'],
+                'networkSegmentPool': network_profile['id'], }
         if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VLAN:
             body['vlan'] = network[providernet.SEGMENTATION_ID]
         elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
-            body['bridgeDomain'] = (network['name'] +
+            body['bridgeDomain'] = (network['id'] +
                                     c_const.BRIDGE_DOMAIN_SUFFIX)
         if network_profile['segment_type'] == c_const.NETWORK_TYPE_TRUNK:
             body['mode'] = c_const.NETWORK_TYPE_TRUNK
@@ -218,88 +216,99 @@ class Client(object):
                 body['addSegments'] = network['add_segment_list']
                 body['delSegments'] = network['del_segment_list']
             else:
-                body['encapProfile'] = (network['name'] +
+                body['encapProfile'] = (network['id'] +
                                         c_const.ENCAPSULATION_PROFILE_SUFFIX)
         else:
             body['mode'] = 'access'
             body['segmentType'] = network_profile['segment_type']
-        return self._post(self.network_segments_path,
+        return self._post(self.network_segment_path % network['id'],
                           body=body)
 
-    def update_network_segment(self, network_segment_name, body):
+    def update_network_segment(self, network_segment_id, body):
         """
         Update a network segment on the VSM.
 
         Network segment on VSM can be updated to associate it with an ip-pool
         or update its description and segment id.
 
-        :param network_segment_name: name of the network segment
+        :param network_segment_id: UUID representing the network segment
         :param body: dict of arguments to be updated
         """
-        return self._post(self.network_segment_path % (network_segment_name),
+        return self._post(self.network_segment_path % network_segment_id,
                           body=body)
 
-    def delete_network_segment(self, network_segment_name):
+    def delete_network_segment(self, network_segment_id):
         """
         Delete a network segment on the VSM.
 
-        :param network_segment_name: name of the network segment
+        :param network_segment_id: UUID representing the network segment
         """
-        return self._delete(self.network_segment_path % (network_segment_name))
+        return self._delete(self.network_segment_path % network_segment_id)
 
-    def create_logical_network(self, network_profile):
+    def create_logical_network(self, network_profile, tenant_id):
         """
         Create a logical network on the VSM.
 
         :param network_profile: network profile dict
+        :param tenant_id: UUID representing the tenant
         """
         LOG.debug(_("Logical network"))
-        body = {'name': network_profile['name']}
-        return self._post(self.logical_networks_path,
+        body = {'description': network_profile['name'],
+                'tenantId': tenant_id}
+        logical_network_name = (network_profile['id'] +
+                                c_const.LOGICAL_NETWORK_SUFFIX)
+        return self._post(self.logical_network_path % logical_network_name,
                           body=body)
 
-    def delete_logical_network(self, network_profile):
+    def delete_logical_network(self, logical_network_name):
         """
         Delete a logical network on VSM.
 
-        :param network_profile: network profile dict
+        :param logical_network_name: string representing name of the logical
+                                     network
         """
         return self._delete(
-            self.logical_network_path % (network_profile['name']))
+            self.logical_network_path % logical_network_name)
 
-    def create_network_segment_pool(self, network_profile):
+    def create_network_segment_pool(self, network_profile, tenant_id):
         """
         Create a network segment pool on the VSM.
 
         :param network_profile: network profile dict
+        :param tenant_id: UUID representing the tenant
         """
         LOG.debug(_("network_segment_pool"))
+        logical_network_name = (network_profile['id'] +
+                                c_const.LOGICAL_NETWORK_SUFFIX)
         body = {'name': network_profile['name'],
+                'description': network_profile['name'],
                 'id': network_profile['id'],
-                'logicalNetwork': network_profile['name']}
-        return self._post(self.network_segment_pools_path,
-                          body=body)
+                'logicalNetwork': logical_network_name,
+                'tenantId': tenant_id}
+        return self._post(
+            self.network_segment_pool_path % network_profile['id'],
+            body=body)
 
-    def update_network_segment_pool(self, network_segment_pool, body):
+    def update_network_segment_pool(self, network_profile):
         """
         Update a network segment pool on the VSM.
 
-        :param network_segment_pool: string representing the name of network
-                                     segment pool to be updated
-        :param body: dictionary representing key values of network segment
-                     pool which need to be updated
+        :param network_profile: network profile dict
         """
+        body = {'name': network_profile['name'],
+                'description': network_profile['name']}
         return self._post(self.network_segment_pool_path %
-                          (network_segment_pool), body=body)
+                          network_profile['id'], body=body)
 
-    def delete_network_segment_pool(self, network_segment_pool_name):
+    def delete_network_segment_pool(self, network_segment_pool_id):
         """
         Delete a network segment pool on the VSM.
 
-        :param network_segment_pool_name: name of the network segment pool
+        :param network_segment_pool_id: UUID representing the network
+                                        segment pool
         """
         return self._delete(self.network_segment_pool_path %
-                            (network_segment_pool_name))
+                            network_segment_pool_id)
 
     def create_ip_pool(self, subnet):
         """
@@ -328,38 +337,38 @@ class Client(object):
         body = {'addressRangeStart': address_range_start,
                 'addressRangeEnd': address_range_end,
                 'ipAddressSubnet': netmask,
-                'name': subnet['name'],
+                'description': subnet['name'],
                 'gateway': subnet['gateway_ip'],
-                'networkAddress': network_address}
-        return self._post(self.ip_pools_path,
+                'networkAddress': network_address,
+                'tenantId': subnet['tenant_id']}
+        return self._post(self.ip_pool_path % subnet['id'],
                           body=body)
 
-    def delete_ip_pool(self, subnet_name):
+    def delete_ip_pool(self, subnet_id):
         """
         Delete an ip-pool on the VSM.
 
-        :param subnet_name: name of the subnet
+        :param subnet_id: UUID representing the subnet
         """
-        return self._delete(self.ip_pool_path % (subnet_name))
+        return self._delete(self.ip_pool_path % subnet_id)
 
     def create_vm_network(self,
                           port,
                           vm_network_name,
-                          policy_profile,
-                          network_name):
+                          policy_profile):
         """
         Create a VM network on the VSM.
 
         :param port: port dict
         :param vm_network_name: name of the VM network
         :param policy_profile: policy profile dict
-        :param network_name: string representing the name of the network
         """
         body = {'name': vm_network_name,
                 'networkSegmentId': port['network_id'],
-                'networkSegment': network_name,
+                'networkSegment': port['network_id'],
                 'portProfile': policy_profile['name'],
                 'portProfileId': policy_profile['id'],
+                'tenantId': port['tenant_id'],
                 }
         return self._post(self.vm_networks_path,
                           body=body)
@@ -370,7 +379,7 @@ class Client(object):
 
         :param vm_network_name: name of the VM network
         """
-        return self._delete(self.vm_network_path % (vm_network_name))
+        return self._delete(self.vm_network_path % vm_network_name)
 
     def create_n1kv_port(self, port, vm_network_name):
         """
@@ -381,7 +390,9 @@ class Client(object):
         """
         body = {'id': port['id'],
                 'macAddress': port['mac_address']}
-        return self._post(self.ports_path % (vm_network_name),
+        if port.get('fixed_ips'):
+            body['ipAddress'] = port['fixed_ips'][0]['ip_address']
+        return self._post(self.ports_path % vm_network_name,
                           body=body)
 
     def update_n1kv_port(self, vm_network_name, port_id, body):
@@ -394,7 +405,7 @@ class Client(object):
         :param port_id: UUID of the port
         :param body: dict of the arguments to be updated
         """
-        return self._post(self.port_path % ((vm_network_name), (port_id)),
+        return self._post(self.port_path % (vm_network_name, port_id),
                           body=body)
 
     def delete_n1kv_port(self, vm_network_name, port_id):
@@ -404,7 +415,7 @@ class Client(object):
         :param vm_network_name: name of the VM network which imports this port
         :param port_id: UUID of the port
         """
-        return self._delete(self.port_path % ((vm_network_name), (port_id)))
+        return self._delete(self.port_path % (vm_network_name, port_id))
 
     def _do_request(self, method, action, body=None,
                     headers=None):
@@ -484,7 +495,7 @@ class Client(object):
         """
         if not format:
             format = self.format
-        return "application/%s" % (format)
+        return "application/%s" % format
 
     def _delete(self, action, body=None, headers=None):
         return self._do_request("DELETE", action, body=body,
@@ -548,7 +559,7 @@ class Client(object):
         :param body: mapping dictionary
         """
         return self._post(self.encap_profile_path
-                          % (profile_name), body=body)
+                          % profile_name, body=body)
 
     def delete_encapsulation_profile(self, name):
         """
@@ -556,4 +567,4 @@ class Client(object):
 
         :param name: name of the encapsulation profile to be deleted
         """
-        return self._delete(self.encap_profile_path % (name))
+        return self._delete(self.encap_profile_path % name)
index 896ce0ffe6960e6c6ec7e106766c2506e4c21c91..f2b9149aecce2a183b4a8d813b812de4fd284483 100644 (file)
@@ -697,15 +697,16 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
 
         return profile_id
 
-    def _send_create_logical_network_request(self, network_profile):
+    def _send_create_logical_network_request(self, network_profile, tenant_id):
         """
         Send create logical network request to VSM.
 
         :param network_profile: network profile dictionary
+        :param tenant_id: UUID representing the tenant
         """
         LOG.debug(_('_send_create_logical_network'))
         n1kvclient = n1kv_client.Client()
-        n1kvclient.create_logical_network(network_profile)
+        n1kvclient.create_logical_network(network_profile, tenant_id)
 
     def _send_delete_logical_network_request(self, network_profile):
         """
@@ -715,7 +716,9 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         """
         LOG.debug('_send_delete_logical_network')
         n1kvclient = n1kv_client.Client()
-        n1kvclient.delete_logical_network(network_profile)
+        logical_network_name = (network_profile['id'] +
+                                c_const.LOGICAL_NETWORK_SUFFIX)
+        n1kvclient.delete_logical_network(logical_network_name)
 
     def _send_create_network_profile_request(self, context, profile):
         """
@@ -726,7 +729,17 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         """
         LOG.debug(_('_send_create_network_profile_request: %s'), profile['id'])
         n1kvclient = n1kv_client.Client()
-        n1kvclient.create_network_segment_pool(profile)
+        n1kvclient.create_network_segment_pool(profile, context.tenant_id)
+
+    def _send_update_network_profile_request(self, profile):
+        """
+        Send update network profile request to VSM.
+
+        :param profile: network profile dictionary
+        """
+        LOG.debug(_('_send_update_network_profile_request: %s'), profile['id'])
+        n1kvclient = n1kv_client.Client()
+        n1kvclient.update_network_segment_pool(profile)
 
     def _send_delete_network_profile_request(self, profile):
         """
@@ -737,7 +750,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         LOG.debug(_('_send_delete_network_profile_request: %s'),
                   profile['name'])
         n1kvclient = n1kv_client.Client()
-        n1kvclient.delete_network_segment_pool(profile['name'])
+        n1kvclient.delete_network_segment_pool(profile['id'])
 
     def _send_create_network_request(self, context, network, segment_pairs):
         """
@@ -786,9 +799,9 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         profile = n1kv_db_v2.get_network_profile(
             db_session, network[n1kv_profile.PROFILE_ID])
         n1kvclient = n1kv_client.Client()
-        body = {'name': network['name'],
+        body = {'publishName': network['name'],
                 'id': network['id'],
-                'networkDefinition': profile['name'],
+                'networkSegmentPool': profile['id'],
                 'vlan': network[providernet.SEGMENTATION_ID],
                 'mode': 'access',
                 'segmentType': profile['segment_type'],
@@ -806,7 +819,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             LOG.debug(_('add_segments=%s'), body['addSegments'])
             LOG.debug(_('del_segments=%s'), body['delSegments'])
             if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
-                encap_profile = (network['name'] +
+                encap_profile = (network['id'] +
                                  c_const.ENCAPSULATION_PROFILE_SUFFIX)
                 encap_dict = {'name': encap_profile,
                               'addMappings': (
@@ -817,7 +830,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                                                            del_segments))}
                 n1kvclient.update_encapsulation_profile(context, encap_profile,
                                                         encap_dict)
-        n1kvclient.update_network_segment(network['name'], body)
+        n1kvclient.update_network_segment(network['id'], body)
 
     def _send_delete_network_request(self, context, network):
         """
@@ -832,13 +845,13 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         n1kvclient = n1kv_client.Client()
         session = context.session
         if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
-            name = network['name'] + c_const.BRIDGE_DOMAIN_SUFFIX
+            name = network['id'] + c_const.BRIDGE_DOMAIN_SUFFIX
             n1kvclient.delete_bridge_domain(name)
         elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_TRUNK:
             profile = self.get_network_profile(
                 context, network[n1kv_profile.PROFILE_ID])
             if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
-                profile_name = (network['name'] +
+                profile_name = (network['id'] +
                                 c_const.ENCAPSULATION_PROFILE_SUFFIX)
                 n1kvclient.delete_encapsulation_profile(profile_name)
         elif (network[providernet.NETWORK_TYPE] ==
@@ -859,7 +872,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                     profile_dict['delSegments'].append(mapping_dict)
                 n1kvclient.update_encapsulation_profile(context, profile,
                                                         profile_dict)
-        n1kvclient.delete_network_segment(network['name'])
+        n1kvclient.delete_network_segment(network['id'])
 
     def _send_create_subnet_request(self, context, subnet):
         """
@@ -869,11 +882,10 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         :param subnet: subnet dictionary
         """
         LOG.debug(_('_send_create_subnet_request: %s'), subnet['id'])
-        network = self.get_network(context, subnet['network_id'])
         n1kvclient = n1kv_client.Client()
         n1kvclient.create_ip_pool(subnet)
-        body = {'ipPoolName': subnet['name']}
-        n1kvclient.update_network_segment(network['name'], body=body)
+        body = {'ipPool': subnet['id']}
+        n1kvclient.update_network_segment(subnet['network_id'], body=body)
 
     def _send_delete_subnet_request(self, context, subnet):
         """
@@ -883,11 +895,10 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         :param subnet: subnet dictionary
         """
         LOG.debug(_('_send_delete_subnet_request: %s'), subnet['name'])
-        network = self.get_network(context, subnet['network_id'])
-        body = {'ipPoolName': subnet['name'], 'deleteSubnet': True}
+        body = {'ipPool': subnet['id'], 'deleteSubnet': True}
         n1kvclient = n1kv_client.Client()
-        n1kvclient.update_network_segment(network['name'], body=body)
-        n1kvclient.delete_ip_pool(subnet['name'])
+        n1kvclient.update_network_segment(subnet['network_id'], body=body)
+        n1kvclient.delete_ip_pool(subnet['id'])
 
     def _send_create_port_request(self, context, port):
         """
@@ -908,7 +919,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         except cisco_exceptions.VMNetworkNotFound:
             policy_profile = n1kv_db_v2.get_policy_profile(
                 context.session, port[n1kv_profile.PROFILE_ID])
-            network = self.get_network(context, port['network_id'])
             vm_network_name = (c_const.VM_NETWORK_NAME_PREFIX +
                                str(port[n1kv_profile.PROFILE_ID]) +
                                "_" + str(port['network_id']))
@@ -921,8 +931,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             n1kvclient = n1kv_client.Client()
             n1kvclient.create_vm_network(port,
                                          vm_network_name,
-                                         policy_profile,
-                                         network['name'])
+                                         policy_profile)
             n1kvclient.create_n1kv_port(port, vm_network_name)
         else:
             vm_network_name = vm_network['name']
@@ -994,7 +1003,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         (network_type, physical_network,
          segmentation_id) = self._process_provider_create(context,
                                                           network['network'])
-        self._add_dummy_profile_only_if_testing(network)
         profile_id = self._process_network_profile(context, network['network'])
         segment_pairs = None
         LOG.debug(_('Create network: profile_id=%s'), profile_id)
@@ -1219,8 +1227,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
         :param port: port dictionary
         :returns: port object
         """
-        self._add_dummy_profile_only_if_testing(port)
-
         if ('device_id' in port['port'] and port['port']['device_owner'] in
             ['network:dhcp', 'network:router_interface']):
             p_profile_name = c_conf.CISCO_N1K.network_node_policy_profile
@@ -1259,15 +1265,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                 LOG.debug(_("Created port: %s"), pt)
                 return pt
 
-    def _add_dummy_profile_only_if_testing(self, obj):
-        """
-        Method to be patched by the test_n1kv_plugin module to
-        inject n1kv:profile_id into the network/port object, since the plugin
-        tests for its existence. This method does not affect
-        the plugin code in any way.
-        """
-        pass
-
     def update_port(self, context, id, port):
         """
         Update port parameters.
@@ -1449,7 +1446,8 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                 n1kv_db_v2.sync_vxlan_allocations(context.session,
                                                   self.vxlan_id_ranges)
         try:
-            self._send_create_logical_network_request(_network_profile)
+            self._send_create_logical_network_request(_network_profile,
+                                                      context.tenant_id)
         except(cisco_exceptions.VSMError,
                cisco_exceptions.VSMConnectionFailed):
             super(N1kvNeutronPluginV2, self).delete_network_profile(
@@ -1489,3 +1487,20 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             n1kv_db_v2.delete_vxlan_allocations(context.session,
                                                 self.delete_vxlan_ranges)
         self._send_delete_network_profile_request(_network_profile)
+
+    def update_network_profile(self, context, net_profile_id, network_profile):
+        """
+        Update a network profile.
+
+        :param context: neutron api request context
+        :param net_profile_id: UUID of the network profile to update
+        :param network_profile: dictionary containing network profile object
+        """
+        session = context.session
+        with session.begin(subtransactions=True):
+            net_p = (super(N1kvNeutronPluginV2, self).
+                     update_network_profile(context,
+                                            net_profile_id,
+                                            network_profile))
+            self._send_update_network_profile_request(net_p)
+            return net_p
index e40cab08897327a6e04c59fea9a889ddd35327df..a3b43e806a33a7e771ecff70e3a012451dbd7a57 100644 (file)
 # @author: Abhishek Raut, Cisco Systems Inc.
 
 from mock import patch
+import os
+from oslo.config import cfg
 
+from neutron.api.v2 import attributes
+from neutron.common.test_lib import test_config
 from neutron import context
 import neutron.db.api as db
 from neutron.plugins.cisco.db import n1kv_db_v2
-from neutron.plugins.cisco.db import n1kv_models_v2
 from neutron.plugins.cisco.db import network_db_v2 as cdb
+from neutron.plugins.cisco import extensions
 from neutron.plugins.cisco.extensions import n1kv_profile
+from neutron.plugins.cisco.extensions import network_profile
 from neutron.plugins.cisco.n1kv import n1kv_client
 from neutron.plugins.cisco.n1kv import n1kv_neutron_plugin
 from neutron.tests import base
+from neutron.tests.unit import test_api_v2
 from neutron.tests.unit import test_db_plugin as test_plugin
 
 
@@ -51,41 +57,30 @@ class FakeResponse(object):
         return self.buffer
 
 
-def _fake_add_dummy_profile_for_test(self, obj):
-    """
-    Replacement for a function in the N1KV neutron plugin module.
-
-    Since VSM is not available at the time of tests, we have no
-    policy profiles. Hence we inject a dummy policy/network profile into the
-    port/network object.
-    """
-    dummy_profile_name = "dummy_profile"
-    dummy_tenant_id = "test-tenant"
-    db_session = db.get_session()
-    if 'port' in obj:
-        dummy_profile_id = "00000000-1111-1111-1111-000000000000"
-        self._add_policy_profile(dummy_profile_name,
-                                 dummy_profile_id,
-                                 dummy_tenant_id)
-        obj['port'][n1kv_profile.PROFILE_ID] = dummy_profile_id
-    elif 'network' in obj:
-        profile = {'name': 'dummy_profile',
-                   'segment_type': 'vlan',
-                   'physical_network': 'phsy1',
-                   'segment_range': '3968-4047'}
-        self.network_vlan_ranges = {profile[
-            'physical_network']: [(3968, 4047)]}
-        n1kv_db_v2.sync_vlan_allocations(db_session, self.network_vlan_ranges)
-        np = n1kv_db_v2.create_network_profile(db_session, profile)
-        obj['network'][n1kv_profile.PROFILE_ID] = np.id
-
-
 def _fake_setup_vsm(self):
     """Fake establish Communication with Cisco Nexus1000V VSM."""
     self.agent_vsm = True
     self._poll_policies(event_type="port_profile")
 
 
+class NetworkProfileTestExtensionManager(object):
+
+    def get_resources(self):
+        # Add the resources to the global attribute map
+        # This is done here as the setup process won't
+        # initialize the main API router which extends
+        # the global attribute map
+        attributes.RESOURCE_ATTRIBUTE_MAP.update(
+            network_profile.RESOURCE_ATTRIBUTE_MAP)
+        return network_profile.Network_profile.get_resources()
+
+    def get_actions(self):
+        return []
+
+    def get_request_extensions(self):
+        return []
+
+
 class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
 
     _plugin_name = ('neutron.plugins.cisco.n1kv.'
@@ -96,31 +91,38 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
     DEFAULT_RESP_BODY = ""
     DEFAULT_RESP_CODE = 200
     DEFAULT_CONTENT_TYPE = ""
+    fmt = "json"
+
+    def _make_test_policy_profile(self, name='service_profile'):
+        """
+        Create a policy profile record for testing purpose.
 
-    def _make_test_policy_profile(self, id):
-        """Create a policy profile record for testing purpose."""
-        profile = {'id': id,
-                   'name': 'TestGrizzlyPP'}
-        profile_obj = n1kv_db_v2.create_policy_profile(profile)
-        return profile_obj
-
-    def _make_test_profile(self):
-        """Create a profile record for testing purposes."""
-        alloc_obj = n1kv_models_v2.N1kvVlanAllocation(physical_network='foo',
-                                                      vlan_id=123)
-        alloc_obj.allocated = False
-        segment_range = "100-900"
-        segment_type = 'vlan'
-        physical_network = 'phys1'
-        profile_obj = n1kv_models_v2.NetworkProfile(
-            name="test_np",
-            segment_type=segment_type,
-            segment_range=segment_range,
-            physical_network=physical_network)
-        session = db.get_session()
-        session.add(profile_obj)
-        session.flush()
-        return profile_obj
+        :param name: string representing the name of the policy profile to
+                     create. Default argument value chosen to correspond to the
+                     default name specified in config.py file.
+        """
+        uuid = test_api_v2._uuid()
+        profile = {'id': uuid,
+                   'name': name}
+        return n1kv_db_v2.create_policy_profile(profile)
+
+    def _make_test_profile(self, name='default_network_profile'):
+        """
+        Create a profile record for testing purposes.
+
+        :param name: string representing the name of the network profile to
+                     create. Default argument value chosen to correspond to the
+                     default name specified in config.py file.
+        """
+        db_session = db.get_session()
+        profile = {'name': name,
+                   'segment_type': 'vlan',
+                   'physical_network': 'phsy1',
+                   'segment_range': '3968-4047'}
+        self.network_vlan_ranges = {profile[
+            'physical_network']: [(3968, 4047)]}
+        n1kv_db_v2.sync_vlan_allocations(db_session, self.network_vlan_ranges)
+        return n1kv_db_v2.create_network_profile(db_session, profile)
 
     def setUp(self):
         """
@@ -199,24 +201,39 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
         fake_get_cred_name.return_value = {"user_name": "admin",
                                            "password": "admin_password"}
 
-        # Patch a dummy profile creation into the N1K plugin code. The original
-        # function in the plugin is a noop for production, but during test, we
-        # need it to return a dummy network profile.
-        (n1kv_neutron_plugin.N1kvNeutronPluginV2.
-         _add_dummy_profile_only_if_testing) = _fake_add_dummy_profile_for_test
-
         n1kv_neutron_plugin.N1kvNeutronPluginV2._setup_vsm = _fake_setup_vsm
 
+        test_config['plugin_name_v2'] = self._plugin_name
+        cfg.CONF.set_override('api_extensions_path',
+                              os.path.dirname(extensions.__file__))
+        self.addCleanup(cfg.CONF.reset)
+        ext_mgr = NetworkProfileTestExtensionManager()
+        test_config['extension_manager'] = ext_mgr
+        self.addCleanup(self.restore_test_config)
+
+        # Save the original RESOURCE_ATTRIBUTE_MAP
+        self.saved_attr_map = {}
+        for resource, attrs in attributes.RESOURCE_ATTRIBUTE_MAP.items():
+            self.saved_attr_map[resource] = attrs.copy()
+        # Update the RESOURCE_ATTRIBUTE_MAP with n1kv specific extended attrs.
+        attributes.RESOURCE_ATTRIBUTE_MAP["networks"].update(
+            n1kv_profile.EXTENDED_ATTRIBUTES_2_0["networks"])
+        attributes.RESOURCE_ATTRIBUTE_MAP["ports"].update(
+            n1kv_profile.EXTENDED_ATTRIBUTES_2_0["ports"])
+        self.addCleanup(self.restore_resource_attribute_map)
+        self.addCleanup(db.clear_db)
         super(N1kvPluginTestCase, self).setUp(self._plugin_name)
         # Create some of the database entries that we require.
-        profile_obj = self._make_test_profile()
-        policy_profile_obj = (self._make_test_policy_profile(
-                              '41548d21-7f89-4da0-9131-3d4fd4e8BBB8'))
-        # Additional args for create_network(), create_port(), etc.
-        self.more_args = {
-            "network": {"n1kv:profile_id": profile_obj.id},
-            "port": {"n1kv:profile_id": policy_profile_obj.id}
-        }
+        self._make_test_profile()
+        self._make_test_policy_profile()
+
+    def restore_resource_attribute_map(self):
+        # Restore the original RESOURCE_ATTRIBUTE_MAP
+        attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
+
+    def restore_test_config(self):
+        # Restore the original test_config
+        del test_config['plugin_name_v2']
 
     def test_plugin(self):
         self._make_network('json',
@@ -233,6 +250,56 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
         self.assertIn('tenant_id', body['networks'][0])
 
 
+class TestN1kvNetworkProfiles(N1kvPluginTestCase):
+    def _prepare_net_profile_data(self, segment_type):
+        netp = {'network_profile': {'name': 'netp1',
+                                    'segment_type': segment_type,
+                                    'tenant_id': self.tenant_id}}
+        if segment_type == 'vlan':
+            netp['network_profile']['segment_range'] = '100-200'
+            netp['network_profile']['physical_network'] = 'phys1'
+        elif segment_type == 'overlay':
+            netp['network_profile']['segment_range'] = '10000-10010'
+            netp['network_profile']['sub_type'] = 'enhanced'
+        return netp
+
+    def test_create_network_profile_plugin(self):
+        data = self._prepare_net_profile_data('vlan')
+        net_p_req = self.new_create_request('network_profiles', data)
+        res = net_p_req.get_response(self.ext_api)
+        self.assertEqual(res.status_int, 201)
+
+    def test_update_network_profile_physical_network_fail(self):
+        net_p = self._make_test_profile(name='netp1')
+        data = {'network_profile': {'physical_network': 'some-phys-net'}}
+        net_p_req = self.new_update_request('network_profiles',
+                                            data,
+                                            net_p['id'])
+        res = net_p_req.get_response(self.ext_api)
+        self.assertEqual(res.status_int, 400)
+
+    def test_update_network_profile_segment_type_fail(self):
+        net_p = self._make_test_profile(name='netp1')
+        data = {'network_profile': {'segment_type': 'overlay'}}
+        net_p_req = self.new_update_request('network_profiles',
+                                            data,
+                                            net_p['id'])
+        res = net_p_req.get_response(self.ext_api)
+        self.assertEqual(res.status_int, 400)
+
+    def test_update_network_profile_sub_type_fail(self):
+        net_p_dict = self._prepare_net_profile_data('overlay')
+        net_p_req = self.new_create_request('network_profiles', net_p_dict)
+        net_p = self.deserialize(self.fmt,
+                                 net_p_req.get_response(self.ext_api))
+        data = {'network_profile': {'sub_type': 'vlan'}}
+        update_req = self.new_update_request('network_profiles',
+                                             data,
+                                             net_p['network_profile']['id'])
+        update_res = update_req.get_response(self.ext_api)
+        self.assertEqual(update_res.status_int, 400)
+
+
 class TestN1kvBasicGet(test_plugin.TestBasicGet,
                        N1kvPluginTestCase):
 
@@ -248,61 +315,76 @@ class TestN1kvHTTPResponse(test_plugin.TestV2HTTPResponse,
 class TestN1kvPorts(test_plugin.TestPortsV2,
                     N1kvPluginTestCase):
 
-    def _make_other_tenant_profile(self):
-        """Underlying test uses other tenant Id for tests."""
-        profile_obj = self._make_test_profile()
-        policy_profile_obj = self._make_test_policy_profile(
-            '41548d21-7f89-4da0-9131-3d4fd4e8BBB9')
-        self.more_args = {
-            "network": {"n1kv:profile_id": profile_obj.id},
-            "port": {"n1kv:profile_id": policy_profile_obj.id}
-        }
-
-    def test_create_port_public_network(self):
-        # The underlying test function needs a profile for a different tenant.
-        self._make_other_tenant_profile()
-        super(TestN1kvPorts, self).test_create_port_public_network()
-
-    def test_create_port_public_network_with_ip(self):
-        # The underlying test function needs a profile for a different tenant.
-        self._make_other_tenant_profile()
-        super(TestN1kvPorts, self).test_create_port_public_network_with_ip()
-
-    def test_create_ports_bulk_emulated(self):
-        # The underlying test function needs a profile for a different tenant.
-        self._make_other_tenant_profile()
-        super(TestN1kvPorts,
-              self).test_create_ports_bulk_emulated()
-
-    def test_create_ports_bulk_emulated_plugin_failure(self):
-        # The underlying test function needs a profile for a different tenant.
-        self._make_other_tenant_profile()
-        super(TestN1kvPorts,
-              self).test_create_ports_bulk_emulated_plugin_failure()
-
-    def test_delete_port_public_network(self):
-        self._make_other_tenant_profile()
-        super(TestN1kvPorts, self).test_delete_port_public_network()
+    def test_create_port_with_default_n1kv_profile_id(self):
+        """Test port create without passing policy profile id."""
+        with self.port() as port:
+            db_session = db.get_session()
+            pp = n1kv_db_v2.get_policy_profile(
+                db_session, port['port'][n1kv_profile.PROFILE_ID])
+            self.assertEqual(pp['name'], 'service_profile')
+
+    def test_create_port_with_n1kv_profile_id(self):
+        """Test port create with policy profile id."""
+        profile_obj = self._make_test_policy_profile(name='test_profile')
+        with self.network() as network:
+            data = {'port': {n1kv_profile.PROFILE_ID: profile_obj.id,
+                             'tenant_id': self.tenant_id,
+                             'network_id': network['network']['id']}}
+            port_req = self.new_create_request('ports', data)
+            port = self.deserialize(self.fmt,
+                                    port_req.get_response(self.api))
+            self.assertEqual(port['port'][n1kv_profile.PROFILE_ID],
+                             profile_obj.id)
+            self._delete('ports', port['port']['id'])
+
+    def test_update_port_with_n1kv_profile_id(self):
+        """Test port update failure while updating policy profile id."""
+        with self.port() as port:
+            data = {'port': {n1kv_profile.PROFILE_ID: 'some-profile-uuid'}}
+            port_req = self.new_update_request('ports',
+                                               data,
+                                               port['port']['id'])
+            res = port_req.get_response(self.api)
+            # Port update should fail to update policy profile id.
+            self.assertEqual(res.status_int, 400)
 
 
 class TestN1kvNetworks(test_plugin.TestNetworksV2,
                        N1kvPluginTestCase):
 
-    _default_tenant = "somebody_else"  # Tenant-id determined by underlying
-                                       # DB-plugin test cases. Need to use this
-                                       # one for profile creation
-
-    def test_update_network_set_not_shared_single_tenant(self):
-        # The underlying test function needs a profile for a different tenant.
-        profile_obj = self._make_test_profile()
-        policy_profile_obj = self._make_test_policy_profile(
-            '41548d21-7f89-4da0-9131-3d4fd4e8BBB9')
-        self.more_args = {
-            "network": {"n1kv:profile_id": profile_obj.id},
-            "port": {"n1kv:profile_id": policy_profile_obj.id}
-        }
-        super(TestN1kvNetworks,
-              self).test_update_network_set_not_shared_single_tenant()
+    def _prepare_net_data(self, net_profile_id):
+        return {'network': {'name': 'net1',
+                            n1kv_profile.PROFILE_ID: net_profile_id,
+                            'tenant_id': self.tenant_id}}
+
+    def test_create_network_with_default_n1kv_profile_id(self):
+        """Test network create without passing network profile id."""
+        with self.network() as network:
+            db_session = db.get_session()
+            np = n1kv_db_v2.get_network_profile(
+                db_session, network['network'][n1kv_profile.PROFILE_ID])
+            self.assertEqual(np['name'], 'default_network_profile')
+
+    def test_create_network_with_n1kv_profile_id(self):
+        """Test network create with network profile id."""
+        profile_obj = self._make_test_profile(name='test_profile')
+        data = self._prepare_net_data(profile_obj.id)
+        network_req = self.new_create_request('networks', data)
+        network = self.deserialize(self.fmt,
+                                   network_req.get_response(self.api))
+        self.assertEqual(network['network'][n1kv_profile.PROFILE_ID],
+                         profile_obj.id)
+
+    def test_update_network_with_n1kv_profile_id(self):
+        """Test network update failure while updating network profile id."""
+        with self.network() as network:
+            data = {'network': {n1kv_profile.PROFILE_ID: 'some-profile-uuid'}}
+            network_req = self.new_update_request('networks',
+                                                  data,
+                                                  network['network']['id'])
+            res = network_req.get_response(self.api)
+            # Network update should fail to update network profile id.
+            self.assertEqual(res.status_int, 400)
 
 
 class TestN1kvNonDbTest(base.BaseTestCase):