Merge "Neutron Public IP Addresses extension"
This commit is contained in:
commit
544037998f
@ -398,10 +398,9 @@ class NetworkingBaseBehaviors(BaseBehavior):
|
||||
raise ResourceUpdateException(err_msg)
|
||||
return result
|
||||
|
||||
def _get_resource(self, resource, resource_id,
|
||||
resource_get_attempts=None, raise_exception=False,
|
||||
poll_interval=None, timeout=None,
|
||||
use_over_limit_retry=False):
|
||||
def _get_resource(self, resource, resource_id, resource_get_attempts=None,
|
||||
raise_exception=False, poll_interval=None, timeout=None,
|
||||
use_over_limit_retry=False, fn_kwargs=None):
|
||||
"""
|
||||
@summary: Shows and verifies a specified resource
|
||||
@param resource: type of resource for ex. network, subnet, port, etc.
|
||||
@ -409,6 +408,8 @@ class NetworkingBaseBehaviors(BaseBehavior):
|
||||
@type resource: resource instance with singular and plural forms
|
||||
@param resource_id: The UUID for the resource
|
||||
@type resource_id: str
|
||||
@param fn_kwargs: function client call params besides the ID
|
||||
@type fn_kwargs: dict
|
||||
@param resource_get_attempts: number of API retries
|
||||
@type resource_get_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the get
|
||||
@ -445,20 +446,20 @@ class NetworkingBaseBehaviors(BaseBehavior):
|
||||
resource_type=resource_type,
|
||||
resource_id=resource_id))
|
||||
|
||||
fn_kwargs = fn_kwargs or {}
|
||||
|
||||
# Adding the resource id to the function kwargs
|
||||
resource_id_name = '{0}_id'.format(resource_type)
|
||||
fn_kwargs[resource_id_name] = resource_id
|
||||
|
||||
# Method uses resource type in singular form (slicing the ending s)
|
||||
get_fn_name = 'get_{0}'.format(resource_type)
|
||||
resp = getattr(self.client, get_fn_name)(resource_id)
|
||||
resp = getattr(self.client, get_fn_name)(**fn_kwargs)
|
||||
|
||||
if use_over_limit_retry:
|
||||
entity_too_large_status_code = (getattr(self.response_codes,
|
||||
'REQUEST_ENTITY_TOO_LARGE'))
|
||||
if resp.status_code == entity_too_large_status_code:
|
||||
fn_kwargs = {}
|
||||
|
||||
# Adding the resource id to the function kwargs
|
||||
resource_id_name = '{0}_id'.format(resource_type)
|
||||
fn_kwargs[resource_id_name] = resource_id
|
||||
|
||||
resp = self.__over_limit_retry(
|
||||
resource_type=resource_type, timeout=timeout,
|
||||
poll_interval=poll_interval,
|
||||
|
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2015 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,270 @@
|
||||
"""
|
||||
Copyright 2015 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.networking.networks.common.behaviors \
|
||||
import NetworkingBaseBehaviors
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.constants \
|
||||
import IPAddressesResource, IPAddressesResponseCodes
|
||||
|
||||
|
||||
class IPAddressesBehaviors(NetworkingBaseBehaviors):
|
||||
|
||||
def __init__(self, ip_addresses_client, ip_addresses_config):
|
||||
super(IPAddressesBehaviors, self).__init__()
|
||||
self.config = ip_addresses_config
|
||||
self.client = ip_addresses_client
|
||||
self.response_codes = IPAddressesResponseCodes
|
||||
self.ip_address_resource = IPAddressesResource(
|
||||
IPAddressesResource.IP_ADDRESS)
|
||||
|
||||
def create_ip_address(self, network_id=None, version=None, device_ids=None,
|
||||
port_ids=None, resource_build_attempts=None,
|
||||
raise_exception=True, poll_interval=None):
|
||||
"""
|
||||
@summary: Creates an IP address on a specified network
|
||||
A list of device_ids may be optionally specified to create the IP
|
||||
address and added to their respective ports. A list of port_ids may
|
||||
be optionally specified to create the IP address and added to the
|
||||
specified ports. At least one of device_ids or port_ids must be
|
||||
specified.
|
||||
@param network_id: network UUID to get the IP address from
|
||||
@type network_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: int
|
||||
@param device_ids (optional): server UUIDs to add the IP address to
|
||||
their respective ports on the given network
|
||||
@type device_ids: list
|
||||
@param port_ids(optional): port UUIDs to add the IP address on the
|
||||
given network
|
||||
@type port_ids: list
|
||||
@param resource_build_attempts: number of API retries
|
||||
@type resource_build_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the
|
||||
Network was not created or to return None
|
||||
@type raise_exception: bool
|
||||
@param poll_interval: sleep time interval between API retries
|
||||
@type poll_interval: int
|
||||
@return: NetworkingResponse object with api response and failure list
|
||||
@rtype: common.behaviors.NetworkingResponse
|
||||
"""
|
||||
attrs_kwargs = dict(network_id=network_id, version=version,
|
||||
device_ids=device_ids, port_ids=port_ids)
|
||||
|
||||
result = self._create_resource(
|
||||
resource=self.ip_address_resource,
|
||||
resource_build_attempts=resource_build_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval,
|
||||
has_name=False, attrs_kwargs=attrs_kwargs)
|
||||
|
||||
return result
|
||||
|
||||
def update_ip_address(self, ip_address_id, port_ids=None,
|
||||
resource_update_attempts=None, raise_exception=False,
|
||||
poll_interval=None):
|
||||
"""
|
||||
@summary: Update an IP address, ex. to change ports.
|
||||
This will eliminate any previous associations to ports.
|
||||
@param ip_address_id: The UUID for the ip_address
|
||||
@type ip_address_id: str
|
||||
@param port_ids: port UUIDs to associate to the IP address
|
||||
@param resource_update_attempts: number of API retries
|
||||
@type resource_update_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the
|
||||
Network was not updated or to return None
|
||||
@type raise_exception: bool
|
||||
@param poll_interval: sleep time interval between API retries
|
||||
@type poll_interval: int
|
||||
@return: NetworkingResponse object with api response and failure list
|
||||
@rtype: common.behaviors.NetworkingResponse
|
||||
"""
|
||||
attrs_kwargs = dict(port_ids=port_ids)
|
||||
|
||||
result = self._update_resource(
|
||||
resource=self.ip_address_resource, resource_id=ip_address_id,
|
||||
resource_update_attempts=resource_update_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval,
|
||||
attrs_kwargs=attrs_kwargs)
|
||||
|
||||
return result
|
||||
|
||||
def get_ip_address(self, ip_address_id, resource_get_attempts=None,
|
||||
raise_exception=False, poll_interval=None):
|
||||
"""
|
||||
@summary: Shows a specific IP address
|
||||
@param ip_address_id: The UUID for the ip_address
|
||||
@type ip_address_id: str
|
||||
@param resource_get_attempts: number of API retries
|
||||
@type resource_get_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the get
|
||||
Network was not as expected or to return None
|
||||
@type raise_exception: bool
|
||||
@param poll_interval: sleep time interval between API retries
|
||||
@type poll_interval: int
|
||||
@return: NetworkingResponse object with api response and failure list
|
||||
@rtype: common.behaviors.NetworkingResponse
|
||||
"""
|
||||
result = self._get_resource(
|
||||
resource=self.ip_address_resource, resource_id=ip_address_id,
|
||||
resource_get_attempts=resource_get_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval)
|
||||
|
||||
return result
|
||||
|
||||
def list_ip_addresses(self, ip_address_id=None, network_id=None,
|
||||
address=None, subnet_id=None, port_ids=None,
|
||||
tenant_id=None, version=None, type_=None,
|
||||
port_id=None, device_id=None, service=None,
|
||||
limit=None, marker=None, page_reverse=None,
|
||||
resource_list_attempts=None, raise_exception=False,
|
||||
poll_interval=None):
|
||||
"""
|
||||
@summary: Lists IP addresses, filtered by params if given
|
||||
@param ip_address_id: shared IP UUID
|
||||
@type ip_address_id: str
|
||||
@param network_id: network UUID where the IP address belongs to
|
||||
@type network_id: str
|
||||
@param address: IP address
|
||||
@type address: str
|
||||
@param subnet_id: subnet UUID where the IP address belongs to
|
||||
@type subnet_id: str
|
||||
@param port_ids: IP addresses port UUIDs
|
||||
@type port_ids: list
|
||||
@param tenant_id: tenant ID of the shared IP user
|
||||
@type tenant_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: int
|
||||
@param type_: IP address type, for ex. fixed
|
||||
@type type_: str
|
||||
@param port_id: IP address by their port ID
|
||||
@type port_id: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param device_id: IP address by their port device ID
|
||||
@type device_id: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param service: IP address by their port service, for ex. compute
|
||||
@type service: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param limit: page size
|
||||
@type limit: int
|
||||
@param marker: Id of the last item of the previous page
|
||||
@type marker: string
|
||||
@param page_reverse: direction of the page
|
||||
@type page_reverse: bool
|
||||
@param resource_list_attempts: number of API retries
|
||||
@type resource_list_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the list
|
||||
Network was not as expected or to return None
|
||||
@type raise_exception: bool
|
||||
@param poll_interval: sleep time interval between API retries
|
||||
@type poll_interval: int
|
||||
@return: NetworkingResponse object with api response and failure list
|
||||
@rtype: common.behaviors.NetworkingResponse
|
||||
"""
|
||||
params_kwargs = dict(
|
||||
ip_address_id=ip_address_id, network_id=network_id,
|
||||
address=address, subnet_id=subnet_id, port_ids=port_ids,
|
||||
tenant_id=tenant_id, version=version, type_=type_, port_id=port_id,
|
||||
device_id=device_id, service=service, limit=limit, marker=marker,
|
||||
page_reverse=page_reverse)
|
||||
|
||||
result = self._list_resources(
|
||||
resource=self.ip_address_resource,
|
||||
resource_list_attempts=resource_list_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval,
|
||||
params_kwargs=params_kwargs)
|
||||
|
||||
return result
|
||||
|
||||
def delete_ip_address(self, ip_address_id, resource_delete_attempts=None,
|
||||
raise_exception=False, poll_interval=None):
|
||||
"""
|
||||
@summary: Deletes a specified IP address
|
||||
@param ip_address_id: The UUID for the ip_address to delete
|
||||
@type ip_address_id: str
|
||||
@param resource_delete_attempts: number of API retries
|
||||
@type resource_delete_attempts: int
|
||||
@param raise_exception: flag to raise an exception if the deleted
|
||||
Network was not as expected or to return None
|
||||
@type raise_exception: bool
|
||||
@param poll_interval: sleep time interval between API retries
|
||||
@type poll_interval: int
|
||||
@return: NetworkingResponse object with api response and failure list
|
||||
@rtype: common.behaviors.NetworkingResponse
|
||||
"""
|
||||
result = self._delete_resource(
|
||||
resource=self.ip_address_resource,
|
||||
resource_id=ip_address_id,
|
||||
resource_delete_attempts=resource_delete_attempts,
|
||||
raise_exception=raise_exception, poll_interval=poll_interval)
|
||||
|
||||
return result
|
||||
|
||||
def delete_ip_addresses(self, ip_address_list=None, tenant_id=None,
|
||||
skip_delete=None):
|
||||
"""
|
||||
@summary: deletes multiple IP Addresses
|
||||
@param ip_address_list: list of IP Address UUIDs
|
||||
@type ip_address_list: list(str)
|
||||
@param tenant_id: IP Address tenant ID to filter by
|
||||
@type tenant_id: string (ignored if ip_address_list given)
|
||||
@param skip_delete: list of IP Address UUIDs that should skip deletion
|
||||
@type skip_delete: list
|
||||
@return: failed deletes list with IP Address IDs and failures
|
||||
@rtype: list(dict)
|
||||
"""
|
||||
result = self._delete_resources(
|
||||
resource=self.ip_address_resource,
|
||||
resource_list=ip_address_list,
|
||||
tenant_id=tenant_id, skip_delete=skip_delete)
|
||||
|
||||
return result
|
||||
|
||||
def clean_ip_address(self, ip_address_id, timeout=None,
|
||||
poll_interval=None):
|
||||
"""
|
||||
@summary: deletes an IP Address within a time out
|
||||
@param ip_address_id: The UUID for the ip_address to delete
|
||||
@type ip_address_id: str
|
||||
@param timeout: seconds to wait for the IP Address to be deleted
|
||||
@type timeout: int
|
||||
@param poll_interval: sleep time interval between API delete/get calls
|
||||
@type poll_interval: int
|
||||
@return: None if delete was successful or the undeleted ip_address_id
|
||||
@rtype: None or string
|
||||
"""
|
||||
result = self._clean_resource(
|
||||
resource=self.ip_address_resource,
|
||||
resource_id=ip_address_id,
|
||||
timeout=timeout, poll_interval=poll_interval)
|
||||
|
||||
return result
|
||||
|
||||
def clean_ip_addresses(self, ip_address_list, timeout=None,
|
||||
poll_interval=None):
|
||||
"""
|
||||
@summary: deletes each IP Address from a list calling clean_ip_address
|
||||
@param ip_address_list: list of IP Address UUIDs
|
||||
@type ip_address_list: list(str)
|
||||
@param timeout: seconds to wait for the IP Address to be deleted
|
||||
@type timeout: int
|
||||
@param poll_interval: sleep time interval between API delete/get calls
|
||||
@type poll_interval: int
|
||||
@return: list of undeleted IP Address UUIDs
|
||||
@rtype: list(str)
|
||||
"""
|
||||
result = self._clean_resources(
|
||||
resource=self.ip_address_resource,
|
||||
resource_list=ip_address_list,
|
||||
timeout=timeout, poll_interval=poll_interval)
|
||||
|
||||
return result
|
@ -0,0 +1,193 @@
|
||||
"""
|
||||
Copyright 2015 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.extensions.ip_addresses_api.models.request\
|
||||
import IPAddressRequest
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.models.response\
|
||||
import IPAddress, IPAddresses
|
||||
|
||||
|
||||
class IPAddressesClient(AutoMarshallingHTTPClient):
|
||||
|
||||
def __init__(self, url, auth_token, serialize_format=None,
|
||||
deserialize_format=None, tenant_id=None):
|
||||
"""
|
||||
@summary: Rackspace Neutron API IP Addresses extension client
|
||||
@param url: Base URL for the networks 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
|
||||
@param tenant_id: optional tenant id to be included in the
|
||||
header if given
|
||||
@type tenant_id: string
|
||||
"""
|
||||
super(IPAddressesClient, 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
|
||||
self.ip_addresses_url = '{url}/ip_addresses'.format(url=self.url)
|
||||
|
||||
def create_ip_address(self, network_id=None, version=None, device_ids=None,
|
||||
port_ids=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Creates an IP address on a specified network
|
||||
A list of device_ids may be optionally specified to create the IP
|
||||
address and added to their respective ports. A list of port_ids may
|
||||
be optionally specified to create the IP address and added to the
|
||||
specified ports. At least one of device_ids or port_ids must be
|
||||
specified.
|
||||
@param network_id: network UUID to get the IP address from
|
||||
@type network_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: int
|
||||
@param device_ids (optional): server UUIDs to add the IP address to
|
||||
their respective ports on the given network
|
||||
@type device_ids: list
|
||||
@param port_ids(optional): port UUIDs to add the IP address on the
|
||||
given network
|
||||
@type port_ids: list
|
||||
@return: IP address create response
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
url = self.ip_addresses_url
|
||||
request = IPAddressRequest(network_id=network_id, version=version,
|
||||
device_ids=device_ids, port_ids=port_ids)
|
||||
|
||||
resp = self.request('POST', url,
|
||||
response_entity_type=IPAddress,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def update_ip_address(self, ip_address_id, port_ids=None,
|
||||
requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Update an IP address, ex. to change ports.
|
||||
This will eliminate any previous associations to ports.
|
||||
@param ip_address_id: The UUID for the ip_address
|
||||
@type ip_address_id: str
|
||||
@param port_ids: port UUIDs to associate to the IP address
|
||||
@return: IP address update response
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
url = '{base_url}/{ip_address_id}'.format(
|
||||
base_url=self.ip_addresses_url, ip_address_id=ip_address_id)
|
||||
request = IPAddressRequest(port_ids=port_ids)
|
||||
|
||||
resp = self.request('PUT', url,
|
||||
response_entity_type=IPAddress,
|
||||
request_entity=request,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def get_ip_address(self, ip_address_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Shows a specific IP address
|
||||
@param ip_address_id: The UUID for the ip_address
|
||||
@type ip_address_id: str
|
||||
@return: IP address get response
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
url = '{base_url}/{ip_address_id}'.format(
|
||||
base_url=self.ip_addresses_url, ip_address_id=ip_address_id)
|
||||
resp = self.request('GET', url,
|
||||
response_entity_type=IPAddress,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def list_ip_addresses(self, ip_address_id=None, network_id=None,
|
||||
address=None, subnet_id=None, port_ids=None,
|
||||
tenant_id=None, version=None,
|
||||
type_=None, port_id=None, device_id=None,
|
||||
service=None, limit=None, marker=None,
|
||||
page_reverse=None, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Lists IP addresses, filtered by params if given
|
||||
@param ip_address_id: shared IP UUID
|
||||
@type ip_address_id: str
|
||||
@param network_id: network UUID where the IP address belongs to
|
||||
@type network_id: str
|
||||
@param address: IP address
|
||||
@type address: str
|
||||
@param subnet_id: subnet UUID where the IP address belongs to
|
||||
@type subnet_id: str
|
||||
@param port_ids: IP addresses port UUIDs
|
||||
@type port_ids: list
|
||||
@param tenant_id: tenant ID of the shared IP user
|
||||
@type tenant_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: int
|
||||
@param type_: IP address type, for ex. fixed
|
||||
@type type_: str
|
||||
@param port_id: IP address by their port ID
|
||||
@type port_id: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param device_id: IP address by their port device ID
|
||||
@type device_id: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param service: IP address by their port service, for ex. compute
|
||||
@type service: str (/ip_addresses/{id}/ports child resource attr)
|
||||
@param limit: page size
|
||||
@type limit: int
|
||||
@param marker: Id of the last item of the previous page
|
||||
@type marker: string
|
||||
@param page_reverse: direction of the page
|
||||
@type page_reverse: bool
|
||||
@return: IP address list response
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
|
||||
params = {'id': ip_address_id, 'network_id': network_id,
|
||||
'address': address, 'subnet_id': subnet_id,
|
||||
'port_ids[]': port_ids, 'tenant_id': tenant_id,
|
||||
'version': version, 'type': type_, 'port_id': port_id,
|
||||
'device_id': device_id, 'service': service,
|
||||
'limit': limit, 'marker': marker,
|
||||
'page_reverse': page_reverse}
|
||||
|
||||
url = self.ip_addresses_url
|
||||
resp = self.request('GET', url, params=params,
|
||||
response_entity_type=IPAddresses,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
||||
|
||||
def delete_ip_address(self, ip_address_id, requestslib_kwargs=None):
|
||||
"""
|
||||
@summary: Deletes a specified IP address
|
||||
@param ip_address_id: The UUID for the ip_address to delete
|
||||
@type ip_address_id: str
|
||||
@return: IP address delete response
|
||||
@rtype: Requests.response
|
||||
"""
|
||||
url = '{base_url}/{ip_address_id}'.format(
|
||||
base_url=self.ip_addresses_url, ip_address_id=ip_address_id)
|
||||
resp = self.request('DELETE', url,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
return resp
|
@ -0,0 +1,38 @@
|
||||
"""
|
||||
Copyright 2015 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.networking.networks.composites import _NetworkingAuthComposite
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.behaviors \
|
||||
import IPAddressesBehaviors
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.client \
|
||||
import IPAddressesClient
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.config \
|
||||
import IPAddressesConfig
|
||||
|
||||
|
||||
class IPAddressesComposite(object):
|
||||
networking_auth_composite = _NetworkingAuthComposite
|
||||
|
||||
def __init__(self):
|
||||
auth_composite = self.networking_auth_composite()
|
||||
self.url = auth_composite.networking_url
|
||||
self.user = auth_composite._auth_user_config
|
||||
self.config = IPAddressesConfig()
|
||||
self.client = IPAddressesClient(**auth_composite.client_args)
|
||||
|
||||
self.behaviors = IPAddressesBehaviors(
|
||||
ip_addresses_client=self.client,
|
||||
ip_addresses_config=self.config)
|
@ -0,0 +1,23 @@
|
||||
"""
|
||||
Copyright 2015 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.networking.networks.common.config import NetworkingBaseConfig
|
||||
|
||||
|
||||
class IPAddressesConfig(NetworkingBaseConfig):
|
||||
"""IP Addresses configuration parameters"""
|
||||
|
||||
SECTION_NAME = 'ip_addresses'
|
@ -0,0 +1,44 @@
|
||||
"""
|
||||
Copyright 2015 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.networking.networks.common.constants \
|
||||
import NeutronResource, NeutronResponseCodes, NeutronErrorTypes
|
||||
|
||||
|
||||
class IPAddressesResource(NeutronResource):
|
||||
"""IP addresses resource types"""
|
||||
|
||||
# Resources to be used by the behavior
|
||||
IP_ADDRESS = 'ip_address'
|
||||
IP_ADDRESSES = 'ip_addresses'
|
||||
|
||||
PLURALS = NeutronResource.PLURALS.update(
|
||||
{IP_ADDRESS: IP_ADDRESSES})
|
||||
|
||||
|
||||
class IPAddressesResponseCodes(NeutronResponseCodes):
|
||||
"""HTTP IP Address API Response codes"""
|
||||
|
||||
LIST_IP_ADDRESSES = 200
|
||||
GET_IP_ADDRESS = 200
|
||||
CREATE_IP_ADDRESS = 201
|
||||
UPDATE_IP_ADDRESS = 200
|
||||
DELETE_IP_ADDRESS = 204
|
||||
|
||||
|
||||
class IPAddressesErrorTypes(NeutronErrorTypes):
|
||||
"""IP Address Error Types"""
|
||||
|
||||
IP_ADDRESS_NOT_FOUND = 'IPAddressNotFound'
|
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2015 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 2015 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
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class IPAddressRequest(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: IP Address model request object for the Shared IPs Rackspace
|
||||
Networking v2.0 API extension for creating (POST) and updating (PUT)
|
||||
IP addresses.
|
||||
@param network_id: network UUID to get the IP address from
|
||||
@type network_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: int
|
||||
@param device_ids (optional): server UUIDs to add the IP address to their
|
||||
respective ports on the given network
|
||||
@type device_ids: list
|
||||
@param port_ids(optional): port UUIDs to add the IP address on the given
|
||||
network
|
||||
@type port_ids: list
|
||||
"""
|
||||
|
||||
def __init__(self, network_id=None, version=None, device_ids=None,
|
||||
port_ids=None):
|
||||
super(IPAddressRequest, self).__init__()
|
||||
self.network_id = network_id
|
||||
self.version = version
|
||||
self.device_ids = device_ids
|
||||
self.port_ids = port_ids
|
||||
|
||||
def _obj_to_json(self):
|
||||
|
||||
body = {
|
||||
'network_id': self.network_id,
|
||||
'version': self.version,
|
||||
'device_ids': self.device_ids,
|
||||
'port_ids': self.port_ids
|
||||
}
|
||||
|
||||
# Removing optional params not given
|
||||
body = self._remove_empty_values(body)
|
||||
main_body = {'ip_address': body}
|
||||
return json.dumps(main_body)
|
@ -0,0 +1,110 @@
|
||||
"""
|
||||
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
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingListModel, \
|
||||
AutoMarshallingModel
|
||||
|
||||
|
||||
class IPAddress(AutoMarshallingModel):
|
||||
"""
|
||||
@summary: IP Address model response object for the Shared IPs Rackspace
|
||||
Networking v2.0 API extension.
|
||||
@param id_: shared IP UUID
|
||||
@type id_: str
|
||||
@param network_id: network UUID where the IP address belongs to
|
||||
@type network_id: str
|
||||
@param address: IP address
|
||||
@type address: str
|
||||
@param port_ids: list of port UUIDs where the shared IP will be associated
|
||||
@type port_ids: list(str)
|
||||
@param subnet_id: subnet UUID where the IP address belongs to
|
||||
@type subnet_id: str
|
||||
@param tenant_id: tenant ID of the shared IP user
|
||||
@type tenant_id: str
|
||||
@param version: IP address version 4 or 6
|
||||
@type version: str
|
||||
@param type_: IP address type, for ex. fixed
|
||||
@type type_: str
|
||||
"""
|
||||
|
||||
IP_ADDRESS = 'ip_address'
|
||||
|
||||
def __init__(self, id_=None, network_id=None, address=None, port_ids=None,
|
||||
subnet_id=None, tenant_id=None, version=None, type_=None,
|
||||
**kwargs):
|
||||
|
||||
# kwargs is to be used for checking unexpected attrs
|
||||
super(IPAddress, self).__init__()
|
||||
self.id = id_
|
||||
self.network_id = network_id
|
||||
self.address = address
|
||||
self.port_ids = port_ids
|
||||
self.subnet_id = subnet_id
|
||||
self.tenant_id = tenant_id
|
||||
self.version = version
|
||||
self.type = type_
|
||||
self.kwargs = kwargs
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""
|
||||
@summary: Return IP address object from a JSON serialized string
|
||||
"""
|
||||
|
||||
ret = None
|
||||
json_dict = json.loads(serialized_str)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'type', 'type_', recursion=True)
|
||||
|
||||
if cls.IP_ADDRESS in json_dict:
|
||||
ip_address_dict = json_dict.get(cls.IP_ADDRESS)
|
||||
ret = IPAddress(**ip_address_dict)
|
||||
return ret
|
||||
|
||||
|
||||
class IPAddresses(AutoMarshallingListModel):
|
||||
|
||||
IP_ADDRESSES = 'ip_addresses'
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
"""
|
||||
@summary: Return a list of IP address objects from a JSON
|
||||
serialized string
|
||||
"""
|
||||
ret = cls()
|
||||
json_dict = json.loads(serialized_str)
|
||||
|
||||
# Replacing attribute response names if they are Python reserved words
|
||||
# with a trailing underscore, for ex. id for id_
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'id', 'id_', recursion=True)
|
||||
json_dict = cls._replace_dict_key(
|
||||
json_dict, 'type', 'type_', recursion=True)
|
||||
|
||||
if cls.IP_ADDRESSES in json_dict:
|
||||
ip_addresses = json_dict.get(cls.IP_ADDRESSES)
|
||||
for ip_address in ip_addresses:
|
||||
result = IPAddress(**ip_address)
|
||||
ret.append(result)
|
||||
return ret
|
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Copyright 2015 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 2015 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,157 @@
|
||||
"""
|
||||
Copyright 2015 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.extensions.ip_addresses_api.models.request\
|
||||
import IPAddressRequest
|
||||
from cloudcafe.networking.networks.extensions.ip_addresses_api.models.response\
|
||||
import IPAddress, IPAddresses
|
||||
|
||||
|
||||
ERROR_MSG_REQ = ('JSON unexpected IP Address request serialization\n'
|
||||
'Actual Serialization:\n{request}\n'
|
||||
'Expected Serialization:\n{expected}\n')
|
||||
ERROR_MSG_RESP = ('JSON to Obj response different than expected\n'
|
||||
'Actual Response:\n{response}\n'
|
||||
'Expected Response:\n{expected}\n')
|
||||
|
||||
|
||||
class CreateIPAddressTest(unittest.TestCase):
|
||||
"""
|
||||
@summary: Test for the IP Address POST model object request
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
create_attrs = dict(
|
||||
network_id='testnet_id', version='4',
|
||||
device_ids=['dev1, dev2, dev3'],
|
||||
port_ids=['port1', 'port2', 'port3'])
|
||||
cls.ip_address_model = IPAddressRequest(**create_attrs)
|
||||
cls.expected_json_output = (
|
||||
'{"ip_address": {"network_id": "testnet_id", "port_ids": '
|
||||
'["port1", "port2", "port3"], "version": "4", "device_ids": '
|
||||
'["dev1, dev2, dev3"]}}')
|
||||
|
||||
def test_json_request(self):
|
||||
request_body = self.ip_address_model._obj_to_json()
|
||||
msg = ERROR_MSG_REQ.format(request=request_body,
|
||||
expected=self.expected_json_output)
|
||||
self.assertEqual(request_body, self.expected_json_output, msg)
|
||||
|
||||
|
||||
class GetIPAddressTest(unittest.TestCase):
|
||||
"""
|
||||
@sumary: Test for the IP Address GET model object response
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Setting the expected response object
|
||||
get_attrs = dict(
|
||||
id_='4cacd68e-d7aa-4ff2-96f4-5c6f57dba737',
|
||||
network_id='fda61e0b-a410-49e8-ad3a-64c595618c7e',
|
||||
address='192.168.10.1',
|
||||
port_ids=['6200d533-a42b-4c04-82a1-cc14dbdbf2de'],
|
||||
subnet_id='f11687e8-ef0d-4207-8e22-c60e737e473b',
|
||||
tenant_id='2345678',
|
||||
version='4',
|
||||
type_='fixed')
|
||||
cls.expected_response = IPAddress(**get_attrs)
|
||||
|
||||
# Data simulating the JSON API response
|
||||
cls.api_json_resp = ("""
|
||||
{
|
||||
"ip_address": {
|
||||
"id": "4cacd68e-d7aa-4ff2-96f4-5c6f57dba737",
|
||||
"network_id": "fda61e0b-a410-49e8-ad3a-64c595618c7e",
|
||||
"address": "192.168.10.1",
|
||||
"port_ids": ["6200d533-a42b-4c04-82a1-cc14dbdbf2de"],
|
||||
"subnet_id": "f11687e8-ef0d-4207-8e22-c60e737e473b",
|
||||
"tenant_id": "2345678",
|
||||
"version": "4",
|
||||
"type": "fixed"}
|
||||
}
|
||||
""")
|
||||
|
||||
def test_json_response(self):
|
||||
response_obj = IPAddress()._json_to_obj(self.api_json_resp)
|
||||
msg = ERROR_MSG_RESP.format(response=response_obj,
|
||||
expected=self.expected_response)
|
||||
self.assertEqual(response_obj, self.expected_response, msg)
|
||||
|
||||
|
||||
class ListIPAddressesTest(unittest.TestCase):
|
||||
"""
|
||||
@sumary: Test for the IP Addresses (List) GET model object response
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# Setting the expected response object
|
||||
get_attrs1 = dict(
|
||||
id_='address',
|
||||
network_id='fda61e0b-a410-49e8-ad3a-64c595618c7e',
|
||||
address='192.168.10.1',
|
||||
port_ids=['6200d533-a42b-4c04-82a1-cc14dbdbf2de'],
|
||||
subnet_id='f11687e8-ef0d-4207-8e22-c60e737e473b',
|
||||
tenant_id='2345678',
|
||||
version='4',
|
||||
type_='fixed')
|
||||
get_attrs2 = dict(
|
||||
id_='address2',
|
||||
network_id='a_network_id',
|
||||
address='192.168.10.7',
|
||||
port_ids=['port_id1', 'port_id2', 'port_id3'],
|
||||
subnet_id='a_subnet_id',
|
||||
tenant_id='a_tenant_id',
|
||||
version='6',
|
||||
type_='floating')
|
||||
ip_address1 = IPAddress(**get_attrs1)
|
||||
ip_address2 = IPAddress(**get_attrs2)
|
||||
cls.expected_response = [ip_address1, ip_address2]
|
||||
|
||||
# Data simulating the JSON API response
|
||||
cls.api_json_resp = ("""
|
||||
{
|
||||
"ip_addresses": [{
|
||||
"id": "address",
|
||||
"network_id": "fda61e0b-a410-49e8-ad3a-64c595618c7e",
|
||||
"address": "192.168.10.1",
|
||||
"port_ids": ["6200d533-a42b-4c04-82a1-cc14dbdbf2de"],
|
||||
"subnet_id": "f11687e8-ef0d-4207-8e22-c60e737e473b",
|
||||
"tenant_id": "2345678",
|
||||
"version": "4",
|
||||
"type": "fixed"},
|
||||
{
|
||||
"id": "address2",
|
||||
"network_id": "a_network_id",
|
||||
"address": "192.168.10.7",
|
||||
"port_ids": ["port_id1", "port_id2", "port_id3"],
|
||||
"subnet_id": "a_subnet_id",
|
||||
"tenant_id": "a_tenant_id",
|
||||
"version": "6",
|
||||
"type": "floating"}]
|
||||
}
|
||||
""")
|
||||
|
||||
def test_json_response(self):
|
||||
response_obj = IPAddresses()._json_to_obj(self.api_json_resp)
|
||||
msg = ERROR_MSG_RESP.format(response=response_obj,
|
||||
expected=self.expected_response)
|
||||
self.assertEqual(response_obj, self.expected_response, msg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user