Merge "Included OCCI IPReservation support"

This commit is contained in:
Jenkins 2017-04-03 07:07:34 +00:00 committed by Gerrit Code Review
commit 2e6c6b22c0
21 changed files with 1014 additions and 152 deletions

View File

@ -291,6 +291,60 @@ It deletes a network::
It returns a 204 empty response. It returns a 204 empty response.
IPReservation
**************
OOI allows to manage public IPs by using IPReservation resources. This resource is a special network to provide public access.
It allocates and releases IPs from public network pools.
List IPReservations
-------------------
It list IPReservation resources::
curl -H "X-Auth-token: "$OS_TOKEN http://127.0.0.1:8787/occi1.1/ipreservation
It returns a HTTP 200 with output::
X-OCCI-Location: http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526
Show IPReservation
------------------
It shows the IPReservation details::
curl -H "X-Auth-token: "$OS_TOKEN http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526
It returns a HTTP 200 with output::
Category: ipreservation; scheme="http://schemas.ogf.org/occi/infrastructure#"; class="kind"; title="IPReservation"; rel="http://schemas.ogf.org/occi/infrastructure#network"; location="http://127.0.0.1:8787/occi1.1/ipreservation/"
X-OCCI-Attribute: occi.core.title="external-net"
X-OCCI-Attribute: occi.core.summary=[]
X-OCCI-Attribute: occi.core.id="3318c3af-ce57-41ef-a9c1-9a5ecfbe0526"
X-OCCI-Attribute: occi.ipreservation.address="193.136.75.90"
X-OCCI-Attribute: occi.ipreservation.used="true"
Link: <http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526?action=up>; rel="http://schemas.ogf.org/occi/infrastructure/network/action#up"
Link: <http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526?action=down>; rel="http://schemas.ogf.org/occi/infrastructure/network/action#down"
Create IPReservation
--------------------
It creates a IPReservation resource::
curl -X POST http://127.0.0.1:8787/occi1.1/ipreservation -H 'X-Auth-token: '$OS_TOKEN \
-H 'Category: ipreshemas.ogf.org/occi/infrastructure#"; class="kind",' \
'external-net; scheme="http://schemas.openstack.org/network/floatingippool#"; class="mixin"' \
-H 'Content-Type: text/occi'
It returns a HTTP 200 with output::
X-OCCI-Location: http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526
Delete IPReservation
--------------------
It deletes IPReservation resources::
curl -X DELETE -H "X-Auth-token: "$OS_TOKEN http://127.0.0.1:8787/occi1.1/ipreservation/3318c3af-ce57-41ef-a9c1-9a5ecfbe0526
It returns a 204 empty response.
Network Link Network Link
************ ************

View File

@ -22,6 +22,7 @@ from ooi import exception
from ooi.occi.core import collection from ooi.occi.core import collection
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import contextualization from ooi.occi.infrastructure import contextualization
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import storage from ooi.occi.infrastructure import storage
from ooi.occi.infrastructure import storage_link from ooi.occi.infrastructure import storage_link
@ -32,8 +33,13 @@ from ooi.openstack import network as os_network
from ooi.openstack import templates from ooi.openstack import templates
def _create_network_link(addr, comp, net_id): def _create_network_link(addr, comp, net_id, type_ip):
net = network.NetworkResource(title="network", id=net_id) if type_ip == "floating":
net = ip_reservation.IPReservation(title="network",
address=None,
id=net_id)
else:
net = network.NetworkResource(title="network", id=net_id)
return os_network.OSNetworkInterface(comp, net, return os_network.OSNetworkInterface(comp, net,
addr["OS-EXT-IPS-MAC:mac_addr"], addr["OS-EXT-IPS-MAC:mac_addr"],
addr["addr"]) addr["addr"])
@ -278,7 +284,9 @@ class Controller(ooi.api.base.Controller):
for addr in addr_set: for addr in addr_set:
# TODO(jorgesece): add pool information # TODO(jorgesece): add pool information
if addr["OS-EXT-IPS:type"] == "floating": if addr["OS-EXT-IPS:type"] == "floating":
net_id = helpers.PUBLIC_NETWORK net_id = self.os_helper.get_floatingip_id(
req, addr['addr']
)
else: else:
try: try:
net_id = self.os_helper.get_network_id( net_id = self.os_helper.get_network_id(
@ -286,7 +294,9 @@ class Controller(ooi.api.base.Controller):
) )
except webob.exc.HTTPNotFound: except webob.exc.HTTPNotFound:
net_id = "FIXED" net_id = "FIXED"
comp.add_link(_create_network_link(addr, comp, net_id)) comp.add_link(_create_network_link(
addr, comp, net_id,
addr["OS-EXT-IPS:type"]))
return comp return comp
@ -310,7 +320,6 @@ class Controller(ooi.api.base.Controller):
if server_ip == ip["ip"]: if server_ip == ip["ip"]:
self.os_helper.remove_floating_ip(req, server_id, self.os_helper.remove_floating_ip(req, server_id,
ip["ip"]) ip["ip"])
self.os_helper.release_floating_ip(req, ip["id"])
def _delete(self, req, server_ids): def _delete(self, req, server_ids):
for server_id in server_ids: for server_id in server_ids:

View File

@ -541,6 +541,19 @@ class OpenStackHelper(BaseHelper):
response = req.get_response(self.app) response = req.get_response(self.app)
return self.get_from_response(response, "floating_ips", []) return self.get_from_response(response, "floating_ips", [])
def get_floating_ip(self, req, floating_id):
"""Get information about a floating IP.
:param req: the incoming request
:param floating_id: floating ip id to get info from
"""
tenant_id = self.tenant_from_req(req)
path = "/%s/os-floating-ips/%s" % (tenant_id,
floating_id)
req = self._make_get_request(req, path)
response = req.get_response(self.app)
return self.get_from_response(response, "floating_ip", [])
def _get_floating_ip_pools_req(self, req): def _get_floating_ip_pools_req(self, req):
tenant_id = self.tenant_from_req(req) tenant_id = self.tenant_from_req(req)
path = "/%s/os-floating-ip-pools" % tenant_id path = "/%s/os-floating-ip-pools" % tenant_id
@ -715,7 +728,7 @@ class OpenStackHelper(BaseHelper):
@staticmethod @staticmethod
def _build_link(net_id, compute_id, ip, ip_id=None, mac=None, pool=None, def _build_link(net_id, compute_id, ip, ip_id=None, mac=None, pool=None,
state='ACTIVE'): state='ACTIVE', public_ip=False):
link = {} link = {}
link['mac'] = mac link['mac'] = mac
link['pool'] = pool link['pool'] = pool
@ -724,6 +737,7 @@ class OpenStackHelper(BaseHelper):
link['ip'] = ip link['ip'] = ip
link['ip_id'] = ip_id link['ip_id'] = ip_id
link['state'] = os_helpers.vm_state(state) link['state'] = os_helpers.vm_state(state)
link['public_ip'] = public_ip
return link return link
def _get_ports(self, req, compute_id): def _get_ports(self, req, compute_id):
@ -739,48 +753,55 @@ class OpenStackHelper(BaseHelper):
LOG.exception("Interfaces can not be shown: " + e.explanation) LOG.exception("Interfaces can not be shown: " + e.explanation)
return result return result
def get_compute_net_link(self, req, compute_id, network_id, def get_compute_net_link(self, req, compute_id, address):
address):
"""Get a specific network/server link """Get a specific network/server link
It shows a specific link (either private or public ip) It shows a specific link (either private or public ip)
:param req: the incoming request :param req: the incoming request
:param compute_id: server id :param compute_id: server id
:param network_id: network id
:param address: ip connected :param address: ip connected
""" """
compute = self.get_server(req, compute_id)
s = self.get_server(req, compute_id) server_addrs = compute.get("addresses", {})
pool = None compute_id = compute["id"]
ip_id = None ports = self._get_ports(req, compute_id)
server_addrs = s.get("addresses", {}) floating_ips = self.get_floating_ips(
req
)
for addr_set in server_addrs.values(): for addr_set in server_addrs.values():
for addr in addr_set: for addr in addr_set:
if addr["addr"] == address: if addr["addr"] == address:
public_ip = False
pool = None
ip_id = None
mac = addr["OS-EXT-IPS-MAC:mac_addr"] mac = addr["OS-EXT-IPS-MAC:mac_addr"]
if network_id == os_helpers.PUBLIC_NETWORK: ip_type = addr["OS-EXT-IPS:type"]
floating_ips = self.get_floating_ips( if ip_type == "fixed":
req network_id = "FIXED"
)
for ip in floating_ips:
if address == ip['ip']:
pool = ip['pool']
ip_id = ip['id']
else:
ports = self._get_ports(req, compute_id)
for p in ports: for p in ports:
if p["net_id"] == network_id: if p['mac_addr'] == mac:
for ip in p["fixed_ips"]: ip_id = str(p['port_id'])
if ip['ip_address'] == address: network_id = str(p['net_id'])
ip_id = p['port_id'] break
return self._build_link(network_id, else:
compute_id, network_id = "PUBLIC"
address, for fp in floating_ips:
mac=mac, if compute_id == fp['instance_id']:
pool=pool, pool = fp['pool']
ip_id=ip_id ip_id = str(fp['id'])
) network_id = str(fp['id'])
public_ip = True
break
return self._build_link(
network_id,
compute_id,
address,
mac=mac,
pool=pool,
ip_id=ip_id,
public_ip=public_ip
)
raise exception.NotFound() raise exception.NotFound()
def list_compute_net_links(self, req): def list_compute_net_links(self, req):
@ -788,45 +809,48 @@ class OpenStackHelper(BaseHelper):
:param req: the incoming request :param req: the incoming request
""" """
floating_ips = self.get_floating_ips(req)
float_list = {}
for ip in floating_ips:
if ip["instance_id"]:
float_list.update({ip['fixed_ip']: ip})
servers = self.index(req)
link_list = [] link_list = []
for s in servers: compute_list = self.index(req)
ports = self._get_ports(req, s['id']) floating_ips = self.get_floating_ips(
for p in ports: req
for ip in p["fixed_ips"]: )
mac = p['mac_addr'] for c in compute_list:
state = p["port_state"] compute_id = c["id"]
link = self._build_link(p["net_id"], compute = self.get_server(req, compute_id)
s['id'], ports = self._get_ports(req, compute_id)
ip['ip_address'], server_addrs = compute.get("addresses", {})
ip_id=p["port_id"], for addr_set in server_addrs.values():
mac=mac, for addr in addr_set:
state=state) public_ip = False
link_list.append(link) pool = None
float_ip = float_list.get(ip['ip_address'], None) network_id = "fixed"
if float_ip: mac = addr["OS-EXT-IPS-MAC:mac_addr"]
link = self._build_link(p["net_id"], ip_type = addr["OS-EXT-IPS:type"]
float_ip['instance_id'], address = addr['addr']
float_ip['ip'], ip_id = None
ip_id=float_ip["id"], if ip_type == "fixed":
mac=mac, for p in ports:
pool=float_ip["pool"] if p['mac_addr'] == mac:
) ip_id = p['port_id']
link_list.append(link) network_id = p["net_id"]
if not link_list: break
for ip in floating_ips: else:
if ip["instance_id"]: for fp in floating_ips:
link = self._build_link(os_helpers.PUBLIC_NETWORK, if address == fp['ip']:
ip['instance_id'], pool = fp['pool']
ip['ip'], ip_id = fp['id']
ip_id=ip["id"], network_id = fp['id']
pool=ip["pool"] public_ip = True
) break
link = self._build_link(
network_id,
compute_id,
address,
mac=mac,
pool=pool,
ip_id=ip_id,
public_ip=public_ip
)
link_list.append(link) link_list.append(link)
return link_list return link_list
@ -893,8 +917,43 @@ class OpenStackHelper(BaseHelper):
raise webob.exc.HTTPNotFound raise webob.exc.HTTPNotFound
def assign_floating_ip(self, req, network_id, device_id, def get_floatingip_id(self, req, address):
pool=None): """Get the floating IP ID
:param req: the incoming network
:param address: floating ip address
"""
floating_ips = self.get_floating_ips(req)
for fp in floating_ips:
if address == fp['ip']:
return str(fp['id'])
raise webob.exc.HTTPNotFound
def assign_floating_ip(self, req, floatingip_id, device_id):
"""assign floating ip to a server
:param req: the incoming request
:param floatingip_id: floating ip id
:param device_id: device id
"""
ip = self.get_floating_ip(req, floatingip_id)
self.associate_floating_ip(req, device_id, ip['ip'])
try:
link_public = self._build_link(
floatingip_id,
device_id,
ip['ip'],
ip_id=floatingip_id,
public_ip=True
)
except Exception:
raise exception.OCCIInvalidSchema()
return link_public
def assign_floating_ip_deprecated(self, req, network_id, device_id,
pool=None):
"""assign floating ip to a server """assign floating ip to a server
:param req: the incoming request :param req: the incoming request

131
ooi/api/ip_reservation.py Normal file
View File

@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
# Copyright 2015 LIP - INDIGO-DataCloud
#
# 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 ooi.api import base
from ooi.api import helpers
from ooi import exception
from ooi.occi.core import collection
from ooi.occi.infrastructure import ip_reservation
from ooi.occi import validator as occi_validator
from ooi.openstack import network as os_network
class Controller(base.Controller):
def __init__(self, app=None, openstack_version=None):
"""IP reservation controller initialization
:param app: application
:param: openstack_version: nova version
"""
super(Controller, self).__init__(
app=app,
openstack_version=openstack_version)
self.os_helper = helpers.OpenStackHelper(
self.app,
self.openstack_version
)
@staticmethod
def _get_ipreservation_resources(ipreservation_list):
"""Create network instances from ip reservations in json format
:param ipreservation_list: ip reservation objects provides by
the cloud infrastructure
"""
occi_ipreservation_resources = []
if ipreservation_list:
for s in ipreservation_list:
n_id = str(s["id"]) # some versions retrieve int.
n_name = s["pool"]
n_address = s["ip"]
n_used = False
if s["instance_id"]:
n_used = True
s = ip_reservation.IPReservation(title=n_name,
id=n_id,
address=n_address,
used=n_used
)
occi_ipreservation_resources.append(s)
return occi_ipreservation_resources
def index(self, req):
"""List ip reservations
:param req: request object
"""
occi_ipreservation = self.os_helper.get_floating_ips(req)
occi_ipreservation_resources = self._get_ipreservation_resources(
occi_ipreservation)
return collection.Collection(
resources=occi_ipreservation_resources)
def show(self, req, id):
"""Get ip reservation details
:param req: request object
:param id: ip reservation identification
"""
resp = self.os_helper.get_floating_ip(req, id)
occi_network_resources = self._get_ipreservation_resources(
[resp])
return occi_network_resources[0]
def create(self, req, body=None):
"""Create an ip reservation instance in the cloud
:param req: request object
:param body: body request (not used)
"""
parser = req.get_parser()(req.headers, req.body)
scheme = {
"category": ip_reservation.IPReservation.kind,
"optional_mixins": [
os_network.OSFloatingIPPool,
]
}
obj = parser.parse()
validator = occi_validator.Validator(obj)
validator.validate(scheme)
pool = None
if os_network.OSFloatingIPPool.scheme in obj["schemes"]:
pool = (
obj["schemes"][os_network.OSFloatingIPPool.scheme][0]
)
resp = self.os_helper.allocate_floating_ip(req, pool)
occi_network_resources = self._get_ipreservation_resources(
[resp])
return collection.Collection(resources=occi_network_resources)
def delete(self, req, id):
"""delete an ip reservation instance
:param req: current request
:param id: identification
"""
self.os_helper.release_floating_ip(req, id)
return []
def run_action(self, req, id, body):
"""Run action over the network
:param req: current request
:param id: ip reservation identification
:param body: body
"""
raise exception.NotImplemented()

View File

@ -18,6 +18,7 @@ from ooi.api import helpers
from ooi import exception from ooi import exception
from ooi.occi.core import collection from ooi.occi.core import collection
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import network_link from ooi.occi.infrastructure import network_link
from ooi.occi import validator as occi_validator from ooi.occi import validator as occi_validator
@ -40,8 +41,14 @@ def _get_network_link_resources(link_list):
state = l.get('state', None) state = l.get('state', None)
ip_id = l.get('ip_id', None) ip_id = l.get('ip_id', None)
net_id = l['network_id'] net_id = l['network_id']
n = network.NetworkResource(title="network", public_ip = l['public_ip']
id=net_id) if public_ip:
n = ip_reservation.IPReservation(title="network",
address=ip,
id=net_id)
else:
n = network.NetworkResource(title="network",
id=net_id)
c = compute.ComputeResource(title="Compute", c = compute.ComputeResource(title="Compute",
id=compute_id id=compute_id
) )
@ -77,14 +84,13 @@ class Controller(base.Controller):
:param id: network link identification :param id: network link identification
""" """
try: try:
server_id, network_id, server_addr = id.split('_', 2) server_id, server_addr = id.split('_', 1)
except ValueError: except ValueError:
raise exception.LinkNotFound(link_id=id) raise exception.LinkNotFound(link_id=id)
try: try:
link = self.os_helper.get_compute_net_link( link = self.os_helper.get_compute_net_link(
req, req,
server_id, server_id,
network_id,
server_addr) server_addr)
occi_instance = _get_network_link_resources([link])[0] occi_instance = _get_network_link_resources([link])[0]
except Exception: except Exception:
@ -122,28 +128,42 @@ class Controller(base.Controller):
validator.validate(scheme) validator.validate(scheme)
attrs = obj.get("attributes", {}) attrs = obj.get("attributes", {})
_, net_id = helpers.get_id_with_kind(
req,
attrs.get("occi.core.target"),
network.NetworkResource.kind)
_, server_id = helpers.get_id_with_kind( _, server_id = helpers.get_id_with_kind(
req, req,
attrs.get("occi.core.source"), attrs.get("occi.core.source"),
compute.ComputeResource.kind) compute.ComputeResource.kind)
pool = None
if os_network.OSFloatingIPPool.scheme in obj["schemes"]: if (ip_reservation.IPReservation.kind.location in
pool = ( attrs.get("occi.core.target")):
obj["schemes"][os_network.OSFloatingIPPool.scheme][0] _, net_id = helpers.get_id_with_kind(
) req,
# Allocate public IP and associate it ot the server attrs.get("occi.core.target"),
if net_id == os_helpers.PUBLIC_NETWORK: ip_reservation.IPReservation.kind)
os_link = self.os_helper.assign_floating_ip( os_link = self.os_helper.assign_floating_ip(
req, net_id, server_id, pool req, net_id, server_id
) )
else: else:
# Allocate private network _, net_id = helpers.get_id_with_kind(
os_link = self.os_helper.create_port( req,
req, net_id, server_id) attrs.get("occi.core.target"),
network.NetworkResource.kind)
# TODO(jorgesece): DEPRECATION
# Delete this method for linking public network.
if net_id == os_helpers.PUBLIC_NETWORK:
pool = None
if os_network.OSFloatingIPPool.scheme in obj["schemes"]:
pool = (
obj["schemes"][os_network.OSFloatingIPPool.scheme][0]
)
# Allocate public IP and associate it on the server
os_link = self.os_helper.assign_floating_ip_deprecated(
req, net_id, server_id, pool
)
# END DEPRECATION
else:
# Allocate private network
os_link = self.os_helper.create_port(
req, net_id, server_id)
occi_link = _get_network_link_resources([os_link]) occi_link = _get_network_link_resources([os_link])
return collection.Collection(resources=occi_link) return collection.Collection(resources=occi_link)
@ -155,6 +175,7 @@ class Controller(base.Controller):
""" """
iface = self._get_interface_from_id(req, id) iface = self._get_interface_from_id(req, id)
server = iface.source.id server = iface.source.id
# TODO(jorgesece): DEPRECATION
if iface.target.id == os_helpers.PUBLIC_NETWORK: if iface.target.id == os_helpers.PUBLIC_NETWORK:
# remove floating IP # remove floating IP
self.os_helper.remove_floating_ip(req, server, self.os_helper.remove_floating_ip(req, server,
@ -163,7 +184,13 @@ class Controller(base.Controller):
# release IP # release IP
self.os_helper.release_floating_ip(req, self.os_helper.release_floating_ip(req,
iface.ip_id) iface.ip_id)
# END DEPRECATION
else: else:
self.os_helper.delete_port( if isinstance(iface.target,
req, server, iface.ip_id) ip_reservation.IPReservation):
self.os_helper.remove_floating_ip(req, server,
iface.address)
else:
self.os_helper.delete_port(
req, server, iface.ip_id)
return [] return []

View File

@ -21,6 +21,7 @@ from ooi.occi.core import link
from ooi.occi.core import resource from ooi.occi.core import resource
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import contextualization from ooi.occi.infrastructure import contextualization
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import network_link from ooi.occi.infrastructure import network_link
from ooi.occi.infrastructure import storage from ooi.occi.infrastructure import storage
@ -99,6 +100,7 @@ class Controller(base.Controller):
mixins.append(network.ip_network) mixins.append(network.ip_network)
kinds.append(network_link.NetworkInterface.kind) kinds.append(network_link.NetworkInterface.kind)
mixins.append(network_link.ip_network_interface) mixins.append(network_link.ip_network_interface)
kinds.append(ip_reservation.IPReservation.kind)
# OCCI infra compute mixins # OCCI infra compute mixins
mixins.append(infra_templates.os_tpl) mixins.append(infra_templates.os_tpl)

View File

@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
# Copyright 2015 LIP - INDIGO-DataCloud
#
# 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 ooi.occi.core import attribute as attr
from ooi.occi.core import kind
from ooi.occi import helpers
from ooi.occi.infrastructure import network
class IPReservation(network.NetworkResource):
attributes = attr.AttributeCollection({
"occi.ipreservation.address": attr.MutableAttribute(
"occi.ipreservation.address",
description="Internet Protocol(IP) network"
" address re-served for Compute instances"
" linking with this IPReservation instance",
attr_type=attr.AttributeType.string_type),
"occi.ipreservation.used": attr.InmutableAttribute(
"occi.ipreservation.used",
description="Indication whether"
" the reserved address is currently in use.",
attr_type=attr.AttributeType.boolean_type),
"occi.ipreservation.state": attr.InmutableAttribute(
"occi.ipreservation.state",
description="Indicates the state of the resource.",
attr_type=attr.AttributeType.string_type),
})
kind = kind.Kind(helpers.build_scheme('infrastructure'), 'ipreservation',
'IPReservation', attributes, 'ipreservation/',
parent=network.NetworkResource.kind)
def __init__(self, title, address, id=None, used=False,
state=None, mixins=[]):
super(IPReservation, self).__init__(title, id=id,
mixins=mixins)
self.address = address
self.attributes["occi.ipreservation.used"] = (
attr.InmutableAttribute.from_attr(
self.attributes["occi.ipreservation.used"], used))
self.attributes["occi.ipreservation.state"] = (
attr.InmutableAttribute.from_attr(
self.attributes["occi.ipreservation.state"], state))
@property
def address(self):
return self.attributes["occi.ipreservation.address"].value
@address.setter
def address(self, value):
self.attributes["occi.ipreservation.address"].value = value
@property
def used(self):
return self.attributes["occi.ipreservation.used"].value
@property
def state(self):
return self.attributes["occi.ipreservation.state"].value

View File

@ -46,7 +46,7 @@ class OSNetworkInterface(network_link.NetworkInterface):
def __init__(self, source, target, mac, address, ip_id=None, def __init__(self, source, target, mac, address, ip_id=None,
pool=None, state='active'): pool=None, state='active'):
link_id = '_'.join([source.id, target.id, address]) link_id = '_'.join([source.id, address])
mixins = [network_link.ip_network_interface] mixins = [network_link.ip_network_interface]
if pool: if pool:
mixins.append(OSFloatingIPPool(pool)) mixins.append(OSFloatingIPPool(pool))

View File

@ -125,8 +125,12 @@ pools = {
} }
linked_vm_id = uuid.uuid4().hex linked_vm_id = uuid.uuid4().hex
linked_vm_id_2 = uuid.uuid4().hex
allocated_ip = "192.168.253.23" allocated_ip = {"ip": "192.168.253.23",
"id": 1,
"pool": uuid.uuid4().hex,
"instance_id": None}
floating_ips = { floating_ips = {
tenants["foo"]["id"]: [], tenants["foo"]["id"]: [],
@ -182,6 +186,16 @@ ports = {
"net_id": uuid.uuid4().hex, "net_id": uuid.uuid4().hex,
"server_id": linked_vm_id "server_id": linked_vm_id
}, },
{
"port_id": uuid.uuid4().hex,
"fixed_ips": [
{"ip_address": "192.168.253.2"}
],
"mac_addr": uuid.uuid4().hex,
"port_state": "ACTIVE",
"net_id": uuid.uuid4().hex,
"server_id": linked_vm_id_2
},
], ],
} }
@ -251,6 +265,32 @@ servers = {
"security_groups":[ "security_groups":[
{"name": "group1"} {"name": "group1"}
] ]
},
{
"id": linked_vm_id_2,
"name": "withvolume",
"flavor": {"id": flavors[1]["id"]},
"image": {"id": images["bar"]["id"]},
"status": "ACTIVE",
"os-extended-volumes:volumes_attached": [
{"id": volumes[tenants["baz"]["id"]][0]["id"]}
],
"addresses": {
"private": [
{"addr": (
(ports[tenants["baz"]["id"]]
[1]["fixed_ips"][0]["ip_address"])
),
"OS-EXT-IPS:type": "fixed",
"OS-EXT-IPS-MAC:mac_addr": (
ports[tenants["baz"]["id"]][1]["mac_addr"]
)
},
{"addr": floating_ips[tenants["baz"]["id"]][0]["ip"],
"OS-EXT-IPS:type": "floating",
"OS-EXT-IPS-MAC:mac_addr": "1234"},
]
}
} }
], ],
} }
@ -441,6 +481,12 @@ def fake_query_results():
'scheme="http://schemas.ogf.org/occi/infrastructure/' 'scheme="http://schemas.ogf.org/occi/infrastructure/'
'networkinterface#"; ' 'networkinterface#"; '
'class="mixin"; title="IP Network interface Mixin"') 'class="mixin"; title="IP Network interface Mixin"')
cats.append(
'ipreservation; '
'scheme="http://schemas.ogf.org/occi/infrastructure#"; '
'class="kind"; title="IPReservation"; '
'rel="http://schemas.ogf.org/occi/infrastructure#network"; '
'location="%s/ipreservation/"' % application_url)
# OCCI Infrastructure Storage # OCCI Infrastructure Storage
cats.append( cats.append(
@ -615,6 +661,20 @@ class FakeApp(object):
self.routes[path_base] = create_fake_json_resp( self.routes[path_base] = create_fake_json_resp(
{obj: list_obj}) {obj: list_obj})
def _populate_ports(self, path, servers_list, ports_list):
for s in servers_list:
p_list = []
path_base = "%s/servers/%s/%s" % (
path,
s["id"],
"os-interface"
)
for p in ports_list:
if p["server_id"] == s["id"]:
p_list.append(p)
self.routes[path_base] = create_fake_json_resp(
{"interfaceAttachments": p_list})
@webob.dec.wsgify() @webob.dec.wsgify()
def __call__(self, req): def __call__(self, req):
if req.method == "GET": if req.method == "GET":
@ -660,7 +720,7 @@ class FakeApp(object):
else: else:
exc = webob.exc.HTTPNotFound() exc = webob.exc.HTTPNotFound()
return FakeOpenStackFault(exc) return FakeOpenStackFault(exc)
ip = {"floating_ip": {"ip": allocated_ip, "id": 1}} ip = {"floating_ip": allocated_ip}
return create_fake_json_resp(ip, 202) return create_fake_json_resp(ip, 202)
def _do_create_port(self, req): def _do_create_port(self, req):
@ -673,10 +733,9 @@ class FakeApp(object):
p = {"interfaceAttachment": { p = {"interfaceAttachment": {
"port_id": uuid.uuid4().hex, "port_id": uuid.uuid4().hex,
"fixed_ips": "fixed_ips":
[{"ip_address": [{
port[0]["fixed_ips"] "ip_address": port[0]["fixed_ips"][0]["ip_address"]
[0]["ip_address"] }],
}],
"mac_addr": port[0]["mac_addr"], "mac_addr": port[0]["mac_addr"],
"port_state": "DOWN", "port_state": "DOWN",
"net_id": net, "net_id": net,

View File

@ -292,7 +292,7 @@ def create_headers(category, content_type=None,
def fake_build_link(net_id, compute_id, ip, mac=None, def fake_build_link(net_id, compute_id, ip, mac=None,
pool=None, state='active'): pool=None, state='active', public_ip=False):
link = {} link = {}
link['mac'] = mac link['mac'] = mac
link['pool'] = pool link['pool'] = pool
@ -300,6 +300,7 @@ def fake_build_link(net_id, compute_id, ip, mac=None,
link['compute_id'] = compute_id link['compute_id'] = compute_id
link['ip'] = ip link['ip'] = ip
link['state'] = state link['state'] = state
link['public_ip'] = public_ip
return link return link

View File

@ -424,12 +424,21 @@ class TestComputeController(test_middleware.TestMiddleware):
for addr in addr_set: for addr in addr_set:
ip = addr["addr"] ip = addr["addr"]
if addr["OS-EXT-IPS:type"] == "fixed": if addr["OS-EXT-IPS:type"] == "fixed":
net_id = fakes.ports[tenant["id"]][0]["net_id"] for p in fakes.ports[tenant["id"]]:
if (p["mac_addr"] ==
addr["OS-EXT-IPS-MAC:mac_addr"]):
net_id = p["net_id"]
break
target = utils.join_url(self.application_url + "/",
"network/%s" % net_id)
else: else:
net_id = "PUBLIC" for floating_ip in fakes.floating_ips[tenant["id"]]:
link_id = '_'.join([server["id"], net_id, ip]) if floating_ip["ip"] == ip:
target = utils.join_url(self.application_url + "/", net_id = floating_ip['id']
"network/%s" % net_id) break
target = utils.join_url(self.application_url + "/",
"ipreservation/%s" % net_id)
link_id = '_'.join([server["id"], ip])
self.assertResultIncludesLink(link_id, source, target, self.assertResultIncludesLink(link_id, source, target,
resp) resp)

View File

@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
# Copyright 2015 LIP - INDIGO-DataCloud
#
# 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 uuid
from ooi.tests import fakes
from ooi.tests.functional.middleware import test_middleware
from ooi import utils
def build_occi_ip_reservation(ip, application_url):
name = ip["pool"]
network_id = ip["id"]
address = ip["ip"]
if ip["instance_id"]:
used = str(True).lower()
else:
used = str(False).lower()
cats = []
cats.append('ipreservation; '
'scheme='
'"http://schemas.ogf.org/occi/infrastructure#";'
' class="kind"; title="IPReservation"; rel='
'"http://schemas.ogf.org/occi/infrastructure#network";'
' location="%s/ipreservation/"' % application_url)
links = []
links.append('<%s/ipreservation/%s?action=up>; '
'rel="http://schemas.ogf.org/occi/'
'infrastructure/network/action#up"' %
(application_url, network_id))
links.append('<%s/ipreservation/%s?action=down>; '
'rel="http://schemas.ogf.org/occi/'
'infrastructure/network/action#down"' %
(application_url, network_id))
attrs = [
'occi.core.title="%s"' % name,
'occi.core.id="%s"' % network_id,
'occi.ipreservation.address="%s"' % address,
'occi.ipreservation.used="%s"' % used,
]
result = []
for c in cats:
result.append(("Category", c))
for a in attrs:
result.append(("X-OCCI-Attribute", a))
for l in links:
result.append(("Link", l))
return result
class TestNetIPReservationController(test_middleware.TestMiddleware):
"""Test OCCI IP Reservation controller."""
def setUp(self):
super(TestNetIPReservationController, self).setUp()
self.application_url = fakes.application_url
self.app = self.get_app()
def test_list_empty(self):
tenant = fakes.tenants["bar"]
for url in ("/ipreservation/", "/ipreservation"):
req = self._build_req(url, tenant["id"], method="GET")
req.environ["HTTP_X_PROJECT_ID"] = tenant["id"]
resp = req.get_response(self.app)
expected_result = ""
self.assertContentType(resp)
self.assertExpectedResult(expected_result, resp)
self.assertEqual(204, resp.status_code)
def test_list(self):
tenant = fakes.tenants["baz"]
for url in ("/ipreservation/", "/ipreservation"):
req = self._build_req(url, tenant["id"], method="GET")
resp = req.get_response(self.app)
self.assertEqual(200, resp.status_code)
expected = []
for ip in fakes.floating_ips[tenant["id"]]:
expected.append(
("X-OCCI-Location",
utils.join_url(self.application_url + "/",
"ipreservation/%s" % ip["id"]))
)
self.assertExpectedResult(expected, resp)
def test_show(self):
tenant = fakes.tenants["baz"]
for ip in fakes.floating_ips[tenant["id"]]:
ip_id = ip["id"]
req = self._build_req("/ipreservation/%s" % ip_id,
tenant["id"], method="GET")
resp = req.get_response(self.app)
self.assertContentType(resp)
self.assertEqual(200, resp.status_code)
expected = build_occi_ip_reservation(
ip,
self.application_url)
self.assertExpectedResult(expected, resp)
def test_show_invalid_id(self):
tenant = fakes.tenants["foo"]
link_id = uuid.uuid4().hex
req = self._build_req("/ipreservation/%s" % link_id,
tenant["id"], method="GET")
resp = req.get_response(self.app)
self.assertEqual(404, resp.status_code)
def test_delete(self):
tenant = fakes.tenants["foo"]
link_id = uuid.uuid4().hex
req = self._build_req("/ipreservation/%s" % link_id,
tenant["id"], method="DELETE")
resp = req.get_response(self.app)
self.assertEqual(204, resp.status_code)
def test_create(self):
tenant = fakes.tenants["baz"]
ip_id = fakes.allocated_ip["id"]
headers = {
'Category': 'ipreservation;'
' scheme='
'"http://schemas.ogf.org/occi/infrastructure#";'
'class="kind",'
}
req = self._build_req("/ipreservation/",
tenant["id"],
method="POST",
headers=headers)
resp = req.get_response(self.app)
expected = [("X-OCCI-Location",
utils.join_url(self.application_url + "/",
"ipreservation/%s" % ip_id))]
self.assertEqual(200, resp.status_code)
self.assertExpectedResult(expected, resp)
def test_create_with_pool(self):
tenant = fakes.tenants["baz"]
ip_id = fakes.allocated_ip["id"]
pool_name = "public"
headers = {
'Category': ('ipreservation;'
' scheme='
'"http://schemas.ogf.org/occi/infrastructure#";'
'class="kind",'
'%s;'
'scheme="http://schemas.openstack.org/network/'
'floatingippool#"; class="mixin"') % pool_name,
}
req = self._build_req("/ipreservation/",
tenant["id"],
method="POST",
headers=headers)
resp = req.get_response(self.app)
expected = [("X-OCCI-Location",
utils.join_url(self.application_url + "/",
"ipreservation/%s" % ip_id))]
self.assertEqual(200, resp.status_code)
self.assertExpectedResult(expected, resp)

View File

@ -52,42 +52,29 @@ class TestNetInterfaceController(test_middleware.TestMiddleware):
resp = req.get_response(self.app) resp = req.get_response(self.app)
self.assertEqual(200, resp.status_code) self.assertEqual(200, resp.status_code)
servers = fakes.servers[tenant["id"]]
expected = [] expected = []
float_list = {} for server in servers:
for floating_ip in fakes.floating_ips[tenant["id"]]: server_addrs = server.get("addresses", {})
if floating_ip["instance_id"]: instance_vm = server["id"]
float_list.update({floating_ip['fixed_ip']: floating_ip}) for addr_set in server_addrs.values():
instance_vm = fakes.linked_vm_id for addr in addr_set:
for p in fakes.ports[tenant["id"]]: address = addr['addr']
for ip in p["fixed_ips"]:
link_id = '_'.join([instance_vm,
p["net_id"],
ip["ip_address"]])
expected.append(
("X-OCCI-Location",
utils.join_url(self.application_url + "/",
"networklink/%s" % link_id))
)
float_ip = float_list.get(ip['ip_address'], None)
if float_ip:
link_id = '_'.join([instance_vm, link_id = '_'.join([instance_vm,
"PUBLIC", address])
float_ip["ip"]])
expected.append( expected.append(
("X-OCCI-Location", ("X-OCCI-Location",
utils.join_url(self.application_url + "/", utils.join_url(self.application_url + "/",
"networklink/%s" % link_id)) "networklink/%s" % link_id)))
)
self.assertExpectedResult(expected, resp) self.assertExpectedResult(expected, resp)
def test_show_iface(self): def test_show_iface(self):
tenant = fakes.tenants["baz"] tenant = fakes.tenants["baz"]
instance_vm = fakes.linked_vm_id
for p in fakes.ports[tenant["id"]]: for p in fakes.ports[tenant["id"]]:
for ip in p["fixed_ips"]: for ip in p["fixed_ips"]:
instance_vm = p["server_id"]
link_id = '_'.join([instance_vm, link_id = '_'.join([instance_vm,
p["net_id"],
ip["ip_address"]] ip["ip_address"]]
) )
req = self._build_req("/networklink/%s" % link_id, req = self._build_req("/networklink/%s" % link_id,
@ -178,7 +165,6 @@ class TestNetInterfaceController(test_middleware.TestMiddleware):
resp = req.get_response(self.app) resp = req.get_response(self.app)
link_id = '_'.join([link_info['server_id'], link_id = '_'.join([link_info['server_id'],
link_info['net_id'],
link_info['fixed_ips'][0] link_info['fixed_ips'][0]
["ip_address"]]) ["ip_address"]])
expected = [("X-OCCI-Location", expected = [("X-OCCI-Location",
@ -188,6 +174,28 @@ class TestNetInterfaceController(test_middleware.TestMiddleware):
self.assertExpectedResult(expected, resp) self.assertExpectedResult(expected, resp)
self.assertDefaults(resp) self.assertDefaults(resp)
def test_create_link_ipreservation(self):
tenant = fakes.tenants["baz"]
net_id = fakes.floating_ips[tenant['id']][0]['id']
occi_compute_id = utils.join_url(
self.application_url + "/",
"compute/%s" % fakes.linked_vm_id)
occi_net_id = utils.join_url(self.application_url + "/",
"ipreservation/%s" % net_id)
headers = {
'Category': (
'networkinterface;'
'scheme="http://schemas.ogf.org/occi/infrastructure#";'
'class="kind"'),
'X-OCCI-Attribute': ('occi.core.source="%s", '
'occi.core.target="%s"'
) % (occi_compute_id, occi_net_id)
}
req = self._build_req("/networklink", tenant["id"], method="POST",
headers=headers)
resp = req.get_response(self.app)
self.assertEqual(200, resp.status_code)
def test_delete_fixed(self): def test_delete_fixed(self):
tenant = fakes.tenants["baz"] tenant = fakes.tenants["baz"]
@ -195,7 +203,6 @@ class TestNetInterfaceController(test_middleware.TestMiddleware):
if n["net_id"] != "PUBLIC": if n["net_id"] != "PUBLIC":
if n["server_id"]: if n["server_id"]:
link_id = '_'.join([n["server_id"], link_id = '_'.join([n["server_id"],
n["net_id"],
n["fixed_ips"] n["fixed_ips"]
[0]["ip_address"]]) [0]["ip_address"]])
req = self._build_req( req = self._build_req(
@ -210,7 +217,18 @@ class TestNetInterfaceController(test_middleware.TestMiddleware):
for n in fakes.floating_ips[tenant["id"]]: for n in fakes.floating_ips[tenant["id"]]:
if n["instance_id"]: if n["instance_id"]:
link_id = '_'.join([n["instance_id"], link_id = '_'.join([n["instance_id"],
"PUBLIC", n["ip"]])
req = self._build_req("/networklink/%s" % link_id,
tenant["id"], method="DELETE")
resp = req.get_response(self.app)
self.assertContentType(resp)
self.assertEqual(204, resp.status_code)
def test_delete_ipreservation(self):
tenant = fakes.tenants["baz"]
for n in fakes.floating_ips[tenant["id"]]:
if n["instance_id"]:
link_id = '_'.join([n["instance_id"],
n["ip"]]) n["ip"]])
req = self._build_req("/networklink/%s" % link_id, req = self._build_req("/networklink/%s" % link_id,
tenant["id"], method="DELETE") tenant["id"], method="DELETE")

View File

@ -86,8 +86,7 @@ class TestComputeController(base.TestController):
@mock.patch.object(compute.Controller, "_get_server_floating_ips") @mock.patch.object(compute.Controller, "_get_server_floating_ips")
@mock.patch.object(helpers.OpenStackHelper, "get_floating_ips") @mock.patch.object(helpers.OpenStackHelper, "get_floating_ips")
@mock.patch.object(helpers.OpenStackHelper, "remove_floating_ip") @mock.patch.object(helpers.OpenStackHelper, "remove_floating_ip")
@mock.patch.object(helpers.OpenStackHelper, "release_floating_ip") def test_release_floating_ips(self, mock_remove,
def test_release_floating_ips(self, mock_release, mock_remove,
mock_get_floating, mock_get_floating,
mock_server_floating): mock_server_floating):
mock_server_floating.return_value = ["1.2.3.4", "5.6.7.8"] mock_server_floating.return_value = ["1.2.3.4", "5.6.7.8"]
@ -100,8 +99,6 @@ class TestComputeController(base.TestController):
mock_get_floating.assert_called_with(None) mock_get_floating.assert_called_with(None)
mock_remove.assert_has_calls([mock.call(None, "foo", "1.2.3.4"), mock_remove.assert_has_calls([mock.call(None, "foo", "1.2.3.4"),
mock.call(None, "foo", "5.6.7.8")]) mock.call(None, "foo", "5.6.7.8")])
mock_release.assert_has_calls([mock.call(None, "bar"),
mock.call(None, "baz")])
@mock.patch.object(compute.Controller, "_delete") @mock.patch.object(compute.Controller, "_delete")
def test_delete(self, mock_delete): def test_delete(self, mock_delete):
@ -179,7 +176,8 @@ class TestComputeController(base.TestController):
@mock.patch.object(helpers.OpenStackHelper, "get_flavor") @mock.patch.object(helpers.OpenStackHelper, "get_flavor")
@mock.patch.object(helpers.OpenStackHelper, "get_server") @mock.patch.object(helpers.OpenStackHelper, "get_server")
@mock.patch.object(helpers.OpenStackHelper, "get_network_id") @mock.patch.object(helpers.OpenStackHelper, "get_network_id")
def test_show(self, m_net_id, m_server, m_flavor, m_image, m_vol): @mock.patch.object(helpers.OpenStackHelper, "get_floatingip_id")
def test_show(self, m_ipr, m_net_id, m_server, m_flavor, m_image, m_vol):
for tenant in fakes.tenants.values(): for tenant in fakes.tenants.values():
servers = fakes.servers[tenant["id"]] servers = fakes.servers[tenant["id"]]
for server in servers: for server in servers:
@ -194,6 +192,11 @@ class TestComputeController(base.TestController):
net_id = fakes.networks.get(tenant["id"], []) net_id = fakes.networks.get(tenant["id"], [])
if net_id: if net_id:
net_id = net_id[0]['id'] net_id = net_id[0]['id']
floatip_ip = fakes.floating_ips.get(tenant["id"], [])
floatip_id = 0
if floatip_ip.__len__() > 0:
floatip_id = floatip_ip[0]['id']
m_ipr.return_value = floatip_id
m_net_id.return_value = net_id m_net_id.return_value = net_id
m_server.return_value = server m_server.return_value = server
m_flavor.return_value = flavor m_flavor.return_value = flavor
@ -207,13 +210,17 @@ class TestComputeController(base.TestController):
m_flavor.assert_called_with(None, flavor["id"]) m_flavor.assert_called_with(None, flavor["id"])
m_image.assert_called_with(None, image["id"]) m_image.assert_called_with(None, image["id"])
m_vol.assert_called_with(None, server["id"]) m_vol.assert_called_with(None, server["id"])
if floatip_ip:
m_ipr.assert_called_with(None, floatip_ip[0]["ip"])
@mock.patch.object(helpers.OpenStackHelper, "get_server_volumes_link") @mock.patch.object(helpers.OpenStackHelper, "get_server_volumes_link")
@mock.patch.object(helpers.OpenStackHelper, "get_image") @mock.patch.object(helpers.OpenStackHelper, "get_image")
@mock.patch.object(helpers.OpenStackHelper, "get_flavor") @mock.patch.object(helpers.OpenStackHelper, "get_flavor")
@mock.patch.object(helpers.OpenStackHelper, "get_server") @mock.patch.object(helpers.OpenStackHelper, "get_server")
@mock.patch.object(helpers.OpenStackHelper, "get_network_id") @mock.patch.object(helpers.OpenStackHelper, "get_network_id")
def test_show_no_image(self, m_net_id, m_server, m_flavor, m_image, m_vol): @mock.patch.object(helpers.OpenStackHelper, "get_floatingip_id")
def test_show_no_image(self, m_ipr, m_net_id, m_server, m_flavor,
m_image, m_vol):
for tenant in fakes.tenants.values(): for tenant in fakes.tenants.values():
servers = fakes.servers[tenant["id"]] servers = fakes.servers[tenant["id"]]
for server in servers: for server in servers:
@ -225,6 +232,11 @@ class TestComputeController(base.TestController):
net_id = fakes.networks.get(tenant["id"], []) net_id = fakes.networks.get(tenant["id"], [])
if net_id: if net_id:
net_id = net_id[0]['id'] net_id = net_id[0]['id']
floatip_ip = fakes.floating_ips.get(tenant["id"], [])
floatip_id = 0
if floatip_ip:
floatip_id = floatip_ip[0]['id']
m_ipr.return_value = floatip_id
m_net_id.return_value = net_id m_net_id.return_value = net_id
m_server.return_value = server m_server.return_value = server
m_flavor.return_value = flavor m_flavor.return_value = flavor
@ -238,6 +250,8 @@ class TestComputeController(base.TestController):
m_flavor.assert_called_with(None, flavor["id"]) m_flavor.assert_called_with(None, flavor["id"])
m_image.assert_called_with(None, image["id"]) m_image.assert_called_with(None, image["id"])
m_vol.assert_called_with(None, server["id"]) m_vol.assert_called_with(None, server["id"])
if floatip_ip:
m_ipr.assert_called_with(None, floatip_ip[0]["ip"])
@mock.patch.object(helpers.OpenStackHelper, "create_server") @mock.patch.object(helpers.OpenStackHelper, "create_server")
@mock.patch.object(compute.Controller, "_get_network_from_req") @mock.patch.object(compute.Controller, "_get_network_from_req")

View File

@ -1403,4 +1403,33 @@ class TestOpenStackHelperReqs(TestBaseHelper):
self.assertEqual(net_id, ret['network_id']) self.assertEqual(net_id, ret['network_id'])
self.assertEqual(device_id, ret['compute_id']) self.assertEqual(device_id, ret['compute_id'])
self.assertEqual(ip, ret['ip']) self.assertEqual(ip, ret['ip'])
@mock.patch.object(helpers.OpenStackHelper,
"_get_req")
@mock.patch.object(helpers.OpenStackHelper, "tenant_from_req")
def test_associate_floating_ip_deprecated(self, m_ten, m_req):
m_ten.return_value = uuid.uuid4().hex
net_id = uuid.uuid4().hex
device_id = uuid.uuid4().hex
ip = uuid.uuid4().hex
ip_id = uuid.uuid4().hex
pool = uuid.uuid4().hex
resp = fakes.create_fake_json_resp(
{"floating_ip": {"ip": ip, "pool": pool, 'id': ip_id}},
202
)
req_all = mock.MagicMock()
req_all.get_response.return_value = resp
resp_ass = fakes.create_fake_json_resp({}, 202)
req_ass = mock.MagicMock()
req_ass.get_response.return_value = resp_ass
m_req.side_effect = [req_all,
req_ass]
ret = self.helper.assign_floating_ip_deprecated(None,
net_id,
device_id)
self.assertIsNotNone(ret)
self.assertEqual(net_id, ret['network_id'])
self.assertEqual(device_id, ret['compute_id'])
self.assertEqual(ip, ret['ip'])
self.assertEqual(pool, ret['pool']) self.assertEqual(pool, ret['pool'])

View File

@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
# Copyright 2015 LIP - INDIGO-DataCloud
#
# 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 mock
from ooi.api import helpers
from ooi.api import ip_reservation as ip_reservation_control
from ooi.occi.infrastructure import ip_reservation
from ooi.openstack import network as os_network
from ooi.tests import base
from ooi.tests import fakes
from ooi.tests import fakes_network as fake_nets
class TestIPReservationController(base.TestController):
def setUp(self):
super(TestIPReservationController, self).setUp()
self.controller = ip_reservation_control.Controller(
mock.MagicMock(), None
)
@mock.patch.object(helpers.OpenStackHelper, "get_floating_ips")
def test_index_empty(self, m_iplist):
tenant = fakes.tenants["foo"]
floating_list = fakes.floating_ips[tenant["id"]]
m_iplist.return_value = floating_list
result = self.controller.index(None)
expected = self.controller._get_ipreservation_resources(floating_list)
self.assertEqual(expected, result.resources)
self.assertEqual([], result.resources)
m_iplist.assert_called_with(None)
@mock.patch.object(helpers.OpenStackHelper, "get_floating_ips")
def test_index(self, m_iplist):
tenant = fakes.tenants["baz"]
floating_list = fakes.floating_ips[tenant["id"]]
m_iplist.return_value = floating_list
result = self.controller.index(None)
expected = self.controller._get_ipreservation_resources(floating_list)
self.assertEqual(expected, result.resources)
m_iplist.assert_called_with(None)
@mock.patch.object(helpers.OpenStackHelper, "get_floating_ip")
def test_show(self, m_ip):
tenant = fakes.tenants["baz"]
floating_ip = fakes.floating_ips[tenant["id"]][0]
m_ip.return_value = floating_ip
result = self.controller.show(None, floating_ip["id"])
expected = self.controller._get_ipreservation_resources(
[floating_ip])[0]
self.assertIsInstance(result, ip_reservation.IPReservation)
self.assertEqual(expected, result)
m_ip.assert_called_with(None, floating_ip["id"])
@mock.patch.object(helpers.OpenStackHelper,
"release_floating_ip")
def test_delete(self, mock_release):
tenant = fakes.tenants["baz"]
floating_ip = fakes.floating_ips[tenant["id"]][0]
mock_release.return_value = []
self.controller.delete(None, floating_ip["id"])
mock_release.assert_called_with(None, floating_ip["id"])
@mock.patch.object(helpers.OpenStackHelper,
"allocate_floating_ip")
def test_create(self, mock_allocate):
tenant = fakes.tenants["baz"]
floating_list = fakes.floating_ips[tenant["id"]][0]
mock_allocate.return_value = floating_list
parameters = {}
categories = {ip_reservation.IPReservation.kind}
req = fake_nets.create_req_test_occi(parameters, categories)
result = self.controller.create(req)
expected = self.controller._get_ipreservation_resources(
[floating_list])
self.assertEqual(expected, result.resources)
mock_allocate.assert_called_with(req, None)
@mock.patch.object(helpers.OpenStackHelper, "allocate_floating_ip")
@mock.patch("ooi.occi.validator.Validator")
def test_create_pool(self, mock_validator, mock_allocate):
tenant = fakes.tenants["baz"]
floating_list = fakes.floating_ips[tenant["id"]][0]
mock_allocate.return_value = floating_list
pool_name = "public"
obj = {
"attributes": {},
"schemes": {
os_network.OSFloatingIPPool.scheme: [pool_name],
}
}
parameters = {}
categories = {ip_reservation.IPReservation.kind}
req = fake_nets.create_req_test_occi(parameters, categories)
req.get_parser = mock.MagicMock()
req.get_parser.return_value.return_value.parse.return_value = obj
mock_validator.validate.return_value = True
result = self.controller.create(req)
expected = self.controller._get_ipreservation_resources(
[floating_list])
self.assertEqual(expected, result.resources)
mock_allocate.assert_called_with(req, pool_name)

View File

@ -22,6 +22,7 @@ from ooi.api import network_link as network_link_api
from ooi import exception from ooi import exception
from ooi.occi.core import collection from ooi.occi.core import collection
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import network_link from ooi.occi.infrastructure import network_link
from ooi.openstack import network as os_network from ooi.openstack import network as os_network
@ -133,16 +134,14 @@ class TestNetworkLinkController(base.TestController):
os_link['network_id'], os_link['instance_id'], os_link['ip'], os_link['network_id'], os_link['instance_id'], os_link['ip'],
mac=None, pool=os_link['pool'], state=os_link['status'] mac=None, pool=os_link['pool'], state=os_link['status']
) )
link_id = '%s_%s_%s' % ( link_id = '%s_%s' % (
os_link['instance_id'], os_link['instance_id'],
os_link['network_id'],
os_link['ip']) os_link['ip'])
ret = self.controller.show(None, link_id) ret = self.controller.show(None, link_id)
self.assertIsInstance(ret, os_network.OSNetworkInterface) self.assertIsInstance(ret, os_network.OSNetworkInterface)
self.assertEqual(os_link["ip"], ret.address) self.assertEqual(os_link["ip"], ret.address)
mock_get.assert_called_with(None, str(os_link['instance_id']), mock_get.assert_called_with(None, str(os_link['instance_id']),
os_link['network_id'],
os_link['ip']) os_link['ip'])
@mock.patch.object(network_link_api.Controller, "_get_interface_from_id") @mock.patch.object(network_link_api.Controller, "_get_interface_from_id")
@ -173,13 +172,13 @@ class TestNetworkLinkController(base.TestController):
server_id = uuid.uuid4().hex server_id = uuid.uuid4().hex
net_id = uuid.uuid4().hex net_id = uuid.uuid4().hex
server_addr = "1.1.1.1" server_addr = "1.1.1.1"
link_id = "%s_%s_%s" % (server_id, net_id, server_addr) link_id = "%s_%s" % (server_id, server_addr)
mock_get_server.return_value = fake_nets.fake_build_link( mock_get_server.return_value = fake_nets.fake_build_link(
net_id, server_id, server_addr net_id, server_id, server_addr
) )
ret = self.controller.show(None, link_id) ret = self.controller.show(None, link_id)
self.assertIsInstance(ret, os_network.OSNetworkInterface) self.assertIsInstance(ret, os_network.OSNetworkInterface)
mock_get_server.assert_called_with(None, server_id, net_id, mock_get_server.assert_called_with(None, server_id,
server_addr) server_addr)
def test_get_network_link_resources_fixed(self): def test_get_network_link_resources_fixed(self):
@ -228,7 +227,8 @@ class TestNetworkLinkController(base.TestController):
ret = network_link_api._get_network_link_resources(None) ret = network_link_api._get_network_link_resources(None)
self.assertEqual(ret.__len__(), 0) self.assertEqual(ret.__len__(), 0)
@mock.patch.object(helpers.OpenStackHelper, "assign_floating_ip") @mock.patch.object(helpers.OpenStackHelper,
"assign_floating_ip_deprecated")
@mock.patch("ooi.api.helpers.get_id_with_kind") @mock.patch("ooi.api.helpers.get_id_with_kind")
def test_create_public(self, mock_get_id, mock_assign): def test_create_public(self, mock_get_id, mock_assign):
server_id = uuid.uuid4().hex server_id = uuid.uuid4().hex
@ -243,7 +243,7 @@ class TestNetworkLinkController(base.TestController):
mock_assign.return_value = fake_nets.fake_build_link( mock_assign.return_value = fake_nets.fake_build_link(
net_id, server_id, ip net_id, server_id, ip
) )
mock_get_id.side_effect = [('', net_id), ('', server_id)] mock_get_id.side_effect = [('', server_id), ('', net_id)]
ret = self.controller.create(req) ret = self.controller.create(req)
self.assertIsNotNone(ret) self.assertIsNotNone(ret)
link = ret.resources.pop() link = ret.resources.pop()
@ -254,12 +254,39 @@ class TestNetworkLinkController(base.TestController):
self.assertEqual(server_id, link.source.id) self.assertEqual(server_id, link.source.id)
mock_assign.assert_called_with(mock.ANY, net_id, server_id, None) mock_assign.assert_called_with(mock.ANY, net_id, server_id, None)
@mock.patch.object(helpers.OpenStackHelper, "assign_floating_ip")
@mock.patch("ooi.api.helpers.get_id_with_kind")
def test_create_ipreservation(self, mock_get_id, mock_assign):
server_id = uuid.uuid4().hex
net_id = "foo/ipreservation/%s" % uuid.uuid4().hex
ip = '8.0.0.0'
parameters = {
"occi.core.target": net_id,
"occi.core.source": server_id,
}
categories = {network_link.NetworkInterface.kind}
req = fake_nets.create_req_test_occi(parameters, categories)
mock_assign.return_value = fake_nets.fake_build_link(
net_id, server_id, ip, public_ip=True
)
mock_get_id.side_effect = [('', server_id), ('', net_id)]
ret = self.controller.create(req)
self.assertIsNotNone(ret)
link = ret.resources.pop()
self.assertIsInstance(link, os_network.OSNetworkInterface)
self.assertIsInstance(link.source, compute.ComputeResource)
self.assertIsInstance(link.target, network.NetworkResource)
self.assertIsInstance(link.target, ip_reservation.IPReservation)
self.assertEqual(net_id, link.target.id)
self.assertEqual(server_id, link.source.id)
mock_assign.assert_called_with(mock.ANY, net_id, server_id)
@mock.patch.object(helpers.OpenStackHelper, "create_port") @mock.patch.object(helpers.OpenStackHelper, "create_port")
@mock.patch("ooi.api.helpers.get_id_with_kind") @mock.patch("ooi.api.helpers.get_id_with_kind")
def test_create_fixed(self, mock_get_id, mock_cre_port): def test_create_fixed(self, mock_get_id, mock_cre_port):
server_id = uuid.uuid4().hex server_id = uuid.uuid4().hex
net_id = uuid.uuid4().hex net_id = uuid.uuid4().hex
mock_get_id.side_effect = [('', net_id), ('', server_id)] mock_get_id.side_effect = [('', server_id), ('', net_id)]
ip = '8.0.0.0' ip = '8.0.0.0'
parameters = { parameters = {
"occi.core.target": net_id, "occi.core.target": net_id,
@ -327,7 +354,7 @@ class TestNetworkLinkController(base.TestController):
mock_validator.validate.return_value = True mock_validator.validate.return_value = True
mock_allocate.return_value = ip mock_allocate.return_value = ip
mock_associate.return_value = None mock_associate.return_value = None
mock_get_id.side_effect = [('', net_id), ('', server_id)] mock_get_id.side_effect = [('', server_id), ('', net_id)]
ret = self.controller.create(req, None) ret = self.controller.create(req, None)
link = ret.resources.pop() link = ret.resources.pop()
@ -368,7 +395,7 @@ class TestNetworkLinkController(base.TestController):
mock_validator.validate.return_value = True mock_validator.validate.return_value = True
mock_allocate.return_value = ip mock_allocate.return_value = ip
mock_associate.return_value = None mock_associate.return_value = None
mock_get_id.side_effect = [('', net_id), ('', server_id)] mock_get_id.side_effect = [('', server_id), ('', net_id)]
ret = self.controller.create(req, None) ret = self.controller.create(req, None)
link = ret.resources.pop() link = ret.resources.pop()

View File

@ -21,6 +21,7 @@ from ooi.occi.core import link
from ooi.occi.core import resource from ooi.occi.core import resource
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import contextualization from ooi.occi.infrastructure import contextualization
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import network_link from ooi.occi.infrastructure import network_link
from ooi.occi.infrastructure import storage from ooi.occi.infrastructure import storage
@ -65,6 +66,7 @@ class TestQueryController(base.TestController):
storage_link.StorageLink.kind, storage_link.StorageLink.kind,
network.NetworkResource.kind, network.NetworkResource.kind,
network_link.NetworkInterface.kind, network_link.NetworkInterface.kind,
ip_reservation.IPReservation.kind,
] ]
expected_mixins = [ expected_mixins = [
@ -133,6 +135,7 @@ class TestQueryController(base.TestController):
storage_link.StorageLink.kind, storage_link.StorageLink.kind,
network.NetworkResource.kind, network.NetworkResource.kind,
network_link.NetworkInterface.kind, network_link.NetworkInterface.kind,
ip_reservation.IPReservation.kind,
] ]
expected_mixins = [ expected_mixins = [

View File

@ -19,6 +19,7 @@ from ooi.occi.core import mixin
from ooi.occi.core import resource from ooi.occi.core import resource
from ooi.occi.infrastructure import compute from ooi.occi.infrastructure import compute
from ooi.occi.infrastructure import contextualization from ooi.occi.infrastructure import contextualization
from ooi.occi.infrastructure import ip_reservation
from ooi.occi.infrastructure import network from ooi.occi.infrastructure import network
from ooi.occi.infrastructure import network_link from ooi.occi.infrastructure import network_link
from ooi.occi.infrastructure import securitygroup from ooi.occi.infrastructure import securitygroup
@ -439,3 +440,45 @@ class TestOCCISecurityGroupLink(base.TestCase):
id=uuid.uuid4().hex) id=uuid.uuid4().hex)
l = securitygroup_link.SecurityGroupLink(c, s, state="foobar") l = securitygroup_link.SecurityGroupLink(c, s, state="foobar")
self.assertEqual("foobar", l.state) self.assertEqual("foobar", l.state)
class TestOCCIIPReservation(base.TestCase):
def test_ipreservation_class(self):
ir = ip_reservation.IPReservation
self.assertIn(network.up, ir.actions)
self.assertIn(network.down, ir.actions)
self.assertIn("occi.ipreservation.address", ir.attributes)
self.assertIn("occi.ipreservation.used", ir.attributes)
self.assertIn("occi.ipreservation.state", ir.attributes)
self.assertEqual(network.NetworkResource.kind, ir.kind.parent)
self.assertEqual(ir.kind.location, "ipreservation/")
def test_ip_reservation(self):
id = uuid.uuid4().hex
ir = ip_reservation.IPReservation("foo",
address="xx",
id=id)
self.assertEqual("foo", ir.title)
self.assertEqual(id, ir.id)
self.assertEqual("xx", ir.address)
self.assertEqual(False, ir.used)
self.assertIsNone(ir.state)
def test_setters(self):
ir = ip_reservation.IPReservation("foo", address="xx")
ir.address = "zzz"
self.assertEqual(
"zzz",
ir.attributes["occi.ipreservation.address"].value)
def test_getters(self):
id_ip = uuid.uuid4().hex
ir = ip_reservation.IPReservation("foo",
address="xx",
state="active",
used=True,
id=id_ip)
self.assertEqual("active", ir.state)
self.assertEqual("xx", ir.address)
self.assertEqual(True, ir.used)
self.assertEqual(id_ip, ir.id)

View File

@ -118,7 +118,7 @@ class TestOSNetworkInterface(base.TestCase):
id=uuid.uuid4().hex) id=uuid.uuid4().hex)
i = os_network.OSNetworkInterface(c, n, "00:01:02:03:04:05", i = os_network.OSNetworkInterface(c, n, "00:01:02:03:04:05",
"127.0.0.1", pool="foo") "127.0.0.1", pool="foo")
self.assertEqual('_'.join([c.id, n.id, "127.0.0.1"]), i.id) self.assertEqual('_'.join([c.id, "127.0.0.1"]), i.id)
self.assertEqual(i.address, "127.0.0.1") self.assertEqual(i.address, "127.0.0.1")
self.assertEqual(i.interface, "eth0") self.assertEqual(i.interface, "eth0")
self.assertEqual(i.mac, "00:01:02:03:04:05") self.assertEqual(i.mac, "00:01:02:03:04:05")

View File

@ -20,6 +20,7 @@ import routes.middleware
import webob.dec import webob.dec
import ooi.api.compute import ooi.api.compute
import ooi.api.ip_reservation
import ooi.api.network import ooi.api.network
import ooi.api.network_link import ooi.api.network_link
from ooi.api import query from ooi.api import query
@ -257,6 +258,11 @@ class OCCIMiddleware(object):
self._setup_resource_routes("network", self._setup_resource_routes("network",
self.resources["network"]) self.resources["network"])
self.resources["ipreservation"] = self._create_resource(
ooi.api.ip_reservation.Controller)
self._setup_resource_routes("ipreservation",
self.resources["ipreservation"])
@webob.dec.wsgify(RequestClass=Request) @webob.dec.wsgify(RequestClass=Request)
def __call__(self, req): def __call__(self, req):
response = self.process_request(req) response = self.process_request(req)