Adding vanilla flavor clients for the Neutron API
Renamed nets_subnets_ports_api for networks Adding configs and composites Code Review updates More Code Review updates Change-Id: If7bd73863ead708e5e690bf8df18a7577ea1f84d
This commit is contained in:
parent
388dadbf36
commit
cfa112f7d5
@ -1,481 +0,0 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.common.client import BaseClient, setup_rest_operation
|
||||
|
||||
|
||||
class NetsSubnetsPortsClient(BaseClient):
|
||||
"""Implements the Neutron ReST client for the following API resources:
|
||||
|
||||
networks
|
||||
subnets
|
||||
ports
|
||||
"""
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None):
|
||||
"""
|
||||
@param url: Base URL for the Neutron service
|
||||
@type url: String
|
||||
@param auth_token: Auth token to be used for all requests
|
||||
@type auth_token: String
|
||||
@param serialize_format: Format for serializing requests
|
||||
@type serialize_format: String
|
||||
@param deserialize_format: Format for de-serializing responses
|
||||
@type deserialize_format: String
|
||||
"""
|
||||
super(NetsSubnetsPortsClient, self).__init__(url, auth_token,
|
||||
serialize_format,
|
||||
deserialize_format)
|
||||
self._models_classes = {'networks': (None, None),
|
||||
'subnets': (None, None),
|
||||
'ports': (None, None), }
|
||||
self._resource_plural_map = {}
|
||||
|
||||
@setup_rest_operation
|
||||
def list_networks(self, name=None, admin_state_up=None, status=None,
|
||||
shared=None, tenant_id=None, limit=None, marker=None,
|
||||
page_reverse=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists all networks. Additionally, can filter results by
|
||||
params. Maps to /networks
|
||||
@param name: Network name to filter by
|
||||
@type name: String
|
||||
@param admin_state_up: Network administrative state up value to filter
|
||||
by
|
||||
@type admin_state_up: Boolean
|
||||
@param status: Network status to filter by
|
||||
@type status: String
|
||||
@param shared: Network shared attribute value to filter by
|
||||
@type shared: Boolean
|
||||
@param tenant_id: Network owner tenant_id to filter by
|
||||
@type tenant_id: String
|
||||
@param marker: Network id to be used as a marker for the next list
|
||||
@type marker: String
|
||||
@param limit: The maximum number of results to return
|
||||
@type limit: Int
|
||||
@param page_reverse: Page direction setting
|
||||
@type page_reverse: Boolean
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._list(name=name, admin_state_up=admin_state_up,
|
||||
status=status, shared=shared, tenant_id=tenant_id,
|
||||
marker=marker, limit=limit,
|
||||
page_reverse=page_reverse,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def create_network(self, name, admin_state_up=None, shared=None,
|
||||
tenant_id=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates an instance of a network given the
|
||||
provided parameters
|
||||
@param name: human readable name of the network. Might not be unique.
|
||||
No default value provided by the API
|
||||
@type name: String
|
||||
@param admin_state_up: Network administrative state up value. If down,
|
||||
the network does not forward packets. API default value is true
|
||||
@type admin_state_up: Boolean
|
||||
@param shared: Specifies whether the network can be shared by other
|
||||
tenants or not. API default value is false
|
||||
@type shared: Boolean
|
||||
@param tenant_id: owner of network. Only admin users can specify a
|
||||
tenant id other than its own. No default value provided by the API
|
||||
@type tenant_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._create(name=name, admin_state_up=admin_state_up,
|
||||
shared=shared, tenant_id=tenant_id,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def update_network(self, network_id, name=None, admin_state_up=None,
|
||||
shared=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: updates an instance of a network given the
|
||||
provided parameters
|
||||
@param network_id: id of the network to update
|
||||
@type network_id: String
|
||||
@param name: human readable name of the network. Might not be unique.
|
||||
@type name: String
|
||||
@param admin_state_up: Network administrative state up value. If down,
|
||||
the network does not forward packets.
|
||||
@type admin_state_up: Boolean
|
||||
@param shared: Specifies whether the network can be shared by other
|
||||
tenants or not.
|
||||
@type shared: Boolean
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._update(network_id, name=name,
|
||||
admin_state_up=admin_state_up, shared=shared,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def show_network(self, network_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: get the attributes of a network instance
|
||||
@param network_id: id of the network whose attributes will be gotten
|
||||
@type network_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._show(network_id, requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def delete_network(self, network_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: delete a network
|
||||
@param network_id: id of the network to delete
|
||||
@type network_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._delete(network_id, requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def list_subnets(self, network_id=None, name=None, ip_version=None,
|
||||
cidr=None, gateway_ip=None, enable_dhcp=None,
|
||||
tenant_id=None, limit=None, marker=None,
|
||||
page_reverse=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists all subnets. Additionally, can filter results by
|
||||
params. Maps to /subnets
|
||||
@param network_id: Network id to filter by
|
||||
@type network_id: String
|
||||
@param name: Subnet id to filter by
|
||||
@type name: String
|
||||
@param ip_version: IP version to filter by
|
||||
@type ip_version: Int
|
||||
@param cidr: cidr to filter by
|
||||
@type cidr: String
|
||||
@param gateway_ip: Gateway ip address to filter by
|
||||
@type gateway_ip: String
|
||||
@param enable_dhcp: Enable dhcp setting to filter by
|
||||
@type enable_dhcp: Boolen
|
||||
@param tenant_id: ID of tenant to filter by
|
||||
@type tenant_id: String
|
||||
@param marker: Subnet id to be used as a marker for the next list
|
||||
@type marker: String
|
||||
@param limit: The maximum number of results to return
|
||||
@type limit: Int
|
||||
@param page_reverse: Page direction setting
|
||||
@type page_reverse: Boolean
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._list(network_id=network_id, name=name,
|
||||
ip_version=ip_version, cidr=cidr,
|
||||
gateway_ip=gateway_ip, enable_dhcp=enable_dhcp,
|
||||
tenant_id=tenant_id, marker=marker, limit=limit,
|
||||
page_reverse=page_reverse,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def create_subnet(self, network_id, cidr, name=None, ip_version=None,
|
||||
gateway_ip=None, dns_nameservers=None,
|
||||
allocation_pools=None, host_routes=None,
|
||||
enable_dhcp=None, tenant_id=None,
|
||||
requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates an instance of a subnet given the
|
||||
provided parameters
|
||||
@param network_id: the id of the network the subnet will be
|
||||
associated with
|
||||
@type network_id: String
|
||||
@param cidr: the ip range for the subnet
|
||||
@type cidr: String
|
||||
@param name: human readable name for the subnet. Might not be unique.
|
||||
No default value provided by the API
|
||||
@type name: String
|
||||
@param ip_version: the IP version for the subnet. API default value is
|
||||
4
|
||||
@type ip_version: Int
|
||||
@param gateway_ip: default gateway used by devices in the subnet
|
||||
API default value is the first address in the cidr
|
||||
@type gateway_ip: String
|
||||
@param dns_nameservers: DNS nanme servers used by hosts in the subnet
|
||||
API default value is an empty list
|
||||
@type dns_nameservers: List of String
|
||||
@param allocation_pools: sub-ranges of cidr available for dynamic
|
||||
allocation to ports. API default value is every address in cidr,
|
||||
excluding gateway ip if configured
|
||||
@type allocation_pools: List of Dictionaries
|
||||
@param host_routes: routes that should be used by devices with IP's
|
||||
from the subnet (not including local subnet route). API default value
|
||||
is empty list
|
||||
@type host_routes: List of Dictionaries
|
||||
@param enable_dhcp: specifies whether DHCP is enabled for the subnet or
|
||||
not. API default value is true
|
||||
@type enable_dhcp: Boolean
|
||||
@param tenant_id: owner of subnet. Only admin users can specify a
|
||||
tenant id other than its own. No default value provided by the API
|
||||
@type tenant_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._create(network_id=network_id, cidr=cidr, name=name,
|
||||
ip_version=ip_version, gateway_ip=gateway_ip,
|
||||
dns_nameservers=dns_nameservers,
|
||||
allocation_pools=allocation_pools,
|
||||
host_routes=host_routes, enable_dhcp=enable_dhcp,
|
||||
tenant_id=tenant_id,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def update_subnet(self, subnet_id, name=None, gateway_ip=None,
|
||||
dns_nameservers=None, host_routes=None,
|
||||
enable_dhcp=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: updates an instance of a subnet given the
|
||||
provided parameters
|
||||
@param subnet_id: the id of the subnet to updtes
|
||||
@type subnet_id: String
|
||||
@param name: human readable name for the subnet. Might not be unique.
|
||||
@type name: String
|
||||
@param gateway_ip: default gateway used by devices in the subnet
|
||||
@type gateway_ip: String
|
||||
@param dns_nameservers: DNS nanme servers used by hosts in the subnet
|
||||
@type dns_nameservers: List of String
|
||||
@param host_routes: routes that should be used by devices with IP's
|
||||
from the subnet (not including local subnet route).
|
||||
@type host_routes: List of Dictionaries
|
||||
@param enable_dhcp: specifies whether DHCP is enabled for the subnet or
|
||||
not.
|
||||
@type enable_dhcp: Boolean
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._update(subnet_id, name=name, gateway_ip=gateway_ip,
|
||||
dns_nameservers=dns_nameservers,
|
||||
host_routes=host_routes, enable_dhcp=enable_dhcp,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def show_subnet(self, subnet_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: get the attributes of a subnet instance
|
||||
@param subnet_id: id of the subnet whose attributes will be gotten
|
||||
@type subnet_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._show(subnet_id, requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def delete_subnet(self, subnet_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: delete a subnet
|
||||
@param subnet_id: id of the subnet to delete
|
||||
@type subnet_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._delete(subnet_id, requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def list_ports(self, network_id=None, name=None, admin_state_up=None,
|
||||
status=None, mac_address=None, device_id=None,
|
||||
device_owner=None, tenant_id=None, limit=None, marker=None,
|
||||
page_reverse=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists all ports. Additionally, can filter results by
|
||||
params. Maps to /ports
|
||||
@param network_id: Network id to filter by
|
||||
@type network_id: String
|
||||
@param name: Port id to filter by
|
||||
@type name: String
|
||||
@param admin_state_up: Network administrative state up value to filter
|
||||
by
|
||||
@type admin_state_up: Boolean
|
||||
@param status: Network status to filter by
|
||||
@type status: String
|
||||
@param mac_address: mac_address to filter by
|
||||
@type mac_address: String
|
||||
@param device_id: Device id to filter by
|
||||
@type device_id: String
|
||||
@param device_owner: Device owner to filter by
|
||||
@type device_owner: String
|
||||
@param tenant_id: ID of tenant to filter by
|
||||
@type tenant_id: String
|
||||
@param marker: Subnet id to be used as a marker for the next list
|
||||
@type marker: String
|
||||
@param limit: The maximum number of results to return
|
||||
@type limit: Int
|
||||
@param page_reverse: Page direction setting
|
||||
@type page_reverse: Boolean
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._list(network_id=network_id, name=name,
|
||||
admin_state_up=admin_state_up, status=status,
|
||||
mac_address=mac_address, device_id=device_id,
|
||||
device_owner=device_owner, tenant_id=tenant_id,
|
||||
marker=marker, limit=limit,
|
||||
page_reverse=page_reverse,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def create_port(self, network_id, name=None, admin_state_up=None,
|
||||
mac_address=None, fixed_ips=None, device_id=None,
|
||||
device_owner=None, tenant_id=None, security_groups=None,
|
||||
requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates an instance of a port given the
|
||||
provided parameters
|
||||
@param network_id: network that the port is associated with. No default
|
||||
value provided by the API
|
||||
@type neywork_id: String
|
||||
@param name: hurman readable name for the port. Might not be unique. No
|
||||
default value provided by the API
|
||||
@type name: String
|
||||
@param admin_state_up: administrative state of the port. If false, port
|
||||
does not forward packets. API default value is true
|
||||
@type admin_state_up: Boolean
|
||||
@param mac_address: mac addres to be used on this port. API default
|
||||
value is generated
|
||||
@type mac_address: String
|
||||
@param fixed_ips: specifies ip adddreses for the port, associating it
|
||||
with the subnets where the ip addresses are picked from. API default
|
||||
value is an ip address selected from the allocation pools associated
|
||||
with the network
|
||||
@type fixed_ips: List of Dictionaries
|
||||
@param device_id: identifies the device (e.g. virtual server) using the
|
||||
port. No default value provided by the API
|
||||
@type device_id: String
|
||||
@param device_owner: identifies the entity (e.g. dhcp agent) using the
|
||||
port. No default value provided by the API
|
||||
@type device_owner: String
|
||||
@param tenant_id: owner of port. Only admin users can specify tenants
|
||||
other than their own. No default value provided by the API
|
||||
@type tenant_id: String
|
||||
@param security_groups: specifies the ID's of any security groups
|
||||
associated with the port. No default value provided by the API
|
||||
@type security_groups: List of Dictionaries
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._create(network_id=network_id, name=name,
|
||||
admin_state_up=admin_state_up,
|
||||
mac_address=mac_address, fixed_ips=fixed_ips,
|
||||
device_id=device_id, device_owner=device_owner,
|
||||
tenant_id=tenant_id,
|
||||
security_groups=security_groups,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def update_port(self, port_id, name=None, admin_state_up=None,
|
||||
fixed_ips=None, device_id=None, device_owner=None,
|
||||
security_groups=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: updates an instance of a port given the
|
||||
provided parameters
|
||||
@param port_id: id of the port to be updated
|
||||
@type neywork_id: String
|
||||
@param name: hurman readable name for the port. Might not be unique.
|
||||
@type name: String
|
||||
@param admin_state_up: administrative state of the port. If false, port
|
||||
does not forward packets.
|
||||
@type admin_state_up: Boolean
|
||||
@param fixed_ips: specifies ip adddreses for the port, associating it
|
||||
with the subnets where the ip addresses are picked from.
|
||||
@type fixed_ips: List of Dictionaries
|
||||
@param device_id: identifies the device (e.g. virtual server) using the
|
||||
port.
|
||||
@type device_id: String
|
||||
@param device_owner: identifies the entity (e.g. dhcp agent) using the
|
||||
port.
|
||||
@type device_owner: String
|
||||
@param security_groups: specifies the ID's of any security groups
|
||||
associated with the port
|
||||
@type security_groups: List of Dictionaries
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._update(port_id, name=name, admin_state_up=admin_state_up,
|
||||
fixed_ips=fixed_ips, device_id=device_id,
|
||||
device_owner=device_owner,
|
||||
security_groups=security_groups,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def show_port(self, port_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: get the attributes of a port instance
|
||||
@param port_id: id of the port whose attributes will be gotten
|
||||
@type port_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._show(port_id, requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
@setup_rest_operation
|
||||
def delete_port(self, port_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: delete a port
|
||||
@param port_id: id of the port to be deleted
|
||||
@type port_id: String
|
||||
@param requestslib_kwargs: keyword arguments to be passed to the
|
||||
requests library
|
||||
@type requestslib_kwargs: Dictionary
|
||||
@return: response from the API
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
return self._delete(port_id, requestslib_kwargs=requestslib_kwargs)
|
15
cloudcafe/networking/networks/__init__.py
Normal file
15
cloudcafe/networking/networks/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
15
cloudcafe/networking/networks/behaviors.py
Normal file
15
cloudcafe/networking/networks/behaviors.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
0
cloudcafe/networking/networks/common/__init__.py
Normal file
0
cloudcafe/networking/networks/common/__init__.py
Normal file
15
cloudcafe/networking/networks/common/models/__init__.py
Normal file
15
cloudcafe/networking/networks/common/models/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
@ -0,0 +1,59 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class NetworkRequest(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Network model object for the OpenStack Neutron v2.0 API
|
||||
requests for creating (POST) and updating (PUT) networks calls
|
||||
@param string name: human readable name for the network,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false, the admin state
|
||||
of the network. If down, the network does not forward packets.
|
||||
Default value is True (CRUD: CRU)
|
||||
@param bool shared: specifies if the network can be accessed by any
|
||||
tenant. Default value is False. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
"""
|
||||
|
||||
def __init__(self, name=None, admin_state_up=None, shared=None,
|
||||
tenant_id=None, **kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(NetworkRequest, self).__init__()
|
||||
self.name = name
|
||||
self.admin_state_up = admin_state_up
|
||||
self.shared = shared
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
def _obj_to_json(self):
|
||||
|
||||
body = {
|
||||
'shared': self.shared,
|
||||
'tenant_id': self.tenant_id,
|
||||
'name': self.name,
|
||||
'admin_state_up': self.admin_state_up
|
||||
}
|
||||
|
||||
# Removing optional params not given
|
||||
body = self._remove_empty_values(body)
|
||||
main_body = {'network': body}
|
||||
return json.dumps(main_body)
|
77
cloudcafe/networking/networks/common/models/request/port.py
Normal file
77
cloudcafe/networking/networks/common/models/request/port.py
Normal file
@ -0,0 +1,77 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class PortRequest(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Port model object for the OpenStack Neutron v2.0 API
|
||||
requests for creating (POST) and updating (PUT) ports calls
|
||||
@param string network_id: network port is associated with (CRUD: CR)
|
||||
@param string name: human readable name for the port,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false (default true), the admin state
|
||||
of the port. If down, the port does not forward packets (CRUD: CRU)
|
||||
@param string mac_address: mac address to use on the port (CRUD: CR)
|
||||
@param list(dict) fixed_ips: ip addresses for the port associating the
|
||||
port with the subnets where the IPs come from (CRUD: CRU)
|
||||
@param string device_id: id of device using this port (CRUD: CRUD)
|
||||
@param string device_owner: entity using this port (ex. dhcp agent,
|
||||
CRUD: CRUD)
|
||||
@param string tenant_id: owner of the port (CRUD: CR)
|
||||
@param list(dict) security_groups: ids of any security groups associated
|
||||
with the port (CRUD: CRUD)
|
||||
"""
|
||||
|
||||
def __init__(self, network_id=None, name=None, admin_state_up=None,
|
||||
mac_address=None, fixed_ips=None, device_id=None,
|
||||
device_owner=None, tenant_id=None, security_groups=None,
|
||||
**kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(PortRequest, self).__init__()
|
||||
self.network_id = network_id
|
||||
self.name = name
|
||||
self.admin_state_up = admin_state_up
|
||||
self.mac_address = mac_address
|
||||
self.fixed_ips = fixed_ips
|
||||
self.device_id = device_id
|
||||
self.device_owner = device_owner
|
||||
self.tenant_id = tenant_id
|
||||
self.security_groups = security_groups
|
||||
|
||||
def _obj_to_json(self):
|
||||
|
||||
body = {
|
||||
'network_id': self.network_id,
|
||||
'name': self.name,
|
||||
'admin_state_up': self.admin_state_up,
|
||||
'mac_address': self.mac_address,
|
||||
'fixed_ips': self.fixed_ips,
|
||||
'device_id': self.device_id,
|
||||
'device_owner': self.device_owner,
|
||||
'tenant_id': self.tenant_id,
|
||||
'security_groups': self.security_groups
|
||||
}
|
||||
|
||||
# The client should instantiate the model with only desired parameters
|
||||
body = self._remove_empty_values(body)
|
||||
main_body = {'port': body}
|
||||
return json.dumps(main_body)
|
@ -0,0 +1,81 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class SubnetRequest(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Subnet model object for the OpenStack Neutron v2.0 API
|
||||
requests for creating (POST) and updating (PUT) subnets
|
||||
@param string name: human readable name for the subnet,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
@param string network_id: network subnet is associated with (CRUD: CR)
|
||||
@param int ip_version: IP version 4 or 6 (CRUD: CR)
|
||||
@param string cidr: represents IP range for the subnet and should be in
|
||||
the form <network_address>/<prefix> (CRUD: CR)
|
||||
@param string gateway_ip: default gateway used by devices in the subnet
|
||||
(CRUD: CRUD)
|
||||
@param list(str) dns_nameservers: DNS name servers used by subnet hosts
|
||||
(CRUD: CRU)
|
||||
@param list(dict) allocation_pools: sub range of cidr available for dynamic
|
||||
allocation to ports (CRUD: CR)
|
||||
@param list(dict) host_routes: routes that should be used by devices with
|
||||
IPs from this subnet (does not includes the local route, CRUD: CRU)
|
||||
@param bool enable_dhcp: whether DHCP is enabled (CRUD:CRU)
|
||||
"""
|
||||
|
||||
def __init__(self, name=None, tenant_id=None, network_id=None,
|
||||
ip_version=None, cidr=None, gateway_ip=None,
|
||||
dns_nameservers=None, allocation_pools=None,
|
||||
host_routes=None, enable_dhcp=None, **kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(SubnetRequest, self).__init__()
|
||||
self.name = name
|
||||
self.tenant_id = tenant_id
|
||||
self.network_id = network_id
|
||||
self.ip_version = ip_version
|
||||
self.cidr = cidr
|
||||
self.gateway_ip = gateway_ip
|
||||
self.allocation_pools = allocation_pools
|
||||
self.dns_nameservers = dns_nameservers
|
||||
self.host_routes = host_routes
|
||||
self.enable_dhcp = enable_dhcp
|
||||
|
||||
def _obj_to_json(self):
|
||||
|
||||
body = {
|
||||
'name': self.name,
|
||||
'tenant_id': self.tenant_id,
|
||||
'ip_version': self.ip_version,
|
||||
'network_id': self.network_id,
|
||||
'cidr': self.cidr,
|
||||
'dns_nameservers': self.dns_nameservers,
|
||||
'gateway_ip': self.gateway_ip,
|
||||
'allocation_pools': self.allocation_pools,
|
||||
'host_routes': self.host_routes,
|
||||
'enable_dhcp': self.enable_dhcp
|
||||
}
|
||||
|
||||
# The client should instantiate the model with only desired parameters
|
||||
body = self._remove_empty_values(body)
|
||||
main_body = {'subnet': body}
|
||||
return json.dumps(main_body)
|
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
104
cloudcafe/networking/networks/common/models/response/network.py
Normal file
104
cloudcafe/networking/networks/common/models/response/network.py
Normal file
@ -0,0 +1,104 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingListModel, \
|
||||
AutoMarshallingModel
|
||||
|
||||
|
||||
class Network(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Network model object for the OpenStack Neutron v2.0 API
|
||||
responses for networks show and list (GET) calls
|
||||
@param string id: UUID for the network (CRUD: R)
|
||||
@param string name: human readable name for the network,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false, the admin state
|
||||
of the network. If down, the network does not forward packets.
|
||||
Default value is True (CRUD: CRU)
|
||||
@param string status: Indicates if the network is currently
|
||||
operational. Possible values: ACTIVE, DOWN, BUILD, ERROR. (CRUD: R)
|
||||
@param list subnets: associated network subnets UUID list. (CRUD: R)
|
||||
@param bool shared: specifies if the network can be accessed by any
|
||||
tenant. Default value is False. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
"""
|
||||
NETWORK = 'network'
|
||||
|
||||
def __init__(self, id_=None, name=None, admin_state_up=None,
|
||||
status=None, subnets=None, shared=None, tenant_id=None,
|
||||
**kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(Network, self).__init__()
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.admin_state_up = admin_state_up
|
||||
self.status = status
|
||||
self.subnets = subnets
|
||||
self.shared = shared
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return network object from a JSON serialized string"""
|
||||
|
||||
ret = None
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.NETWORK in json_dict:
|
||||
network_dict = json_dict.get(cls.NETWORK)
|
||||
ret = Network(**network_dict)
|
||||
return ret
|
||||
|
||||
|
||||
class Networks(AutoMarshallingListModel):
|
||||
|
||||
NETWORKS = 'networks'
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return a list of network objects from a JSON serialized string"""
|
||||
|
||||
ret = cls()
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.NETWORKS in json_dict:
|
||||
networks = json_dict.get(cls.NETWORKS)
|
||||
for network in networks:
|
||||
ret.append(Network(**network))
|
||||
return ret
|
115
cloudcafe/networking/networks/common/models/response/port.py
Normal file
115
cloudcafe/networking/networks/common/models/response/port.py
Normal file
@ -0,0 +1,115 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingListModel
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class Port(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Port model object for the OpenStack Neutron v2.0 API
|
||||
responses for ports show and list (GET) calls
|
||||
@param string id: UUID for the port (CRUD: R)
|
||||
@param string network_id: network port is associated with (CRUD: CR)
|
||||
@param string name: human readable name for the port,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false (default true), the admin state
|
||||
of the port. If down, the port does not forward packets (CRUD: CRU)
|
||||
@param string status: Indicates if the port is currently
|
||||
operational. Possible values: ACTIVE, DOWN, BUILD, ERROR (CRUD: R)
|
||||
@param string mac_address: mac address to use on the port (CRUD: CR)
|
||||
@param list(dict) fixed_ips: ip addresses for the port associating the
|
||||
port with the subnets where the IPs come from (CRUD: CRU)
|
||||
@param string device_id: id of device using this port (CRUD: CRUD)
|
||||
@param string device_owner: entity using this port (ex. dhcp agent,
|
||||
CRUD: CRUD)
|
||||
@param string tenant_id: owner of the port (CRUD: CR)
|
||||
@param list(dict) security_groups: ids of any security groups associated
|
||||
with the port (CRUD: CRUD)
|
||||
"""
|
||||
|
||||
PORT = 'port'
|
||||
|
||||
def __init__(self, id_=None, network_id=None, name=None,
|
||||
admin_state_up=None, status=None, mac_address=None,
|
||||
fixed_ips=None, device_id=None, device_owner=None,
|
||||
tenant_id=None, security_groups=None, **kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(Port, self).__init__()
|
||||
self.id = id_
|
||||
self.network_id = network_id
|
||||
self.name = name
|
||||
self.admin_state_up = admin_state_up
|
||||
self.status = status
|
||||
self.mac_address = mac_address
|
||||
self.fixed_ips = fixed_ips
|
||||
self.device_id = device_id
|
||||
self.device_owner = device_owner
|
||||
self.tenant_id = tenant_id
|
||||
self.security_groups = security_groups
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return port object from a JSON serialized string"""
|
||||
|
||||
ret = None
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.PORT in json_dict:
|
||||
subnet_dict = json_dict.get(cls.PORT)
|
||||
ret = Port(**subnet_dict)
|
||||
return ret
|
||||
|
||||
|
||||
class Ports(AutoMarshallingListModel):
|
||||
|
||||
PORTS = 'ports'
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return a list of port objects from a JSON serialized string"""
|
||||
|
||||
ret = cls()
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.PORTS in json_dict:
|
||||
ports = json_dict.get(cls.PORTS)
|
||||
for port in ports:
|
||||
ret.append(Port(**port))
|
||||
return ret
|
115
cloudcafe/networking/networks/common/models/response/subnet.py
Normal file
115
cloudcafe/networking/networks/common/models/response/subnet.py
Normal file
@ -0,0 +1,115 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingListModel
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class Subnet(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: Subnet model object for the OpenStack Neutron v2.0 API
|
||||
responses for subnets show and list (GET) calls
|
||||
@param string id: UUID for the subnet (CRUD: R)
|
||||
@param string name: human readable name for the subnet,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
@param string network_id: network subnet is associated with (CRUD: CR)
|
||||
@param int ip_version: IP version 4 or 6 (CRUD: CR)
|
||||
@param string cidr: represents IP range for the subnet and should be in
|
||||
the form <network_address>/<prefix> (CRUD: CR)
|
||||
@param string gateway_ip: default gateway used by devices in the subnet
|
||||
(CRUD: CRUD)
|
||||
@param list(str) dns_nameservers: DNS name servers used by subnet hosts
|
||||
(CRUD: CRU)
|
||||
@param list(dict) allocation_pools: sub range of cidr available for dynamic
|
||||
allocation to ports (CRUD: CR)
|
||||
@param list(dict) host_routes: routes that should be used by devices with
|
||||
IPs from this subnet (does not includes the local route, CRUD: CRU)
|
||||
@param bool enable_dhcp: whether DHCP is enabled (CRUD:CRU)
|
||||
"""
|
||||
|
||||
SUBNET = 'subnet'
|
||||
|
||||
def __init__(self, id_=None, name=None, tenant_id=None, network_id=None,
|
||||
ip_version=None, cidr=None, gateway_ip=None,
|
||||
dns_nameservers=None, allocation_pools=None,
|
||||
host_routes=None, enable_dhcp=None, **kwargs):
|
||||
|
||||
# kwargs is to be used for extensions
|
||||
super(Subnet, self).__init__()
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.tenant_id = tenant_id
|
||||
self.network_id = network_id
|
||||
self.ip_version = ip_version
|
||||
self.cidr = cidr
|
||||
self.gateway_ip = gateway_ip
|
||||
self.dns_nameservers = dns_nameservers
|
||||
self.allocation_pools = allocation_pools
|
||||
self.host_routes = host_routes
|
||||
self.enable_dhcp = enable_dhcp
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return subnet object from a JSON serialized string"""
|
||||
|
||||
ret = None
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.SUBNET in json_dict:
|
||||
subnet_dict = json_dict.get(cls.SUBNET)
|
||||
ret = Subnet(**subnet_dict)
|
||||
return ret
|
||||
|
||||
|
||||
class Subnets(AutoMarshallingListModel):
|
||||
|
||||
SUBNETS = 'subnets'
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""Return a list of subnet objects from a JSON serialized string"""
|
||||
|
||||
ret = cls()
|
||||
json_response = json.loads(serialized_str)
|
||||
|
||||
# Creating a deep copy just in case later we want the original resp
|
||||
json_dict = copy.deepcopy(json_response)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_ or if they have a
|
||||
# special character within the name replacing it for an underscore too
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
|
||||
if cls.SUBNETS in json_dict:
|
||||
subnets = json_dict.get(cls.SUBNETS)
|
||||
for subnet in subnets:
|
||||
ret.append(Subnet(**subnet))
|
||||
return ret
|
146
cloudcafe/networking/networks/composites.py
Normal file
146
cloudcafe/networking/networks/composites.py
Normal file
@ -0,0 +1,146 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.auth.provider import MemoizedAuthServiceComposite
|
||||
from cloudcafe.networking.networks.config import MarshallingConfig,\
|
||||
NetworksConfig, NetworksEndpointConfig, NetworksAdminEndpointConfig,\
|
||||
NetworksAdminAuthConfig, NetworksSecondUserConfig, \
|
||||
NetworksAdminUserConfig, UserAuthConfig, UserConfig
|
||||
from cloudcafe.networking.networks.networks_api.client import NetworksClient
|
||||
from cloudcafe.networking.networks.networks_api.config import NetworksAPIConfig
|
||||
from cloudcafe.networking.networks.networks_api.behaviors \
|
||||
import NetworksAPIBehaviors
|
||||
from cloudcafe.networking.networks.ports_api.client import PortsClient
|
||||
from cloudcafe.networking.networks.ports_api.config import PortsAPIConfig
|
||||
from cloudcafe.networking.networks.ports_api.behaviors import PortsAPIBehaviors
|
||||
from cloudcafe.networking.networks.subnets_api.client import SubnetsClient
|
||||
from cloudcafe.networking.networks.subnets_api.config import SubnetsAPIConfig
|
||||
from cloudcafe.networking.networks.subnets_api.behaviors \
|
||||
import SubnetsAPIBehaviors
|
||||
|
||||
|
||||
class _NetworksAuthComposite(MemoizedAuthServiceComposite):
|
||||
_networks_config = NetworksConfig
|
||||
_networks_endpoint_config = NetworksEndpointConfig
|
||||
_auth_endpoint_config = UserAuthConfig
|
||||
_auth_user_config = UserConfig
|
||||
|
||||
def __init__(self):
|
||||
self.networks_endpoint_config = self._networks_endpoint_config()
|
||||
self.marshalling_config = MarshallingConfig()
|
||||
self._auth_endpoint_config = self._auth_endpoint_config()
|
||||
self._auth_user_config = self._auth_user_config()
|
||||
|
||||
super(_NetworksAuthComposite, self).__init__(
|
||||
service_name=self.networks_endpoint_config.networks_endpoint_name,
|
||||
region=self.networks_endpoint_config.region,
|
||||
endpoint_config=self._auth_endpoint_config,
|
||||
user_config=self._auth_user_config)
|
||||
|
||||
self.networks_url = self.public_url
|
||||
|
||||
# Overriding the publicURL if networks_endpoint_url given
|
||||
if self.networks_endpoint_config.networks_endpoint_url:
|
||||
self.networks_url = \
|
||||
self.networks_endpoint_config.networks_endpoint_url
|
||||
|
||||
# Ending backslash is not expected, removing if present
|
||||
if self.networks_url[-1] == '/':
|
||||
self.networks_url = self.networks_url[:-1]
|
||||
|
||||
self.client_args = {
|
||||
'url': self.networks_url,
|
||||
'auth_token': self.token_id,
|
||||
'serialize_format': self.marshalling_config.serializer,
|
||||
'deserialize_format': self.marshalling_config.deserializer}
|
||||
|
||||
if self.networks_endpoint_config.header_tenant_id:
|
||||
self.client_args.update(
|
||||
tenant_id=self.networks_endpoint_config.header_tenant_id)
|
||||
|
||||
|
||||
class _NetworksAdminAuthComposite(_NetworksAuthComposite):
|
||||
_networks_endpoint_config = NetworksAdminEndpointConfig
|
||||
_auth_endpoint_config = NetworksAdminAuthConfig
|
||||
_auth_user_config = NetworksAdminUserConfig
|
||||
|
||||
|
||||
class NetworksComposite(object):
|
||||
networks_auth_composite = _NetworksAuthComposite
|
||||
|
||||
def __init__(self):
|
||||
auth_composite = self.networks_auth_composite()
|
||||
self.url = auth_composite.networks_url
|
||||
self.user = auth_composite._auth_user_config
|
||||
self.config = NetworksConfig()
|
||||
self.networks = NetworksAPIComposite(auth_composite)
|
||||
self.subnets = SubnetsAPIComposite(auth_composite)
|
||||
self.ports = PortsAPIComposite(auth_composite)
|
||||
|
||||
self.networks.behaviors = self.networks.behavior_class(
|
||||
networks_client=self.networks.client,
|
||||
networks_config=self.networks.config,
|
||||
subnets_client=self.subnets.client,
|
||||
subnets_config=self.subnets.config,
|
||||
ports_client=self.ports.client,
|
||||
ports_config=self.ports.config)
|
||||
|
||||
self.subnets.behaviors = self.subnets.behavior_class(
|
||||
subnets_client=self.subnets.client,
|
||||
subnets_config=self.subnets.config,
|
||||
networks_client=self.networks.client,
|
||||
networks_config=self.networks.config,
|
||||
ports_client=self.ports.client,
|
||||
ports_config=self.ports.config)
|
||||
|
||||
self.ports.behaviors = self.ports.behavior_class(
|
||||
ports_client=self.ports.client,
|
||||
ports_config=self.ports.config,
|
||||
networks_client=self.networks.client,
|
||||
networks_config=self.networks.config,
|
||||
subnets_client=self.subnets.client,
|
||||
subnets_config=self.subnets.config)
|
||||
|
||||
|
||||
class NetworksAdminComposite(NetworksComposite):
|
||||
_auth_composite = _NetworksAdminAuthComposite
|
||||
|
||||
|
||||
class NetworksAPIComposite(NetworksComposite):
|
||||
behavior_class = NetworksAPIBehaviors
|
||||
|
||||
def __init__(self, auth_composite):
|
||||
self.config = NetworksAPIConfig()
|
||||
self.client = NetworksClient(**auth_composite.client_args)
|
||||
self.behaviors = None
|
||||
|
||||
|
||||
class SubnetsAPIComposite(NetworksComposite):
|
||||
behavior_class = SubnetsAPIBehaviors
|
||||
|
||||
def __init__(self, auth_composite):
|
||||
self.config = SubnetsAPIConfig()
|
||||
self.client = SubnetsClient(**auth_composite.client_args)
|
||||
self.behaviors = None
|
||||
|
||||
|
||||
class PortsAPIComposite(NetworksComposite):
|
||||
behavior_class = PortsAPIBehaviors
|
||||
|
||||
def __init__(self, auth_composite):
|
||||
self.config = PortsAPIConfig()
|
||||
self.client = PortsClient(**auth_composite.client_args)
|
||||
self.behaviors = None
|
90
cloudcafe/networking/networks/config.py
Normal file
90
cloudcafe/networking/networks/config.py
Normal file
@ -0,0 +1,90 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.auth.config import UserAuthConfig, UserConfig
|
||||
from cloudcafe.common.models.configuration import ConfigSectionInterface
|
||||
|
||||
|
||||
class MarshallingConfig(ConfigSectionInterface):
|
||||
SECTION_NAME = 'marshalling'
|
||||
|
||||
@property
|
||||
def serializer(self):
|
||||
return self.get("serialize_format")
|
||||
|
||||
@property
|
||||
def deserializer(self):
|
||||
return self.get("deserialize_format")
|
||||
|
||||
|
||||
class NetworksConfig(ConfigSectionInterface):
|
||||
|
||||
SECTION_NAME = 'networks'
|
||||
|
||||
@property
|
||||
def public_network_id(self):
|
||||
"""The uuid of the public network"""
|
||||
return self.get("public_network_id",
|
||||
"00000000-0000-0000-0000-000000000000")
|
||||
|
||||
@property
|
||||
def service_network_id(self):
|
||||
"""The uuid of the service network (aka private)"""
|
||||
return self.get("service_network_id",
|
||||
"11111111-1111-1111-1111-111111111111")
|
||||
|
||||
|
||||
class NetworksEndpointConfig(ConfigSectionInterface):
|
||||
|
||||
SECTION_NAME = 'networks_endpoint'
|
||||
|
||||
@property
|
||||
def region(self):
|
||||
return self.get("region")
|
||||
|
||||
@property
|
||||
def networks_endpoint_name(self):
|
||||
return self.get("networks_endpoint_name")
|
||||
|
||||
@property
|
||||
def networks_endpoint_url(self):
|
||||
"""Optional override of the Networks url"""
|
||||
return self.get("networks_endpoint_url")
|
||||
|
||||
@property
|
||||
def header_tenant_id(self):
|
||||
"""Optional tenant ID to set in client request headers"""
|
||||
return self.get("header_tenant_id")
|
||||
|
||||
|
||||
class NetworksAdminEndpointConfig(NetworksEndpointConfig):
|
||||
"""RackerAdmin API endpoint and name"""
|
||||
SECTION_NAME = 'networks_admin_endpoint'
|
||||
|
||||
|
||||
class NetworksAdminAuthConfig(UserAuthConfig):
|
||||
"""Networks Admin endpoint and auth strategy, for ex. keystone"""
|
||||
SECTION_NAME = 'networks_admin_auth_config'
|
||||
|
||||
|
||||
class NetworksSecondUserConfig(UserConfig):
|
||||
|
||||
SECTION_NAME = 'networks_secondary_user'
|
||||
|
||||
|
||||
class NetworksAdminUserConfig(UserConfig):
|
||||
|
||||
SECTION_NAME = 'networks_admin_user'
|
15
cloudcafe/networking/networks/networks_api/__init__.py
Normal file
15
cloudcafe/networking/networks/networks_api/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
30
cloudcafe/networking/networks/networks_api/behaviors.py
Normal file
30
cloudcafe/networking/networks/networks_api/behaviors.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cafe.engine.behaviors import BaseBehavior
|
||||
|
||||
|
||||
class NetworksAPIBehaviors(BaseBehavior):
|
||||
|
||||
def __init__(self, networks_client, networks_config, subnets_client,
|
||||
subnets_config, ports_client, ports_config):
|
||||
super(NetworksAPIBehaviors, self).__init__()
|
||||
self.config = networks_config
|
||||
self.client = networks_client
|
||||
self.subnets_client = subnets_client
|
||||
self.subnets_config = subnets_config
|
||||
self.ports_client = ports_client
|
||||
self.ports_config = ports_config
|
137
cloudcafe/networking/networks/networks_api/client.py
Normal file
137
cloudcafe/networking/networks/networks_api/client.py
Normal file
@ -0,0 +1,137 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||
from cloudcafe.networking.networks.common.models.request.network \
|
||||
import NetworkRequest
|
||||
from cloudcafe.networking.networks.common.models.response.network \
|
||||
import Network, Networks
|
||||
|
||||
|
||||
class NetworksClient(AutoMarshallingHTTPClient):
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None, tenant_id=None):
|
||||
"""
|
||||
@param string url: Base URL for the networks service
|
||||
@param string auth_token: Auth token to be used for all requests
|
||||
@param string serialize_format: Format for serializing requests
|
||||
@param string deserialize_format: Format for de-serializing responses
|
||||
@param string tenant_id: optional tenant id to be included in the
|
||||
header if given
|
||||
"""
|
||||
super(NetworksClient, self).__init__(serialize_format,
|
||||
deserialize_format)
|
||||
self.auth_token = auth_token
|
||||
self.default_headers['X-Auth-Token'] = auth_token
|
||||
ct = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.serialize_format)
|
||||
accept = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.deserialize_format)
|
||||
self.default_headers['Content-Type'] = ct
|
||||
self.default_headers['Accept'] = accept
|
||||
if tenant_id:
|
||||
self.default_headers['X-Auth-Project-Id'] = tenant_id
|
||||
self.url = url
|
||||
|
||||
def create_network(self, name=None, admin_state_up=None, shared=None,
|
||||
tenant_id=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates a Network
|
||||
@param string name: human readable name for the network,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false, the admin state
|
||||
of the network. If down, the network does not forward packets.
|
||||
Default value is True (CRUD: CRU)
|
||||
@param bool shared: specifies if the network can be accessed by any
|
||||
tenant. Default value is False. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
"""
|
||||
url = '{base_url}/networks'.format(base_url=self.url)
|
||||
|
||||
request = NetworkRequest(name=name, admin_state_up=admin_state_up,
|
||||
shared=shared, tenant_id=tenant_id)
|
||||
|
||||
resp = self.request('POST', url,
|
||||
response_entity_type=Network,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def update_network(self, network_id, name=None, admin_state_up=None,
|
||||
shared=None, tenant_id=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Updates a specified Network
|
||||
@param string network_id: The UUID for the network
|
||||
@param string name: human readable name for the network,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false, the admin state
|
||||
of the network. If down, the network does not forward packets.
|
||||
Default value is True (CRUD: CRU)
|
||||
@param bool shared: specifies if the network can be accessed by any
|
||||
tenant. Default value is False. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
"""
|
||||
|
||||
url = '{base_url}/networks/{network_id}'.format(
|
||||
base_url=self.url, network_id=network_id)
|
||||
|
||||
request = NetworkRequest(name=name, admin_state_up=admin_state_up,
|
||||
shared=shared, tenant_id=tenant_id)
|
||||
resp = self.request('PUT', url,
|
||||
response_entity_type=Network,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def get_network(self, network_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Shows information for a specified network
|
||||
@param string network_id: The UUID for the network
|
||||
"""
|
||||
|
||||
url = '{base_url}/networks/{network_id}'.format(
|
||||
base_url=self.url, network_id=network_id)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Network,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def list_networks(self, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists networks
|
||||
"""
|
||||
|
||||
# TODO: add field query params to filter the response
|
||||
url = '{base_url}/networks'.format(base_url=self.url)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Networks,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def delete_network(self, network_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Deletes a specified network and its associated resources
|
||||
@param string network_id: The UUID for the network
|
||||
"""
|
||||
|
||||
url = '{base_url}/networks/{network_id}'.format(
|
||||
base_url=self.url, network_id=network_id)
|
||||
resp = self.request('DELETE', url,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
53
cloudcafe/networking/networks/networks_api/config.py
Normal file
53
cloudcafe/networking/networks/networks_api/config.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.common.models.configuration import ConfigSectionInterface
|
||||
|
||||
|
||||
class NetworksAPIConfig(ConfigSectionInterface):
|
||||
"""Network is the resource"""
|
||||
|
||||
SECTION_NAME = 'networks_api'
|
||||
|
||||
@property
|
||||
def resource_build_attempts(self):
|
||||
"""Number of times to try to create a resource"""
|
||||
return int(self.get("resource_build_attempts", 1))
|
||||
|
||||
@property
|
||||
def keep_resources(self):
|
||||
"""Flag for not deleting resources on tearDown"""
|
||||
return self.get_boolean("keep_resources", False)
|
||||
|
||||
@property
|
||||
def keep_resources_on_failure(self):
|
||||
"""Flag for not deleting resources w failures on tearDown"""
|
||||
return self.get_boolean("keep_resources_on_failure", False)
|
||||
|
||||
@property
|
||||
def resource_create_timeout(self):
|
||||
"""Seconds to wait for creating a resource"""
|
||||
return int(self.get("resource_create_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_delete_timeout(self):
|
||||
"""Seconds to wait for deleting a resource"""
|
||||
return int(self.get("resource_delete_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_change_status_timeout(self):
|
||||
"""Seconds to wait for a status change in the resource"""
|
||||
return int(self.get("resource_change_status_timeout", 15))
|
15
cloudcafe/networking/networks/ports_api/__init__.py
Normal file
15
cloudcafe/networking/networks/ports_api/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
30
cloudcafe/networking/networks/ports_api/behaviors.py
Normal file
30
cloudcafe/networking/networks/ports_api/behaviors.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cafe.engine.behaviors import BaseBehavior
|
||||
|
||||
|
||||
class PortsAPIBehaviors(BaseBehavior):
|
||||
|
||||
def __init__(self, ports_client, ports_config, networks_client,
|
||||
networks_config, subnets_client, subnets_config):
|
||||
super(PortsAPIBehaviors, self).__init__()
|
||||
self.config = ports_config
|
||||
self.client = ports_client
|
||||
self.networks_client = networks_client
|
||||
self.networks_config = networks_config
|
||||
self.subnets_client = subnets_client
|
||||
self.subnets_config = subnets_config
|
155
cloudcafe/networking/networks/ports_api/client.py
Normal file
155
cloudcafe/networking/networks/ports_api/client.py
Normal file
@ -0,0 +1,155 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||
from cloudcafe.networking.networks.common.models.request.port \
|
||||
import PortRequest
|
||||
from cloudcafe.networking.networks.common.models.response.port \
|
||||
import Port, Ports
|
||||
|
||||
|
||||
class PortsClient(AutoMarshallingHTTPClient):
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None, tenant_id=None):
|
||||
"""
|
||||
@param string url: Base URL for the ports service
|
||||
@param string auth_token: Auth token to be used for all requests
|
||||
@param string serialize_format: Format for serializing requests
|
||||
@param string deserialize_format: Format for de-serializing responses
|
||||
@param string tenant_id: optional tenant id to be included in the
|
||||
header if given
|
||||
"""
|
||||
super(PortsClient, self).__init__(serialize_format,
|
||||
deserialize_format)
|
||||
self.auth_token = auth_token
|
||||
self.default_headers['X-Auth-Token'] = auth_token
|
||||
ct = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.serialize_format)
|
||||
accept = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.deserialize_format)
|
||||
self.default_headers['Content-Type'] = ct
|
||||
self.default_headers['Accept'] = accept
|
||||
if tenant_id:
|
||||
self.default_headers['X-Auth-Project-Id'] = tenant_id
|
||||
self.url = url
|
||||
|
||||
def create_port(self, network_id, name=None, admin_state_up=None,
|
||||
mac_address=None, fixed_ips=None, device_id=None,
|
||||
device_owner=None, tenant_id=None, security_groups=None,
|
||||
requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates a Port
|
||||
@param string network_id: network port is associated with (CRUD: CR)
|
||||
@param string name: human readable name for the port,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false (default true),
|
||||
the admin state of the port. If down, the port does not forward
|
||||
packets (CRUD: CRU)
|
||||
@param string mac_address: mac address to use on the port (CRUD: CR)
|
||||
@param list(dict) fixed_ips: ip addresses for the port associating the
|
||||
port with the subnets where the IPs come from (CRUD: CRU)
|
||||
@param string device_id: id of device using this port (CRUD: CRUD)
|
||||
@param string device_owner: entity using this port (ex. dhcp agent,
|
||||
CRUD: CRUD)
|
||||
@param string tenant_id: owner of the port (CRUD: CR)
|
||||
@param list(dict) security_groups: ids of any security groups
|
||||
associated with the port (CRUD: CRUD)
|
||||
"""
|
||||
|
||||
url = '{base_url}/ports'.format(base_url=self.url)
|
||||
|
||||
request = PortRequest(
|
||||
network_id=network_id, name=name, admin_state_up=admin_state_up,
|
||||
mac_address=mac_address, fixed_ips=fixed_ips, device_id=device_id,
|
||||
device_owner=device_owner, tenant_id=tenant_id,
|
||||
security_groups=security_groups)
|
||||
|
||||
resp = self.request('POST', url,
|
||||
response_entity_type=Port,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def update_port(self, port_id, name=None, admin_state_up=None,
|
||||
fixed_ips=None, device_id=None, device_owner=None,
|
||||
security_groups=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Updates a specified Port
|
||||
@param string port_id: The UUID for the port
|
||||
@param string name: human readable name for the port,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param bool admin_state_up: true or false (default true),
|
||||
the admin state of the port. If down, the port does not forward
|
||||
packets (CRUD: CRU)
|
||||
@param list(dict) fixed_ips: ip addresses for the port associating the
|
||||
port with the subnets where the IPs come from (CRUD: CRU)
|
||||
@param string device_id: id of device using this port (CRUD: CRUD)
|
||||
@param string device_owner: entity using this port (ex. dhcp agent,
|
||||
CRUD: CRUD)
|
||||
@param list(dict) security_groups: ids of any security groups
|
||||
associated with the port (CRUD: CRUD)
|
||||
"""
|
||||
|
||||
url = '{base_url}/ports/{port_id}'.format(
|
||||
base_url=self.url, port_id=port_id)
|
||||
|
||||
request = PortRequest(name=name, admin_state_up=admin_state_up,
|
||||
fixed_ips=fixed_ips, device_id=device_id,
|
||||
device_owner=device_owner, security_groups=security_groups)
|
||||
resp = self.request('PUT', url,
|
||||
response_entity_type=Port,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def get_port(self, port_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Shows information for a specified port
|
||||
@param string port_id: The UUID for the port
|
||||
"""
|
||||
|
||||
url = '{base_url}/ports/{port_id}'.format(
|
||||
base_url=self.url, port_id=port_id)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Port,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def list_ports(self, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists ports
|
||||
"""
|
||||
|
||||
# TODO: add field query params to filter the response
|
||||
url = '{base_url}/ports'.format(base_url=self.url)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Ports,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def delete_port(self, port_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Deletes a specified port
|
||||
@param string port_id: The UUID for the port
|
||||
"""
|
||||
|
||||
url = '{base_url}/ports/{port_id}'.format(
|
||||
base_url=self.url, port_id=port_id)
|
||||
resp = self.request('DELETE', url,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
53
cloudcafe/networking/networks/ports_api/config.py
Normal file
53
cloudcafe/networking/networks/ports_api/config.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.common.models.configuration import ConfigSectionInterface
|
||||
|
||||
|
||||
class PortsAPIConfig(ConfigSectionInterface):
|
||||
"""Port is the resource"""
|
||||
|
||||
SECTION_NAME = 'ports_api'
|
||||
|
||||
@property
|
||||
def resource_build_attempts(self):
|
||||
"""Number of times to try to create a resource"""
|
||||
return int(self.get("resource_build_attempts", 1))
|
||||
|
||||
@property
|
||||
def keep_resources(self):
|
||||
"""Flag for not deleting resources on tearDown"""
|
||||
return self.get_boolean("keep_resources", False)
|
||||
|
||||
@property
|
||||
def keep_resources_on_failure(self):
|
||||
"""Flag for not deleting resources w failures on tearDown"""
|
||||
return self.get_boolean("keep_resources_on_failure", False)
|
||||
|
||||
@property
|
||||
def resource_create_timeout(self):
|
||||
"""Seconds to wait for creating a resource"""
|
||||
return int(self.get("resource_create_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_delete_timeout(self):
|
||||
"""Seconds to wait for deleting a resource"""
|
||||
return int(self.get("resource_delete_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_change_status_timeout(self):
|
||||
"""Seconds to wait for a status change in the resource"""
|
||||
return int(self.get("resource_change_status_timeout", 15))
|
15
cloudcafe/networking/networks/subnets_api/__init__.py
Normal file
15
cloudcafe/networking/networks/subnets_api/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
30
cloudcafe/networking/networks/subnets_api/behaviors.py
Normal file
30
cloudcafe/networking/networks/subnets_api/behaviors.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cafe.engine.behaviors import BaseBehavior
|
||||
|
||||
|
||||
class SubnetsAPIBehaviors(BaseBehavior):
|
||||
|
||||
def __init__(self, subnets_client, subnets_config, networks_client,
|
||||
networks_config, ports_client, ports_config):
|
||||
super(SubnetsAPIBehaviors, self).__init__()
|
||||
self.config = subnets_config
|
||||
self.client = subnets_client
|
||||
self.networks_client = networks_client
|
||||
self.networks_config = networks_config
|
||||
self.ports_client = ports_client
|
||||
self.ports_config = ports_config
|
157
cloudcafe/networking/networks/subnets_api/client.py
Normal file
157
cloudcafe/networking/networks/subnets_api/client.py
Normal file
@ -0,0 +1,157 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||
from cloudcafe.networking.networks.common.models.request.subnet \
|
||||
import SubnetRequest
|
||||
from cloudcafe.networking.networks.common.models.response.subnet \
|
||||
import Subnet, Subnets
|
||||
|
||||
|
||||
class SubnetsClient(AutoMarshallingHTTPClient):
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None, tenant_id=None):
|
||||
"""
|
||||
@param string url: Base URL for the subnets service
|
||||
@param string auth_token: Auth token to be used for all requests
|
||||
@param string serialize_format: Format for serializing requests
|
||||
@param string deserialize_format: Format for de-serializing responses
|
||||
@param string tenant_id: optional tenant id to be included in the
|
||||
header if given
|
||||
"""
|
||||
super(SubnetsClient, self).__init__(serialize_format,
|
||||
deserialize_format)
|
||||
self.auth_token = auth_token
|
||||
self.default_headers['X-Auth-Token'] = auth_token
|
||||
ct = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.serialize_format)
|
||||
accept = '{content_type}/{content_subtype}'.format(
|
||||
content_type='application',
|
||||
content_subtype=self.deserialize_format)
|
||||
self.default_headers['Content-Type'] = ct
|
||||
self.default_headers['Accept'] = accept
|
||||
if tenant_id:
|
||||
self.default_headers['X-Auth-Project-Id'] = tenant_id
|
||||
self.url = url
|
||||
|
||||
def create_subnet(self, network_id, ip_version, cidr, name=None,
|
||||
tenant_id=None, gateway_ip=None, dns_nameservers=None,
|
||||
allocation_pools=None, host_routes=None,
|
||||
enable_dhcp=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates a Subnet
|
||||
@param string name: human readable name for the subnet,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param string tenant_id: owner of the network. (CRUD: CR)
|
||||
@param string network_id: network subnet is associated with (CRUD: CR)
|
||||
@param int ip_version: IP version 4 or 6 (CRUD: CR)
|
||||
@param string cidr: represents IP range for the subnet and should be in
|
||||
the form <network_address>/<prefix> (CRUD: CR)
|
||||
@param string gateway_ip: default gateway used by devices in the subnet
|
||||
(CRUD: CRUD)
|
||||
@param list(str) dns_nameservers: DNS name servers used by subnet hosts
|
||||
(CRUD: CRU)
|
||||
@param list(dict) allocation_pools: sub range of cidr available for
|
||||
dynamic allocation to ports (CRUD: CR)
|
||||
@param list(dict) host_routes: routes that should be used by devices
|
||||
with IPs from this subnet (does not includes the local route,
|
||||
CRUD: CRU)
|
||||
@param bool enable_dhcp: whether DHCP is enabled (CRUD:CRU)
|
||||
"""
|
||||
url = '{base_url}/subnets'.format(base_url=self.url)
|
||||
|
||||
request = SubnetRequest(network_id=network_id, ip_version=ip_version,
|
||||
cidr=cidr, name=name, tenant_id=tenant_id,
|
||||
gateway_ip=gateway_ip,
|
||||
dns_nameservers=dns_nameservers,
|
||||
allocation_pools=allocation_pools,
|
||||
host_routes=host_routes,
|
||||
enable_dhcp=enable_dhcp)
|
||||
|
||||
resp = self.request('POST', url,
|
||||
response_entity_type=Subnet,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def update_subnet(self, subnet_id, name=None, gateway_ip=None,
|
||||
dns_nameservers=None, host_routes=None,
|
||||
enable_dhcp=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Updates a specified Subnet
|
||||
@param string subnet_id: The UUID for the subnet
|
||||
@param string name: human readable name for the subnet,
|
||||
may not be unique. (CRUD: CRU)
|
||||
@param string gateway_ip: default gateway used by devices in the subnet
|
||||
(CRUD: CRUD)
|
||||
@param list(str) dns_nameservers: DNS name servers used by subnet hosts
|
||||
(CRUD: CRU)
|
||||
@param list(dict) host_routes: routes that should be used by devices
|
||||
with IPs from this subnet (does not includes the local route,
|
||||
CRUD: CRU)
|
||||
@param bool enable_dhcp: whether DHCP is enabled (CRUD:CRU)
|
||||
"""
|
||||
|
||||
url = '{base_url}/subnets/{subnet_id}'.format(
|
||||
base_url=self.url, subnet_id=subnet_id)
|
||||
|
||||
request = SubnetRequest(name=name, gateway_ip=gateway_ip,
|
||||
dns_nameservers=dns_nameservers,
|
||||
host_routes=host_routes,
|
||||
enable_dhcp=enable_dhcp)
|
||||
resp = self.request('PUT', url,
|
||||
response_entity_type=Subnet,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def get_subnet(self, subnet_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Shows information for a specified subnet
|
||||
@param string subnet_id: The UUID for the subnet
|
||||
"""
|
||||
|
||||
url = '{base_url}/subnets/{subnet_id}'.format(
|
||||
base_url=self.url, subnet_id=subnet_id)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Subnet,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def list_subnets(self, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists subnets
|
||||
"""
|
||||
|
||||
# TODO: add field query params to filter the response
|
||||
url = '{base_url}/subnets'.format(base_url=self.url)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=Subnets,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def delete_subnet(self, subnet_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Deletes a specified subnet
|
||||
@param string subnet_id: The UUID for the subnet
|
||||
"""
|
||||
|
||||
url = '{base_url}/subnets/{subnet_id}'.format(
|
||||
base_url=self.url, subnet_id=subnet_id)
|
||||
resp = self.request('DELETE', url,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
53
cloudcafe/networking/networks/subnets_api/config.py
Normal file
53
cloudcafe/networking/networks/subnets_api/config.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cloudcafe.common.models.configuration import ConfigSectionInterface
|
||||
|
||||
|
||||
class SubnetsAPIConfig(ConfigSectionInterface):
|
||||
"""Subnet is the resource"""
|
||||
|
||||
SECTION_NAME = 'subnets_api'
|
||||
|
||||
@property
|
||||
def resource_build_attempts(self):
|
||||
"""Number of times to try to create a resource"""
|
||||
return int(self.get("resource_build_attempts", 1))
|
||||
|
||||
@property
|
||||
def keep_resources(self):
|
||||
"""Flag for not deleting resources on tearDown"""
|
||||
return self.get_boolean("keep_resources", False)
|
||||
|
||||
@property
|
||||
def keep_resources_on_failure(self):
|
||||
"""Flag for not deleting resources w failures on tearDown"""
|
||||
return self.get_boolean("keep_resources_on_failure", False)
|
||||
|
||||
@property
|
||||
def resource_create_timeout(self):
|
||||
"""Seconds to wait for creating a resource"""
|
||||
return int(self.get("resource_create_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_delete_timeout(self):
|
||||
"""Seconds to wait for deleting a resource"""
|
||||
return int(self.get("resource_delete_timeout", 15))
|
||||
|
||||
@property
|
||||
def resource_change_status_timeout(self):
|
||||
"""Seconds to wait for a status change in the resource"""
|
||||
return int(self.get("resource_change_status_timeout", 15))
|
15
metatests/cloudcafe/networking/networks/models/__init__.py
Normal file
15
metatests/cloudcafe/networking/networks/models/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
187
metatests/cloudcafe/networking/networks/models/test_network.py
Executable file
187
metatests/cloudcafe/networking/networks/models/test_network.py
Executable file
@ -0,0 +1,187 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from cloudcafe.networking.networks.common.models.request.network \
|
||||
import NetworkRequest
|
||||
from cloudcafe.networking.networks.common.models.response.network \
|
||||
import Network, Networks
|
||||
|
||||
NETWORK_TAG = Network.NETWORK
|
||||
NETWORKS_TAG = Networks.NETWORKS
|
||||
|
||||
|
||||
class CreateNetworkTest(unittest.TestCase):
|
||||
"""Test for the Network Create (POST) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
create_attrs = dict(
|
||||
name='test_name_value', admin_state_up='test_admin_state_up_value',
|
||||
shared='test_shared_value', tenant_id='test_tenant_id_value')
|
||||
cls.network_model = NetworkRequest(**create_attrs)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with all possible create attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"shared": "test_shared_value", '
|
||||
'"tenant_id": "test_tenant_id_value", "name": "test_name_value", '
|
||||
'"admin_state_up": "test_admin_state_up_value"}}}}').format(
|
||||
tag=NETWORK_TAG)
|
||||
request_body = self.network_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Network request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class UpdateNetworkTest(unittest.TestCase):
|
||||
"""Test for the Network Update (PUT) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
update_attrs = dict(
|
||||
name='test_name_value', admin_state_up='test_admin_state_up_value',
|
||||
shared='test_shared_value')
|
||||
cls.network_model = NetworkRequest(**update_attrs)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with all possible update attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"shared": "test_shared_value", '
|
||||
'"name": "test_name_value", '
|
||||
'"admin_state_up": "test_admin_state_up_value"}}}}').format(
|
||||
tag=NETWORK_TAG)
|
||||
request_body = self.network_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Network request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class ShowNetworkTest(unittest.TestCase):
|
||||
"""Test for the Network Show (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating network_model with currently supported attributes"""
|
||||
show_attrs = dict(
|
||||
status='ACTIVE', subnets=['54d6f61d-db07-451c-9ab3-b9609b6b6f0b',
|
||||
'79d6f61d-d007-51cd-9a33-b9609b6b6f0c'],
|
||||
name='net1', admin_state_up=True,
|
||||
tenant_id='9bacb3c5d39d41a79512987f338cf177', shared=False,
|
||||
id_='4e8e5957-649f-477b-9e5b-f1f75b21c03c', router_external=True)
|
||||
cls.expected_response = Network(**show_attrs)
|
||||
|
||||
def test_json_response(self):
|
||||
# Response data with extension attributes, if supported later on they
|
||||
# will need to be added to the setUp object model in this test class
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": {{
|
||||
"status": "ACTIVE",
|
||||
"subnets": [
|
||||
"54d6f61d-db07-451c-9ab3-b9609b6b6f0b",
|
||||
"79d6f61d-d007-51cd-9a33-b9609b6b6f0c"
|
||||
],
|
||||
"name": "net1",
|
||||
"admin_state_up": true,
|
||||
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
|
||||
"segments": [
|
||||
{{
|
||||
"provider:segmentation_id": 2,
|
||||
"provider:physical_network":
|
||||
"8bab8453-1bc9-45af-8c70-f83aa9b50453",
|
||||
"provider:network_type": "vlan"
|
||||
}},
|
||||
{{
|
||||
"provider:segmentation_id": null,
|
||||
"provider:physical_network":
|
||||
"8bab8453-1bc9-45af-8c70-f83aa9b50453",
|
||||
"provider:network_type": "stt"
|
||||
}}
|
||||
],
|
||||
"shared": false,
|
||||
"port_security_enabled": true,
|
||||
"id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c",
|
||||
"router:external": true
|
||||
}}
|
||||
}}""").format(tag=NETWORK_TAG)
|
||||
response_obj = Network()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
class ShowMultipleNetworksTest(unittest.TestCase):
|
||||
"""Test for the Networks List (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating network_model with currently supported attributes"""
|
||||
show_attrs_1 = dict(
|
||||
status='ACTIVE', subnets=['54d6f61d-db07-451c-9ab3-b9609b6b6f0b'],
|
||||
name='private-network', admin_state_up=True,
|
||||
tenant_id='4fd44f30292945e481c7b8a0c8908869', shared=True,
|
||||
id_='d32019d3-bc6e-4319-9c1d-6722fc136a22', router_external=True)
|
||||
show_attrs_2 = dict(
|
||||
status='ACTIVE', subnets=['08eae331-0402-425a-923c-34f7cfe39c1b'],
|
||||
name='private', admin_state_up=True,
|
||||
tenant_id='26a7980765d0414dbc1fc1f88cdb7e6e', shared=True,
|
||||
id_='db193ab3-96e3-4cb3-8fc5-05f4296d0324', router_external=True)
|
||||
net1 = Network(**show_attrs_1)
|
||||
net2 = Network(**show_attrs_2)
|
||||
cls.expected_response = [net1, net2]
|
||||
|
||||
def test_json_response(self):
|
||||
# Response data with extension attributes, if supported later on they
|
||||
# will need to be added to the setUp object model in this test class
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": [
|
||||
{{
|
||||
"status": "ACTIVE",
|
||||
"subnets": [
|
||||
"54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
|
||||
],
|
||||
"name": "private-network",
|
||||
"provider:physical_network": null,
|
||||
"admin_state_up": true,
|
||||
"tenant_id": "4fd44f30292945e481c7b8a0c8908869",
|
||||
"provider:network_type": "local",
|
||||
"router:external": true,
|
||||
"shared": true,
|
||||
"id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
||||
"provider:segmentation_id": null
|
||||
}},
|
||||
{{
|
||||
"status": "ACTIVE",
|
||||
"subnets": [
|
||||
"08eae331-0402-425a-923c-34f7cfe39c1b"
|
||||
],
|
||||
"name": "private",
|
||||
"provider:physical_network": null,
|
||||
"admin_state_up": true,
|
||||
"tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
|
||||
"provider:network_type": "local",
|
||||
"router:external": true,
|
||||
"shared": true,
|
||||
"id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
|
||||
"provider:segmentation_id": null
|
||||
}}
|
||||
]
|
||||
}}""").format(tag=NETWORKS_TAG)
|
||||
response_obj = Networks()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
268
metatests/cloudcafe/networking/networks/models/test_port.py
Executable file
268
metatests/cloudcafe/networking/networks/models/test_port.py
Executable file
@ -0,0 +1,268 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from cloudcafe.networking.networks.common.models.request.port \
|
||||
import PortRequest
|
||||
from cloudcafe.networking.networks.common.models.response.port \
|
||||
import Port, Ports
|
||||
|
||||
PORT_TAG = Port.PORT
|
||||
PORTS_TAG = Ports.PORTS
|
||||
|
||||
|
||||
class CreatePortTest(unittest.TestCase):
|
||||
"""Test for the Port Create (POST) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
create_attrs = dict(
|
||||
network_id='a87cc70a-3e15-4acf-8205-9b711a3531b7',
|
||||
name='private-port', admin_state_up=True)
|
||||
cls.subnet_model = PortRequest(**create_attrs)
|
||||
|
||||
# With all possible create attributes
|
||||
create_attrs_all = dict(
|
||||
network_id='test_net_id', name='port_name', admin_state_up=False,
|
||||
mac_address='fa:16:3e:c9:cb:f0', fixed_ips=[{'subnet_id':
|
||||
'subnet_id_value', 'ip_address': 'ip_address_value'},
|
||||
{'subnet_id2': 'subnet_id_value2', 'ip_address2':
|
||||
'ip_address_value2'}], device_id='test_device_id',
|
||||
device_owner='test_device_owner', tenant_id='test_tenant_id',
|
||||
security_groups=[[{'key1': 'value1', 'key2': 'value2'}, {'key1b':
|
||||
'value1b', 'key2b':'value2b'}]])
|
||||
cls.subnet_model_all = PortRequest(**create_attrs_all)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with create attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7"'
|
||||
', "name": "private-port", "admin_state_up": true}}}}').format(
|
||||
tag=PORT_TAG)
|
||||
|
||||
request_body = self.subnet_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Port request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
def test_json_request_all_attrs(self):
|
||||
"""JSON test with all create attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"name": "port_name", "admin_state_up": false, '
|
||||
'"network_id": "test_net_id", "tenant_id": "test_tenant_id", '
|
||||
'"device_owner": "test_device_owner", "mac_address": '
|
||||
'"fa:16:3e:c9:cb:f0", "fixed_ips": [{{"subnet_id": '
|
||||
'"subnet_id_value", "ip_address": "ip_address_value"}}, '
|
||||
'{{"subnet_id2": "subnet_id_value2", "ip_address2": '
|
||||
'"ip_address_value2"}}], "security_groups": [[{{"key2": "value2", '
|
||||
'"key1": "value1"}}, {{"key2b": "value2b", "key1b": "value1b"}}]],'
|
||||
' "device_id": "test_device_id"}}}}').format(tag=PORT_TAG)
|
||||
request_body = self.subnet_model_all._obj_to_json()
|
||||
msg = ('Unexpected JSON Subnet request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class UpdatePortTest(unittest.TestCase):
|
||||
"""Test for the Port Update (PUT) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
update_attrs = dict(
|
||||
name='port_update_name', admin_state_up=True,
|
||||
fixed_ips=[{'subnet_id': 'subnet_updated_id_value', 'ip_address':
|
||||
'ip_address_updated_value'}, {'subnet_id2':
|
||||
'subnet_id_updated_value2', 'ip_address2':
|
||||
'ip_address_updated_value2'}],
|
||||
device_id='updated_device_id', device_owner='updated_device_owner',
|
||||
security_groups=[[{'key1': 'updated_value1', 'key2':
|
||||
'updated_value2'}, {'key1b': 'updated_value1b', 'key2b':
|
||||
'updated_value2b'}]])
|
||||
cls.subnet_model = PortRequest(**update_attrs)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with all possible update attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"name": "port_update_name", "admin_state_up": true, '
|
||||
'"device_owner": "updated_device_owner", "fixed_ips": '
|
||||
'[{{"subnet_id": "subnet_updated_id_value", "ip_address": '
|
||||
'"ip_address_updated_value"}}, {{"subnet_id2": '
|
||||
'"subnet_id_updated_value2", "ip_address2": '
|
||||
'"ip_address_updated_value2"}}], "security_groups": '
|
||||
'[[{{"key2": "updated_value2", "key1": "updated_value1"}}, '
|
||||
'{{"key2b": "updated_value2b", "key1b": "updated_value1b"}}]], '
|
||||
'"device_id": "updated_device_id"}}}}').format(tag=PORT_TAG)
|
||||
request_body = self.subnet_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Subnet request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class ShowPortTest(unittest.TestCase):
|
||||
"""Test for the Port Show (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating port_model with with extension included attributes"""
|
||||
show_attrs = dict(
|
||||
status="ACTIVE", binding_host_id="devstack", name="response_name",
|
||||
allowed_address_pairs=[], admin_state_up=True,
|
||||
network_id="a87cc70a-3e15-4acf-8205-9b711a3531b7",
|
||||
tenant_id="7e02058126cc4950b75f9970368ba177",
|
||||
extra_dhcp_opts=[], binding_vif_details={"port_filter": True,
|
||||
"ovs_hybrid_plug": True}, binding_vif_type="ovs",
|
||||
device_owner="network:router_interface",
|
||||
mac_address="fa:16:3e:23:fd:d7", binding_profile={},
|
||||
binding_vnic_type="normal", fixed_ips=[{"subnet_id":
|
||||
"a0304c3a-4f08-4c43-88af-d796509c97d2", "ip_address": "10.0.0.1"}],
|
||||
id_="46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2", security_groups=[],
|
||||
device_id="5e3898d7-11be-483e-9732-b2f5eccd2b2e")
|
||||
cls.expected_response = Port(**show_attrs)
|
||||
|
||||
def test_json_response(self):
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": {{
|
||||
"status": "ACTIVE",
|
||||
"binding:host_id": "devstack",
|
||||
"name": "response_name",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": true,
|
||||
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
|
||||
"tenant_id": "7e02058126cc4950b75f9970368ba177",
|
||||
"extra_dhcp_opts": [],
|
||||
"binding:vif_details": {{
|
||||
"port_filter": true,
|
||||
"ovs_hybrid_plug": true
|
||||
}},
|
||||
"binding:vif_type": "ovs",
|
||||
"device_owner": "network:router_interface",
|
||||
"mac_address": "fa:16:3e:23:fd:d7",
|
||||
"binding:profile": {{}},
|
||||
"binding:vnic_type": "normal",
|
||||
"fixed_ips": [
|
||||
{{
|
||||
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
|
||||
"ip_address": "10.0.0.1"
|
||||
}}
|
||||
],
|
||||
"id": "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2",
|
||||
"security_groups": [],
|
||||
"device_id": "5e3898d7-11be-483e-9732-b2f5eccd2b2e"
|
||||
}}
|
||||
}}""").format(tag=PORT_TAG)
|
||||
response_obj = Port()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
class ShowMultiplePortTest(unittest.TestCase):
|
||||
"""Test for the Port List (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating port_model with currently supported attributes"""
|
||||
show_attrs_1 = dict(
|
||||
status='ACTIVE', name='', admin_state_up=True,
|
||||
network_id='70c1db1f-b701-45bd-96e0-a313ee3430b3', tenant_id='',
|
||||
mac_address='fa:16:3e:58:42:ed',
|
||||
device_owner='network:router_gateway',
|
||||
fixed_ips=[{u'subnet_id': u'008ba151-0b8c-4a67-98b5-0d2b87666062',
|
||||
u'ip_address': u'172.24.4.2'}],
|
||||
id_='d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b', security_groups=[],
|
||||
device_id='9ae135f4-b6e0-4dad-9e91-3c223e385824')
|
||||
show_attrs_2 = dict(
|
||||
status='ACTIVE', name='', admin_state_up=True,
|
||||
network_id='f27aa545-cbdd-4907-b0c6-c9e8b039dcc2',
|
||||
tenant_id='d397de8a63f341818f198abb0966f6f3',
|
||||
mac_address='fa:16:3e:bb:3c:e4',
|
||||
device_owner='network:router_interface', fixed_ips=[{u'subnet_id':
|
||||
u'288bf4a1-51ba-43b6-9d0a-520e9005db17', u'ip_address':
|
||||
u'10.0.0.1'}], id_='f71a6703-d6de-4be1-a91a-a570ede1d159',
|
||||
security_groups=[],
|
||||
device_id='9ae135f4-b6e0-4dad-9e91-3c223e385824',)
|
||||
sub1 = Port(**show_attrs_1)
|
||||
sub2 = Port(**show_attrs_2)
|
||||
cls.expected_response = [sub1, sub2]
|
||||
|
||||
def test_json_response(self):
|
||||
# Response data with extension attributes, if supported later on they
|
||||
# will need to be added to the setUp object model in this test class
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": [
|
||||
{{
|
||||
"status": "ACTIVE",
|
||||
"binding:host_id": "devstack",
|
||||
"name": "",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": true,
|
||||
"network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
|
||||
"tenant_id": "",
|
||||
"extra_dhcp_opts": [],
|
||||
"binding:vif_details": {{
|
||||
"port_filter": true,
|
||||
"ovs_hybrid_plug": true
|
||||
}},
|
||||
"binding:vif_type": "ovs",
|
||||
"device_owner": "network:router_gateway",
|
||||
"mac_address": "fa:16:3e:58:42:ed",
|
||||
"binding:profile": {{}},
|
||||
"binding:vnic_type": "normal",
|
||||
"fixed_ips": [
|
||||
{{
|
||||
"subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062",
|
||||
"ip_address": "172.24.4.2"
|
||||
}}
|
||||
],
|
||||
"id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
|
||||
"security_groups": [],
|
||||
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824"
|
||||
}},
|
||||
{{
|
||||
"status": "ACTIVE",
|
||||
"binding:host_id": "devstack",
|
||||
"name": "",
|
||||
"allowed_address_pairs": [],
|
||||
"admin_state_up": true,
|
||||
"network_id": "f27aa545-cbdd-4907-b0c6-c9e8b039dcc2",
|
||||
"tenant_id": "d397de8a63f341818f198abb0966f6f3",
|
||||
"extra_dhcp_opts": [],
|
||||
"binding:vif_details": {{
|
||||
"port_filter": true,
|
||||
"ovs_hybrid_plug": true
|
||||
}},
|
||||
"binding:vif_type": "ovs",
|
||||
"device_owner": "network:router_interface",
|
||||
"mac_address": "fa:16:3e:bb:3c:e4",
|
||||
"binding:profile": {{}},
|
||||
"binding:vnic_type": "normal",
|
||||
"fixed_ips": [
|
||||
{{
|
||||
"subnet_id": "288bf4a1-51ba-43b6-9d0a-520e9005db17",
|
||||
"ip_address": "10.0.0.1"
|
||||
}}
|
||||
],
|
||||
"id": "f71a6703-d6de-4be1-a91a-a570ede1d159",
|
||||
"security_groups": [],
|
||||
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824"
|
||||
}}
|
||||
]
|
||||
}}""").format(tag=PORTS_TAG)
|
||||
response_obj = Ports()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
223
metatests/cloudcafe/networking/networks/models/test_subnet.py
Executable file
223
metatests/cloudcafe/networking/networks/models/test_subnet.py
Executable file
@ -0,0 +1,223 @@
|
||||
"""
|
||||
Copyright 2014 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from cloudcafe.networking.networks.common.models.request.subnet \
|
||||
import SubnetRequest
|
||||
from cloudcafe.networking.networks.common.models.response.subnet \
|
||||
import Subnet, Subnets
|
||||
|
||||
SUBNET_TAG = Subnet.SUBNET
|
||||
SUBNETS_TAG = Subnets.SUBNETS
|
||||
|
||||
|
||||
class CreateSubnetTest(unittest.TestCase):
|
||||
"""Test for the Subnet Create (POST) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
create_attrs = dict(
|
||||
network_id='d32019d3-bc6e-4319-9c1d-6722fc136a22',
|
||||
ip_version=4, cidr='192.168.199.0/24')
|
||||
cls.subnet_model = SubnetRequest(**create_attrs)
|
||||
|
||||
# With all possible create attributes
|
||||
create_attrs_all = dict(
|
||||
name='test_subnet_name', tenant_id='test_tenant_id',
|
||||
network_id='test_network_id', ip_version=6, cidr='test_cidr',
|
||||
gateway_ip='test_gateway_ip', dns_nameservers=['test_dnsname1',
|
||||
'test_dnsname2', 'test_dnsname3'], allocation_pools=[{'start':
|
||||
'start_ip', 'end': 'end_ip'}, {'start2': 'start_ip2', 'end2':
|
||||
'end_ip2'}, {'start3': 'start_ip3', 'end3': 'end_ip3'}],
|
||||
host_routes=[{'route1_key': 'route1_value', 'route1_key2':
|
||||
'route1_value2'}, {'route2_key': 'route2_value', 'route2_key2':
|
||||
'route2_value2'}], enable_dhcp=True)
|
||||
cls.subnet_model_all = SubnetRequest(**create_attrs_all)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with create attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"'
|
||||
', "ip_version": 4, "cidr": "192.168.199.0/24"}}}}').format(
|
||||
tag=SUBNET_TAG)
|
||||
request_body = self.subnet_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Subnet request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
def test_json_request_all_attrs(self):
|
||||
"""JSON test with all create attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"name": "test_subnet_name", "enable_dhcp": true, '
|
||||
'"network_id": "test_network_id", "tenant_id": "test_tenant_id", '
|
||||
'"dns_nameservers": ["test_dnsname1", "test_dnsname2", '
|
||||
'"test_dnsname3"], "allocation_pools": [{{"start": "start_ip", '
|
||||
'"end": "end_ip"}}, {{"start2": "start_ip2", "end2": "end_ip2"}}, '
|
||||
'{{"start3": "start_ip3", "end3": "end_ip3"}}], "gateway_ip": '
|
||||
'"test_gateway_ip", "ip_version": 6, "host_routes": '
|
||||
'[{{"route1_key2": "route1_value2", "route1_key": "route1_value"}}'
|
||||
', {{"route2_key2": "route2_value2", "route2_key": "route2_value"'
|
||||
'}}], "cidr": "test_cidr"}}}}').format(tag=SUBNET_TAG)
|
||||
request_body = self.subnet_model_all._obj_to_json()
|
||||
msg = ('Unexpected JSON Subnet request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class UpdateSubnetTest(unittest.TestCase):
|
||||
"""Test for the Subnet Update (PUT) Model object requests"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
update_attrs = dict(
|
||||
name='test_subnet_name', gateway_ip='test_gateway_ip',
|
||||
dns_nameservers=['test_dnsname1', 'test_dnsname2',
|
||||
'test_dnsname3'], host_routes=[{'route1_key': 'route1_value',
|
||||
'route1_key2': 'route1_value2'}, {'route2_key': 'route2_value',
|
||||
'route2_key2': 'route2_value2'}], enable_dhcp=True)
|
||||
cls.subnet_model = SubnetRequest(**update_attrs)
|
||||
|
||||
def test_json_request(self):
|
||||
"""JSON test with all possible update attrs"""
|
||||
expected_json_output = (
|
||||
'{{"{tag}": {{"gateway_ip": "test_gateway_ip", "host_routes": '
|
||||
'[{{"route1_key2": "route1_value2", "route1_key": "route1_value"}}'
|
||||
', {{"route2_key2": "route2_value2", "route2_key": "route2_value"'
|
||||
'}}], "name": "test_subnet_name", "enable_dhcp": true, '
|
||||
'"dns_nameservers": ["test_dnsname1", "test_dnsname2", '
|
||||
'"test_dnsname3"]}}}}').format(tag=SUBNET_TAG)
|
||||
request_body = self.subnet_model._obj_to_json()
|
||||
msg = ('Unexpected JSON Subnet request serialization. Expected {0} '
|
||||
'instead of {1}'.format(expected_json_output, request_body))
|
||||
self.assertEqual(request_body, expected_json_output, msg)
|
||||
|
||||
|
||||
class ShowSubnetTest(unittest.TestCase):
|
||||
"""Test for the Subnet Show (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating subnet_model with currently supported attributes"""
|
||||
show_attrs = dict(
|
||||
name='my_subnet', enable_dhcp=True,
|
||||
network_id='d32019d3-bc6e-4319-9c1d-6722fc136a22',
|
||||
tenant_id='4fd44f30292945e481c7b8a0c8908869', dns_nameservers=[],
|
||||
allocation_pools=[{u'start': u'192.0.0.2', u'end':
|
||||
u'192.255.255.254'}], gateway_ip='192.0.0.1', ip_version=4,
|
||||
host_routes=[], cidr='192.0.0.0/8',
|
||||
id_='54d6f61d-db07-451c-9ab3-b9609b6b6f0b')
|
||||
cls.expected_response = Subnet(**show_attrs)
|
||||
|
||||
def test_json_response(self):
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": {{
|
||||
"name": "my_subnet",
|
||||
"enable_dhcp": true,
|
||||
"network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
||||
"tenant_id": "4fd44f30292945e481c7b8a0c8908869",
|
||||
"dns_nameservers": [],
|
||||
"allocation_pools": [
|
||||
{{
|
||||
"start": "192.0.0.2",
|
||||
"end": "192.255.255.254"
|
||||
}}
|
||||
],
|
||||
"host_routes": [],
|
||||
"ip_version": 4,
|
||||
"gateway_ip": "192.0.0.1",
|
||||
"cidr": "192.0.0.0/8",
|
||||
"id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
|
||||
}}
|
||||
}}""").format(tag=SUBNET_TAG)
|
||||
response_obj = Subnet()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
class ShowMultipleSubnetTest(unittest.TestCase):
|
||||
"""Test for the Subnet List (GET) Model object response"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Creating subnet_model with currently supported attributes"""
|
||||
show_attrs_1 = dict(
|
||||
name='private-subnet', enable_dhcp=True,
|
||||
network_id='db193ab3-96e3-4cb3-8fc5-05f4296d0324',
|
||||
tenant_id='26a7980765d0414dbc1fc1f88cdb7e6e', dns_nameservers=[],
|
||||
allocation_pools=[{u'start': u'10.0.0.2', u'end': u'10.0.0.254'}],
|
||||
gateway_ip='10.0.0.1', ip_version=4, host_routes=[],
|
||||
cidr='10.0.0.0/24', id_='08eae331-0402-425a-923c-34f7cfe39c1b')
|
||||
show_attrs_2 = dict(
|
||||
name='my_subnet', enable_dhcp=True,
|
||||
network_id='d32019d3-bc6e-4319-9c1d-6722fc136a22',
|
||||
tenant_id='4fd44f30292945e481c7b8a0c8908869', dns_nameservers=[],
|
||||
allocation_pools=[{u'start': u'192.0.0.2', u'end':
|
||||
u'192.255.255.254'}], gateway_ip='192.0.0.1', ip_version=4,
|
||||
host_routes=[], cidr='192.0.0.0/8',
|
||||
id_='54d6f61d-db07-451c-9ab3-b9609b6b6f0b')
|
||||
sub1 = Subnet(**show_attrs_1)
|
||||
sub2 = Subnet(**show_attrs_2)
|
||||
cls.expected_response = [sub1, sub2]
|
||||
|
||||
def test_json_response(self):
|
||||
# Response data with extension attributes, if supported later on they
|
||||
# will need to be added to the setUp object model in this test class
|
||||
api_json_resp = (
|
||||
"""{{
|
||||
"{tag}": [
|
||||
{{
|
||||
"name": "private-subnet",
|
||||
"enable_dhcp": true,
|
||||
"network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
|
||||
"tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
|
||||
"dns_nameservers": [],
|
||||
"allocation_pools": [
|
||||
{{
|
||||
"start": "10.0.0.2",
|
||||
"end": "10.0.0.254"
|
||||
}}
|
||||
],
|
||||
"host_routes": [],
|
||||
"ip_version": 4,
|
||||
"gateway_ip": "10.0.0.1",
|
||||
"cidr": "10.0.0.0/24",
|
||||
"id": "08eae331-0402-425a-923c-34f7cfe39c1b"
|
||||
}},
|
||||
{{
|
||||
"name": "my_subnet",
|
||||
"enable_dhcp": true,
|
||||
"network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
|
||||
"tenant_id": "4fd44f30292945e481c7b8a0c8908869",
|
||||
"dns_nameservers": [],
|
||||
"allocation_pools": [
|
||||
{{
|
||||
"start": "192.0.0.2",
|
||||
"end": "192.255.255.254"
|
||||
}}
|
||||
],
|
||||
"host_routes": [],
|
||||
"ip_version": 4,
|
||||
"gateway_ip": "192.0.0.1",
|
||||
"cidr": "192.0.0.0/8",
|
||||
"id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
|
||||
}}
|
||||
]
|
||||
}}""").format(tag=SUBNETS_TAG)
|
||||
response_obj = Subnets()._json_to_obj(api_json_resp)
|
||||
self.assertEqual(response_obj, self.expected_response,
|
||||
'JSON to Obj response different than expected')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user