Merge "Update Cisco N1KV plugin to VSM REST api calls"

This commit is contained in:
Jenkins 2013-10-16 15:42:47 +00:00 committed by Gerrit Code Review
commit f76c1909a0
7 changed files with 319 additions and 211 deletions

View File

@ -105,6 +105,7 @@ MAPPING = 'mapping'
SEGMENTS = 'segments' SEGMENTS = 'segments'
SEGMENT = 'segment' SEGMENT = 'segment'
BRIDGE_DOMAIN_SUFFIX = '_bd' BRIDGE_DOMAIN_SUFFIX = '_bd'
LOGICAL_NETWORK_SUFFIX = '_log_net'
ENCAPSULATION_PROFILE_SUFFIX = '_profile' ENCAPSULATION_PROFILE_SUFFIX = '_profile'
UUID_LENGTH = 36 UUID_LENGTH = 36

View File

@ -849,6 +849,7 @@ def create_network_profile(db_session, network_profile):
kwargs["multicast_ip_range"] = network_profile[ kwargs["multicast_ip_range"] = network_profile[
"multicast_ip_range"] "multicast_ip_range"]
kwargs["segment_range"] = network_profile["segment_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: elif network_profile["segment_type"] == c_const.NETWORK_TYPE_TRUNK:
kwargs["sub_type"] = network_profile["sub_type"] kwargs["sub_type"] = network_profile["sub_type"]
net_profile = n1kv_models_v2.NetworkProfile(**kwargs) net_profile = n1kv_models_v2.NetworkProfile(**kwargs)

View File

@ -30,7 +30,7 @@ MEMBER_SEGMENTS = 'n1kv:member_segments'
EXTENDED_ATTRIBUTES_2_0 = { EXTENDED_ATTRIBUTES_2_0 = {
'networks': { 'networks': {
PROFILE_ID: {'allow_post': True, 'allow_put': True, PROFILE_ID: {'allow_post': True, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN}, 'validate': {'type:regex': attributes.UUID_PATTERN},
'default': attributes.ATTR_NOT_SPECIFIED, 'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True}, 'is_visible': True},
@ -48,7 +48,7 @@ EXTENDED_ATTRIBUTES_2_0 = {
'is_visible': True}, 'is_visible': True},
}, },
'ports': { 'ports': {
PROFILE_ID: {'allow_post': True, 'allow_put': True, PROFILE_ID: {'allow_post': True, 'allow_put': False,
'validate': {'type:regex': attributes.UUID_PATTERN}, 'validate': {'type:regex': attributes.UUID_PATTERN},
'default': attributes.ATTR_NOT_SPECIFIED, 'default': attributes.ATTR_NOT_SPECIFIED,
'is_visible': True} 'is_visible': True}

View File

@ -32,20 +32,18 @@ RESOURCE_ATTRIBUTE_MAP = {
'is_visible': True}, 'is_visible': True},
'name': {'allow_post': True, 'allow_put': True, 'name': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''}, 'is_visible': True, 'default': ''},
'segment_type': {'allow_post': True, 'allow_put': True, 'segment_type': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': ''}, 'is_visible': True, 'default': ''},
'sub_type': {'allow_post': True, 'allow_put': True, 'sub_type': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'is_visible': True,
'default': attributes.ATTR_NOT_SPECIFIED}, 'default': attributes.ATTR_NOT_SPECIFIED},
'segment_range': {'allow_post': True, 'allow_put': True, 'segment_range': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': ''}, '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, 'multicast_ip_range': {'allow_post': True, 'allow_put': True,
'is_visible': True, 'default': '0.0.0.0'}, 'is_visible': True, 'default': '0.0.0.0'},
'multicast_ip_index': {'allow_post': False, 'allow_put': False, 'multicast_ip_index': {'allow_post': False, 'allow_put': False,
'is_visible': False, 'default': '0'}, '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': ''}, 'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False, 'tenant_id': {'allow_post': True, 'allow_put': False,
'is_visible': False, 'default': ''}, 'is_visible': False, 'default': ''},

View File

@ -126,11 +126,8 @@ class Client(object):
# Define paths for the URI where the client connects for HTTP requests. # Define paths for the URI where the client connects for HTTP requests.
port_profiles_path = "/virtual-port-profile" port_profiles_path = "/virtual-port-profile"
network_segments_path = "/network-segment"
network_segment_path = "/network-segment/%s" network_segment_path = "/network-segment/%s"
network_segment_pools_path = "/network-segment-pool"
network_segment_pool_path = "/network-segment-pool/%s" network_segment_pool_path = "/network-segment-pool/%s"
ip_pools_path = "/ip-pool-template"
ip_pool_path = "/ip-pool-template/%s" ip_pool_path = "/ip-pool-template/%s"
ports_path = "/kvm/vm-network/%s/ports" ports_path = "/kvm/vm-network/%s/ports"
port_path = "/kvm/vm-network/%s/ports/%s" port_path = "/kvm/vm-network/%s/ports/%s"
@ -138,7 +135,6 @@ class Client(object):
vm_network_path = "/kvm/vm-network/%s" vm_network_path = "/kvm/vm-network/%s"
bridge_domains_path = "/kvm/bridge-domain" bridge_domains_path = "/kvm/bridge-domain"
bridge_domain_path = "/kvm/bridge-domain/%s" bridge_domain_path = "/kvm/bridge-domain/%s"
logical_networks_path = "/logical-network"
logical_network_path = "/logical-network/%s" logical_network_path = "/logical-network/%s"
events_path = "/kvm/events" events_path = "/kvm/events"
clusters_path = "/cluster" clusters_path = "/cluster"
@ -179,9 +175,10 @@ class Client(object):
:param network: network dict :param network: network dict
:param overlay_subtype: string representing subtype of overlay network :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], 'segmentId': network[providernet.SEGMENTATION_ID],
'subType': overlay_subtype} 'subType': overlay_subtype,
'tenantId': network['tenant_id']}
if overlay_subtype == c_const.NETWORK_SUBTYPE_NATIVE_VXLAN: if overlay_subtype == c_const.NETWORK_SUBTYPE_NATIVE_VXLAN:
body['groupIp'] = network[n1kv_profile.MULTICAST_IP] body['groupIp'] = network[n1kv_profile.MULTICAST_IP]
return self._post(self.bridge_domains_path, return self._post(self.bridge_domains_path,
@ -193,7 +190,7 @@ class Client(object):
:param name: name of the bridge domain to be deleted :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): def create_network_segment(self, network, network_profile):
""" """
@ -202,14 +199,15 @@ class Client(object):
:param network: network dict :param network: network dict
:param network_profile: network profile dict :param network_profile: network profile dict
""" """
body = {'name': network['name'], body = {'publishName': network['name'],
'description': network['name'],
'id': network['id'], 'id': network['id'],
'mode': 'access', 'tenantId': network['tenant_id'],
'networkSegmentPool': network_profile['name'], } 'networkSegmentPool': network_profile['id'], }
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VLAN: if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_VLAN:
body['vlan'] = network[providernet.SEGMENTATION_ID] body['vlan'] = network[providernet.SEGMENTATION_ID]
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY: elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY:
body['bridgeDomain'] = (network['name'] + body['bridgeDomain'] = (network['id'] +
c_const.BRIDGE_DOMAIN_SUFFIX) c_const.BRIDGE_DOMAIN_SUFFIX)
if network_profile['segment_type'] == c_const.NETWORK_TYPE_TRUNK: if network_profile['segment_type'] == c_const.NETWORK_TYPE_TRUNK:
body['mode'] = 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['addSegments'] = network['add_segment_list']
body['delSegments'] = network['del_segment_list'] body['delSegments'] = network['del_segment_list']
else: else:
body['encapProfile'] = (network['name'] + body['encapProfile'] = (network['id'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX) c_const.ENCAPSULATION_PROFILE_SUFFIX)
else: else:
body['mode'] = 'access' body['mode'] = 'access'
body['segmentType'] = network_profile['segment_type'] body['segmentType'] = network_profile['segment_type']
return self._post(self.network_segments_path, return self._post(self.network_segment_path % network['id'],
body=body) 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. Update a network segment on the VSM.
Network segment on VSM can be updated to associate it with an ip-pool Network segment on VSM can be updated to associate it with an ip-pool
or update its description and segment id. 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 :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) 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. 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. Create a logical network on the VSM.
:param network_profile: network profile dict :param network_profile: network profile dict
:param tenant_id: UUID representing the tenant
""" """
LOG.debug(_("Logical network")) LOG.debug(_("Logical network"))
body = {'name': network_profile['name']} body = {'description': network_profile['name'],
return self._post(self.logical_networks_path, '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) body=body)
def delete_logical_network(self, network_profile): def delete_logical_network(self, logical_network_name):
""" """
Delete a logical network on VSM. 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( 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. Create a network segment pool on the VSM.
:param network_profile: network profile dict :param network_profile: network profile dict
:param tenant_id: UUID representing the tenant
""" """
LOG.debug(_("network_segment_pool")) LOG.debug(_("network_segment_pool"))
logical_network_name = (network_profile['id'] +
c_const.LOGICAL_NETWORK_SUFFIX)
body = {'name': network_profile['name'], body = {'name': network_profile['name'],
'description': network_profile['name'],
'id': network_profile['id'], 'id': network_profile['id'],
'logicalNetwork': network_profile['name']} 'logicalNetwork': logical_network_name,
return self._post(self.network_segment_pools_path, 'tenantId': tenant_id}
body=body) 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. Update a network segment pool on the VSM.
:param network_segment_pool: string representing the name of network :param network_profile: network profile dict
segment pool to be updated
:param body: dictionary representing key values of network segment
pool which need to be updated
""" """
body = {'name': network_profile['name'],
'description': network_profile['name']}
return self._post(self.network_segment_pool_path % 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. 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 % return self._delete(self.network_segment_pool_path %
(network_segment_pool_name)) network_segment_pool_id)
def create_ip_pool(self, subnet): def create_ip_pool(self, subnet):
""" """
@ -328,38 +337,38 @@ class Client(object):
body = {'addressRangeStart': address_range_start, body = {'addressRangeStart': address_range_start,
'addressRangeEnd': address_range_end, 'addressRangeEnd': address_range_end,
'ipAddressSubnet': netmask, 'ipAddressSubnet': netmask,
'name': subnet['name'], 'description': subnet['name'],
'gateway': subnet['gateway_ip'], 'gateway': subnet['gateway_ip'],
'networkAddress': network_address} 'networkAddress': network_address,
return self._post(self.ip_pools_path, 'tenantId': subnet['tenant_id']}
return self._post(self.ip_pool_path % subnet['id'],
body=body) body=body)
def delete_ip_pool(self, subnet_name): def delete_ip_pool(self, subnet_id):
""" """
Delete an ip-pool on the VSM. 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, def create_vm_network(self,
port, port,
vm_network_name, vm_network_name,
policy_profile, policy_profile):
network_name):
""" """
Create a VM network on the VSM. Create a VM network on the VSM.
:param port: port dict :param port: port dict
:param vm_network_name: name of the VM network :param vm_network_name: name of the VM network
:param policy_profile: policy profile dict :param policy_profile: policy profile dict
:param network_name: string representing the name of the network
""" """
body = {'name': vm_network_name, body = {'name': vm_network_name,
'networkSegmentId': port['network_id'], 'networkSegmentId': port['network_id'],
'networkSegment': network_name, 'networkSegment': port['network_id'],
'portProfile': policy_profile['name'], 'portProfile': policy_profile['name'],
'portProfileId': policy_profile['id'], 'portProfileId': policy_profile['id'],
'tenantId': port['tenant_id'],
} }
return self._post(self.vm_networks_path, return self._post(self.vm_networks_path,
body=body) body=body)
@ -370,7 +379,7 @@ class Client(object):
:param vm_network_name: name of the VM network :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): def create_n1kv_port(self, port, vm_network_name):
""" """
@ -381,7 +390,9 @@ class Client(object):
""" """
body = {'id': port['id'], body = {'id': port['id'],
'macAddress': port['mac_address']} '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) body=body)
def update_n1kv_port(self, vm_network_name, port_id, 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 port_id: UUID of the port
:param body: dict of the arguments to be updated :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) body=body)
def delete_n1kv_port(self, vm_network_name, port_id): 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 vm_network_name: name of the VM network which imports this port
:param port_id: UUID of the 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, def _do_request(self, method, action, body=None,
headers=None): headers=None):
@ -484,7 +495,7 @@ class Client(object):
""" """
if not format: if not format:
format = self.format format = self.format
return "application/%s" % (format) return "application/%s" % format
def _delete(self, action, body=None, headers=None): def _delete(self, action, body=None, headers=None):
return self._do_request("DELETE", action, body=body, return self._do_request("DELETE", action, body=body,
@ -548,7 +559,7 @@ class Client(object):
:param body: mapping dictionary :param body: mapping dictionary
""" """
return self._post(self.encap_profile_path return self._post(self.encap_profile_path
% (profile_name), body=body) % profile_name, body=body)
def delete_encapsulation_profile(self, name): def delete_encapsulation_profile(self, name):
""" """
@ -556,4 +567,4 @@ class Client(object):
:param name: name of the encapsulation profile to be deleted :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)

View File

@ -697,15 +697,16 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
return profile_id 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. Send create logical network request to VSM.
:param network_profile: network profile dictionary :param network_profile: network profile dictionary
:param tenant_id: UUID representing the tenant
""" """
LOG.debug(_('_send_create_logical_network')) LOG.debug(_('_send_create_logical_network'))
n1kvclient = n1kv_client.Client() 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): 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') LOG.debug('_send_delete_logical_network')
n1kvclient = n1kv_client.Client() 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): 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']) LOG.debug(_('_send_create_network_profile_request: %s'), profile['id'])
n1kvclient = n1kv_client.Client() 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): 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'), LOG.debug(_('_send_delete_network_profile_request: %s'),
profile['name']) profile['name'])
n1kvclient = n1kv_client.Client() 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): 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( profile = n1kv_db_v2.get_network_profile(
db_session, network[n1kv_profile.PROFILE_ID]) db_session, network[n1kv_profile.PROFILE_ID])
n1kvclient = n1kv_client.Client() n1kvclient = n1kv_client.Client()
body = {'name': network['name'], body = {'publishName': network['name'],
'id': network['id'], 'id': network['id'],
'networkDefinition': profile['name'], 'networkSegmentPool': profile['id'],
'vlan': network[providernet.SEGMENTATION_ID], 'vlan': network[providernet.SEGMENTATION_ID],
'mode': 'access', 'mode': 'access',
'segmentType': profile['segment_type'], 'segmentType': profile['segment_type'],
@ -806,7 +819,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
LOG.debug(_('add_segments=%s'), body['addSegments']) LOG.debug(_('add_segments=%s'), body['addSegments'])
LOG.debug(_('del_segments=%s'), body['delSegments']) LOG.debug(_('del_segments=%s'), body['delSegments'])
if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY: if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
encap_profile = (network['name'] + encap_profile = (network['id'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX) c_const.ENCAPSULATION_PROFILE_SUFFIX)
encap_dict = {'name': encap_profile, encap_dict = {'name': encap_profile,
'addMappings': ( 'addMappings': (
@ -817,7 +830,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
del_segments))} del_segments))}
n1kvclient.update_encapsulation_profile(context, encap_profile, n1kvclient.update_encapsulation_profile(context, encap_profile,
encap_dict) encap_dict)
n1kvclient.update_network_segment(network['name'], body) n1kvclient.update_network_segment(network['id'], body)
def _send_delete_network_request(self, context, network): def _send_delete_network_request(self, context, network):
""" """
@ -832,13 +845,13 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
n1kvclient = n1kv_client.Client() n1kvclient = n1kv_client.Client()
session = context.session session = context.session
if network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_OVERLAY: 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) n1kvclient.delete_bridge_domain(name)
elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_TRUNK: elif network[providernet.NETWORK_TYPE] == c_const.NETWORK_TYPE_TRUNK:
profile = self.get_network_profile( profile = self.get_network_profile(
context, network[n1kv_profile.PROFILE_ID]) context, network[n1kv_profile.PROFILE_ID])
if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY: if profile['sub_type'] == c_const.NETWORK_TYPE_OVERLAY:
profile_name = (network['name'] + profile_name = (network['id'] +
c_const.ENCAPSULATION_PROFILE_SUFFIX) c_const.ENCAPSULATION_PROFILE_SUFFIX)
n1kvclient.delete_encapsulation_profile(profile_name) n1kvclient.delete_encapsulation_profile(profile_name)
elif (network[providernet.NETWORK_TYPE] == elif (network[providernet.NETWORK_TYPE] ==
@ -859,7 +872,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
profile_dict['delSegments'].append(mapping_dict) profile_dict['delSegments'].append(mapping_dict)
n1kvclient.update_encapsulation_profile(context, profile, n1kvclient.update_encapsulation_profile(context, profile,
profile_dict) profile_dict)
n1kvclient.delete_network_segment(network['name']) n1kvclient.delete_network_segment(network['id'])
def _send_create_subnet_request(self, context, subnet): def _send_create_subnet_request(self, context, subnet):
""" """
@ -869,11 +882,10 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
:param subnet: subnet dictionary :param subnet: subnet dictionary
""" """
LOG.debug(_('_send_create_subnet_request: %s'), subnet['id']) LOG.debug(_('_send_create_subnet_request: %s'), subnet['id'])
network = self.get_network(context, subnet['network_id'])
n1kvclient = n1kv_client.Client() n1kvclient = n1kv_client.Client()
n1kvclient.create_ip_pool(subnet) n1kvclient.create_ip_pool(subnet)
body = {'ipPoolName': subnet['name']} body = {'ipPool': subnet['id']}
n1kvclient.update_network_segment(network['name'], body=body) n1kvclient.update_network_segment(subnet['network_id'], body=body)
def _send_delete_subnet_request(self, context, subnet): def _send_delete_subnet_request(self, context, subnet):
""" """
@ -883,11 +895,10 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
:param subnet: subnet dictionary :param subnet: subnet dictionary
""" """
LOG.debug(_('_send_delete_subnet_request: %s'), subnet['name']) LOG.debug(_('_send_delete_subnet_request: %s'), subnet['name'])
network = self.get_network(context, subnet['network_id']) body = {'ipPool': subnet['id'], 'deleteSubnet': True}
body = {'ipPoolName': subnet['name'], 'deleteSubnet': True}
n1kvclient = n1kv_client.Client() n1kvclient = n1kv_client.Client()
n1kvclient.update_network_segment(network['name'], body=body) n1kvclient.update_network_segment(subnet['network_id'], body=body)
n1kvclient.delete_ip_pool(subnet['name']) n1kvclient.delete_ip_pool(subnet['id'])
def _send_create_port_request(self, context, port): def _send_create_port_request(self, context, port):
""" """
@ -908,7 +919,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
except cisco_exceptions.VMNetworkNotFound: except cisco_exceptions.VMNetworkNotFound:
policy_profile = n1kv_db_v2.get_policy_profile( policy_profile = n1kv_db_v2.get_policy_profile(
context.session, port[n1kv_profile.PROFILE_ID]) context.session, port[n1kv_profile.PROFILE_ID])
network = self.get_network(context, port['network_id'])
vm_network_name = (c_const.VM_NETWORK_NAME_PREFIX + vm_network_name = (c_const.VM_NETWORK_NAME_PREFIX +
str(port[n1kv_profile.PROFILE_ID]) + str(port[n1kv_profile.PROFILE_ID]) +
"_" + str(port['network_id'])) "_" + str(port['network_id']))
@ -921,8 +931,7 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
n1kvclient = n1kv_client.Client() n1kvclient = n1kv_client.Client()
n1kvclient.create_vm_network(port, n1kvclient.create_vm_network(port,
vm_network_name, vm_network_name,
policy_profile, policy_profile)
network['name'])
n1kvclient.create_n1kv_port(port, vm_network_name) n1kvclient.create_n1kv_port(port, vm_network_name)
else: else:
vm_network_name = vm_network['name'] vm_network_name = vm_network['name']
@ -994,7 +1003,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
(network_type, physical_network, (network_type, physical_network,
segmentation_id) = self._process_provider_create(context, segmentation_id) = self._process_provider_create(context,
network['network']) network['network'])
self._add_dummy_profile_only_if_testing(network)
profile_id = self._process_network_profile(context, network['network']) profile_id = self._process_network_profile(context, network['network'])
segment_pairs = None segment_pairs = None
LOG.debug(_('Create network: profile_id=%s'), profile_id) LOG.debug(_('Create network: profile_id=%s'), profile_id)
@ -1219,8 +1227,6 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
:param port: port dictionary :param port: port dictionary
:returns: port object :returns: port object
""" """
self._add_dummy_profile_only_if_testing(port)
if ('device_id' in port['port'] and port['port']['device_owner'] in if ('device_id' in port['port'] and port['port']['device_owner'] in
['network:dhcp', 'network:router_interface']): ['network:dhcp', 'network:router_interface']):
p_profile_name = c_conf.CISCO_N1K.network_node_policy_profile 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) LOG.debug(_("Created port: %s"), pt)
return 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): def update_port(self, context, id, port):
""" """
Update port parameters. Update port parameters.
@ -1449,7 +1446,8 @@ class N1kvNeutronPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
n1kv_db_v2.sync_vxlan_allocations(context.session, n1kv_db_v2.sync_vxlan_allocations(context.session,
self.vxlan_id_ranges) self.vxlan_id_ranges)
try: try:
self._send_create_logical_network_request(_network_profile) self._send_create_logical_network_request(_network_profile,
context.tenant_id)
except(cisco_exceptions.VSMError, except(cisco_exceptions.VSMError,
cisco_exceptions.VSMConnectionFailed): cisco_exceptions.VSMConnectionFailed):
super(N1kvNeutronPluginV2, self).delete_network_profile( 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, n1kv_db_v2.delete_vxlan_allocations(context.session,
self.delete_vxlan_ranges) self.delete_vxlan_ranges)
self._send_delete_network_profile_request(_network_profile) 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

View File

@ -18,16 +18,22 @@
# @author: Abhishek Raut, Cisco Systems Inc. # @author: Abhishek Raut, Cisco Systems Inc.
from mock import patch 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 from neutron import context
import neutron.db.api as db import neutron.db.api as db
from neutron.plugins.cisco.db import n1kv_db_v2 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.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 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_client
from neutron.plugins.cisco.n1kv import n1kv_neutron_plugin from neutron.plugins.cisco.n1kv import n1kv_neutron_plugin
from neutron.tests import base from neutron.tests import base
from neutron.tests.unit import test_api_v2
from neutron.tests.unit import test_db_plugin as test_plugin from neutron.tests.unit import test_db_plugin as test_plugin
@ -51,41 +57,30 @@ class FakeResponse(object):
return self.buffer 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): def _fake_setup_vsm(self):
"""Fake establish Communication with Cisco Nexus1000V VSM.""" """Fake establish Communication with Cisco Nexus1000V VSM."""
self.agent_vsm = True self.agent_vsm = True
self._poll_policies(event_type="port_profile") 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): class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
_plugin_name = ('neutron.plugins.cisco.n1kv.' _plugin_name = ('neutron.plugins.cisco.n1kv.'
@ -96,31 +91,38 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
DEFAULT_RESP_BODY = "" DEFAULT_RESP_BODY = ""
DEFAULT_RESP_CODE = 200 DEFAULT_RESP_CODE = 200
DEFAULT_CONTENT_TYPE = "" DEFAULT_CONTENT_TYPE = ""
fmt = "json"
def _make_test_policy_profile(self, id): def _make_test_policy_profile(self, name='service_profile'):
"""Create a policy profile record for testing purpose.""" """
profile = {'id': id, Create a policy profile record for testing purpose.
'name': 'TestGrizzlyPP'}
profile_obj = n1kv_db_v2.create_policy_profile(profile)
return profile_obj
def _make_test_profile(self): :param name: string representing the name of the policy profile to
"""Create a profile record for testing purposes.""" create. Default argument value chosen to correspond to the
alloc_obj = n1kv_models_v2.N1kvVlanAllocation(physical_network='foo', default name specified in config.py file.
vlan_id=123) """
alloc_obj.allocated = False uuid = test_api_v2._uuid()
segment_range = "100-900" profile = {'id': uuid,
segment_type = 'vlan' 'name': name}
physical_network = 'phys1' return n1kv_db_v2.create_policy_profile(profile)
profile_obj = n1kv_models_v2.NetworkProfile(
name="test_np", def _make_test_profile(self, name='default_network_profile'):
segment_type=segment_type, """
segment_range=segment_range, Create a profile record for testing purposes.
physical_network=physical_network)
session = db.get_session() :param name: string representing the name of the network profile to
session.add(profile_obj) create. Default argument value chosen to correspond to the
session.flush() default name specified in config.py file.
return profile_obj """
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): def setUp(self):
""" """
@ -199,24 +201,39 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
fake_get_cred_name.return_value = {"user_name": "admin", fake_get_cred_name.return_value = {"user_name": "admin",
"password": "admin_password"} "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 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) super(N1kvPluginTestCase, self).setUp(self._plugin_name)
# Create some of the database entries that we require. # Create some of the database entries that we require.
profile_obj = self._make_test_profile() self._make_test_profile()
policy_profile_obj = (self._make_test_policy_profile( self._make_test_policy_profile()
'41548d21-7f89-4da0-9131-3d4fd4e8BBB8'))
# Additional args for create_network(), create_port(), etc. def restore_resource_attribute_map(self):
self.more_args = { # Restore the original RESOURCE_ATTRIBUTE_MAP
"network": {"n1kv:profile_id": profile_obj.id}, attributes.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map
"port": {"n1kv:profile_id": policy_profile_obj.id}
} def restore_test_config(self):
# Restore the original test_config
del test_config['plugin_name_v2']
def test_plugin(self): def test_plugin(self):
self._make_network('json', self._make_network('json',
@ -233,6 +250,56 @@ class N1kvPluginTestCase(test_plugin.NeutronDbPluginV2TestCase):
self.assertIn('tenant_id', body['networks'][0]) 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, class TestN1kvBasicGet(test_plugin.TestBasicGet,
N1kvPluginTestCase): N1kvPluginTestCase):
@ -248,61 +315,76 @@ class TestN1kvHTTPResponse(test_plugin.TestV2HTTPResponse,
class TestN1kvPorts(test_plugin.TestPortsV2, class TestN1kvPorts(test_plugin.TestPortsV2,
N1kvPluginTestCase): N1kvPluginTestCase):
def _make_other_tenant_profile(self): def test_create_port_with_default_n1kv_profile_id(self):
"""Underlying test uses other tenant Id for tests.""" """Test port create without passing policy profile id."""
profile_obj = self._make_test_profile() with self.port() as port:
policy_profile_obj = self._make_test_policy_profile( db_session = db.get_session()
'41548d21-7f89-4da0-9131-3d4fd4e8BBB9') pp = n1kv_db_v2.get_policy_profile(
self.more_args = { db_session, port['port'][n1kv_profile.PROFILE_ID])
"network": {"n1kv:profile_id": profile_obj.id}, self.assertEqual(pp['name'], 'service_profile')
"port": {"n1kv:profile_id": policy_profile_obj.id}
}
def test_create_port_public_network(self): def test_create_port_with_n1kv_profile_id(self):
# The underlying test function needs a profile for a different tenant. """Test port create with policy profile id."""
self._make_other_tenant_profile() profile_obj = self._make_test_policy_profile(name='test_profile')
super(TestN1kvPorts, self).test_create_port_public_network() 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_create_port_public_network_with_ip(self): def test_update_port_with_n1kv_profile_id(self):
# The underlying test function needs a profile for a different tenant. """Test port update failure while updating policy profile id."""
self._make_other_tenant_profile() with self.port() as port:
super(TestN1kvPorts, self).test_create_port_public_network_with_ip() data = {'port': {n1kv_profile.PROFILE_ID: 'some-profile-uuid'}}
port_req = self.new_update_request('ports',
def test_create_ports_bulk_emulated(self): data,
# The underlying test function needs a profile for a different tenant. port['port']['id'])
self._make_other_tenant_profile() res = port_req.get_response(self.api)
super(TestN1kvPorts, # Port update should fail to update policy profile id.
self).test_create_ports_bulk_emulated() self.assertEqual(res.status_int, 400)
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()
class TestN1kvNetworks(test_plugin.TestNetworksV2, class TestN1kvNetworks(test_plugin.TestNetworksV2,
N1kvPluginTestCase): N1kvPluginTestCase):
_default_tenant = "somebody_else" # Tenant-id determined by underlying def _prepare_net_data(self, net_profile_id):
# DB-plugin test cases. Need to use this return {'network': {'name': 'net1',
# one for profile creation n1kv_profile.PROFILE_ID: net_profile_id,
'tenant_id': self.tenant_id}}
def test_update_network_set_not_shared_single_tenant(self): def test_create_network_with_default_n1kv_profile_id(self):
# The underlying test function needs a profile for a different tenant. """Test network create without passing network profile id."""
profile_obj = self._make_test_profile() with self.network() as network:
policy_profile_obj = self._make_test_policy_profile( db_session = db.get_session()
'41548d21-7f89-4da0-9131-3d4fd4e8BBB9') np = n1kv_db_v2.get_network_profile(
self.more_args = { db_session, network['network'][n1kv_profile.PROFILE_ID])
"network": {"n1kv:profile_id": profile_obj.id}, self.assertEqual(np['name'], 'default_network_profile')
"port": {"n1kv:profile_id": policy_profile_obj.id}
} def test_create_network_with_n1kv_profile_id(self):
super(TestN1kvNetworks, """Test network create with network profile id."""
self).test_update_network_set_not_shared_single_tenant() 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): class TestN1kvNonDbTest(base.BaseTestCase):