Adds API for bulk creation/deletion of floating IPs
This adds an extension that provides a REST API for the bulk creation, deletion and listing of floating IPs. The interface is accessed via /v2/{tenant_id}/os-floating-ips-bulk This forms part of the work to provide APIs for functionality currently implemented by nova-manage that needs direct db access so nova-manage can eventually be removed Implements: blueprint apis-for-nova-manage DocImpact Change-Id: I621e2b070a896f7230cdf3f26f78ded85e72cf16
This commit is contained in:
parent
9dfb4b420f
commit
576ada198a
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_create" :
|
||||||
|
{
|
||||||
|
"ip_range": "192.168.1.0/24",
|
||||||
|
"pool": "nova",
|
||||||
|
"interface": "eth0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_create>
|
||||||
|
<ip_range>192.168.1.0/24</ip_range>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
</floating_ips_bulk_create>
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_create": {
|
||||||
|
"interface": "eth0",
|
||||||
|
"ip_range": "192.168.1.0/24",
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_create>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<ip_range>192.168.1.0/24</ip_range>
|
||||||
|
<pool>nova</pool>
|
||||||
|
</floating_ips_bulk_create>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"ip_range": "192.168.1.0/24"
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<ip_range>192.168.1.0/24</ip_range>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_delete": "192.168.1.0/24"
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_delete>192.168.1.0/24</floating_ips_bulk_delete>
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"floating_ip_info": [
|
||||||
|
{
|
||||||
|
"address": "10.10.10.3",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ip_info>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.3</address>
|
||||||
|
</item>
|
||||||
|
</floating_ip_info>
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"floating_ip_info": [
|
||||||
|
{
|
||||||
|
"address": "10.10.10.1",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "10.10.10.2",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "10.10.10.3",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ip_info>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.1</address>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.2</address>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.3</address>
|
||||||
|
</item>
|
||||||
|
</floating_ip_info>
|
@ -47,6 +47,7 @@
|
|||||||
"compute_extension:floating_ip_dns": "",
|
"compute_extension:floating_ip_dns": "",
|
||||||
"compute_extension:floating_ip_pools": "",
|
"compute_extension:floating_ip_pools": "",
|
||||||
"compute_extension:floating_ips": "",
|
"compute_extension:floating_ips": "",
|
||||||
|
"compute_extension:floating_ips_bulk": "rule:admin_api",
|
||||||
"compute_extension:fping": "",
|
"compute_extension:fping": "",
|
||||||
"compute_extension:fping:all_tenants": "rule:admin_api",
|
"compute_extension:fping:all_tenants": "rule:admin_api",
|
||||||
"compute_extension:hosts": "rule:admin_api",
|
"compute_extension:hosts": "rule:admin_api",
|
||||||
|
176
nova/api/openstack/compute/contrib/floating_ips_bulk.py
Normal file
176
nova/api/openstack/compute/contrib/floating_ips_bulk.py
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 IBM
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 netaddr
|
||||||
|
import urllib
|
||||||
|
import webob.exc
|
||||||
|
|
||||||
|
from nova.api.openstack import extensions
|
||||||
|
from nova.api.openstack import wsgi
|
||||||
|
from nova.api.openstack import xmlutil
|
||||||
|
from nova import db
|
||||||
|
from nova import exception
|
||||||
|
from nova.openstack.common import cfg
|
||||||
|
from nova.openstack.common import log as logging
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.import_opt('default_floating_pool', 'nova.network.manager')
|
||||||
|
CONF.import_opt('public_interface', 'nova.network.linux_net')
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
authorize = extensions.extension_authorizer('compute', 'floating_ips_bulk')
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingIPBulkController(object):
|
||||||
|
|
||||||
|
def index(self, req):
|
||||||
|
"""Return a list of all floating ips"""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
authorize(context)
|
||||||
|
|
||||||
|
return self._get_floating_ip_info(context)
|
||||||
|
|
||||||
|
def show(self, req, id):
|
||||||
|
"""Return a list of all floating ips for a given host"""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
authorize(context)
|
||||||
|
|
||||||
|
return self._get_floating_ip_info(context, id)
|
||||||
|
|
||||||
|
def _get_floating_ip_info(self, context, host=None):
|
||||||
|
floating_ip_info = {"floating_ip_info": []}
|
||||||
|
|
||||||
|
try:
|
||||||
|
if host is None:
|
||||||
|
floating_ips = db.floating_ip_get_all(context)
|
||||||
|
else:
|
||||||
|
floating_ips = db.floating_ip_get_all_by_host(context, host)
|
||||||
|
except exception.NoFloatingIpsDefined:
|
||||||
|
return floating_ip_info
|
||||||
|
|
||||||
|
for floating_ip in floating_ips:
|
||||||
|
instance_uuid = None
|
||||||
|
if floating_ip['fixed_ip_id']:
|
||||||
|
fixed_ip = db.fixed_ip_get(context, floating_ip['fixed_ip_id'])
|
||||||
|
instance_uuid = fixed_ip['instance_uuid']
|
||||||
|
|
||||||
|
result = {'address': floating_ip['address'],
|
||||||
|
'pool': floating_ip['pool'],
|
||||||
|
'interface': floating_ip['interface'],
|
||||||
|
'project_id': floating_ip['project_id'],
|
||||||
|
'instance_uuid': instance_uuid}
|
||||||
|
floating_ip_info['floating_ip_info'].append(result)
|
||||||
|
|
||||||
|
return floating_ip_info
|
||||||
|
|
||||||
|
def create(self, req, body):
|
||||||
|
"""Bulk create floating ips"""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
authorize(context)
|
||||||
|
|
||||||
|
if not 'floating_ips_bulk_create' in body:
|
||||||
|
raise webob.exc.HTTPUnprocessableEntity()
|
||||||
|
params = body['floating_ips_bulk_create']
|
||||||
|
|
||||||
|
LOG.debug(params)
|
||||||
|
|
||||||
|
if not 'ip_range' in params:
|
||||||
|
raise webob.exc.HTTPUnprocessableEntity()
|
||||||
|
ip_range = params['ip_range']
|
||||||
|
|
||||||
|
pool = params.get('pool', CONF.default_floating_pool)
|
||||||
|
interface = params.get('interface', CONF.public_interface)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ips = ({'address': str(address),
|
||||||
|
'pool': pool,
|
||||||
|
'interface': interface}
|
||||||
|
for address in self._address_to_hosts(ip_range))
|
||||||
|
except exception.InvalidInput as exc:
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=str(exc))
|
||||||
|
|
||||||
|
try:
|
||||||
|
db.floating_ip_bulk_create(context, ips)
|
||||||
|
except exception.FloatingIpExists as exc:
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=str(exc))
|
||||||
|
|
||||||
|
return {"floating_ips_bulk_create": {"ip_range": ip_range,
|
||||||
|
"pool": pool,
|
||||||
|
"interface": interface}}
|
||||||
|
|
||||||
|
def update(self, req, id, body):
|
||||||
|
"""Bulk delete floating IPs"""
|
||||||
|
context = req.environ['nova.context']
|
||||||
|
authorize(context)
|
||||||
|
|
||||||
|
if id != "delete":
|
||||||
|
raise webob.exc.HTTPNotFound("Unknown action")
|
||||||
|
|
||||||
|
try:
|
||||||
|
ip_range = body['ip_range']
|
||||||
|
except (TypeError, KeyError):
|
||||||
|
raise webob.exc.HTTPUnprocessableEntity()
|
||||||
|
|
||||||
|
try:
|
||||||
|
ips = ({'address': str(address)}
|
||||||
|
for address in self._address_to_hosts(ip_range))
|
||||||
|
except exception.InvalidInput as exc:
|
||||||
|
raise webob.exc.HTTPBadRequest(explanation=str(exc))
|
||||||
|
db.floating_ip_bulk_destroy(context, ips)
|
||||||
|
|
||||||
|
return {"floating_ips_bulk_delete": ip_range}
|
||||||
|
|
||||||
|
def _address_to_hosts(self, addresses):
|
||||||
|
"""
|
||||||
|
Iterate over hosts within an address range.
|
||||||
|
|
||||||
|
If an explicit range specifier is missing, the parameter is
|
||||||
|
interpreted as a specific individual address.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return [netaddr.IPAddress(addresses)]
|
||||||
|
except ValueError:
|
||||||
|
net = netaddr.IPNetwork(addresses)
|
||||||
|
if net.size < 4:
|
||||||
|
reason = _("/%s should be specified as single address(es) "
|
||||||
|
"not in cidr format") % net.prefixlen
|
||||||
|
raise exception.InvalidInput(reason=reason)
|
||||||
|
else:
|
||||||
|
return net.iter_hosts()
|
||||||
|
except netaddr.AddrFormatError as exc:
|
||||||
|
raise exception.InvalidInput(reason=str(exc))
|
||||||
|
|
||||||
|
|
||||||
|
class Floating_ips_bulk(extensions.ExtensionDescriptor):
|
||||||
|
"""Bulk handling of Floating IPs"""
|
||||||
|
|
||||||
|
name = "FloatingIpsBulk"
|
||||||
|
alias = "os-floating-ips-bulk"
|
||||||
|
namespace = ("http://docs.openstack.org/compute/ext/"
|
||||||
|
"floating_ips_bulk/api/v2")
|
||||||
|
updated = "2012-10-29T13:25:27-06:00"
|
||||||
|
|
||||||
|
def __init__(self, ext_mgr):
|
||||||
|
ext_mgr.register(self)
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
resources = []
|
||||||
|
resource = extensions.ResourceExtension('os-floating-ips-bulk',
|
||||||
|
FloatingIPBulkController())
|
||||||
|
resources.append(resource)
|
||||||
|
return resources
|
@ -0,0 +1,127 @@
|
|||||||
|
# Copyright 2012 IBM
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 netaddr
|
||||||
|
import webob
|
||||||
|
|
||||||
|
from nova.api.openstack.compute.contrib import floating_ips_bulk
|
||||||
|
from nova import context
|
||||||
|
from nova import db
|
||||||
|
from nova import exception
|
||||||
|
from nova.openstack.common import cfg
|
||||||
|
from nova import test
|
||||||
|
from nova.tests.api.openstack import fakes
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingIPBulk(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FloatingIPBulk, self).setUp()
|
||||||
|
|
||||||
|
self.context = context.get_admin_context()
|
||||||
|
self.controller = floating_ips_bulk.FloatingIPBulkController()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(FloatingIPBulk, self).tearDown()
|
||||||
|
|
||||||
|
def _setup_floating_ips(self, ip_range):
|
||||||
|
body = {'floating_ips_bulk_create': {'ip_range': ip_range}}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk')
|
||||||
|
res_dict = self.controller.create(req, body)
|
||||||
|
response = {"floating_ips_bulk_create": {
|
||||||
|
'ip_range': ip_range,
|
||||||
|
'pool': CONF.default_floating_pool,
|
||||||
|
'interface': CONF.public_interface}}
|
||||||
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
|
def test_create_ips(self):
|
||||||
|
ip_range = '192.168.1.0/24'
|
||||||
|
self._setup_floating_ips(ip_range)
|
||||||
|
|
||||||
|
def test_create_ips_pool(self):
|
||||||
|
ip_range = '10.0.1.0/20'
|
||||||
|
pool = 'a new pool'
|
||||||
|
body = {'floating_ips_bulk_create':
|
||||||
|
{'ip_range': ip_range,
|
||||||
|
'pool': pool}}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk')
|
||||||
|
res_dict = self.controller.create(req, body)
|
||||||
|
response = {"floating_ips_bulk_create": {
|
||||||
|
'ip_range': ip_range,
|
||||||
|
'pool': pool,
|
||||||
|
'interface': CONF.public_interface}}
|
||||||
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
|
def test_list_ips(self):
|
||||||
|
ip_range = '192.168.1.1/28'
|
||||||
|
self._setup_floating_ips(ip_range)
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk',
|
||||||
|
use_admin_context=True)
|
||||||
|
res_dict = self.controller.index(req)
|
||||||
|
|
||||||
|
ip_info = [{'address': str(ip_addr),
|
||||||
|
'pool': CONF.default_floating_pool,
|
||||||
|
'interface': CONF.public_interface,
|
||||||
|
'project_id': None,
|
||||||
|
'instance_uuid': None}
|
||||||
|
for ip_addr in netaddr.IPNetwork(ip_range).iter_hosts()]
|
||||||
|
response = {'floating_ip_info': ip_info}
|
||||||
|
|
||||||
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
|
def test_delete_ips(self):
|
||||||
|
ip_range = '192.168.1.0/20'
|
||||||
|
self._setup_floating_ips(ip_range)
|
||||||
|
|
||||||
|
body = {'ip_range': ip_range}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/delete')
|
||||||
|
res_dict = self.controller.update(req, "delete", body)
|
||||||
|
|
||||||
|
response = {"floating_ips_bulk_delete": ip_range}
|
||||||
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
|
# Check that the IPs are actually deleted
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk',
|
||||||
|
use_admin_context=True)
|
||||||
|
res_dict = self.controller.index(req)
|
||||||
|
response = {'floating_ip_info': []}
|
||||||
|
self.assertEqual(res_dict, response)
|
||||||
|
|
||||||
|
def test_create_duplicate_fail(self):
|
||||||
|
ip_range = '192.168.1.0/20'
|
||||||
|
self._setup_floating_ips(ip_range)
|
||||||
|
|
||||||
|
ip_range = '192.168.1.0/28'
|
||||||
|
body = {'floating_ips_bulk_create': {'ip_range': ip_range}}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk')
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
|
req, body)
|
||||||
|
|
||||||
|
def test_create_bad_cidr_fail(self):
|
||||||
|
# netaddr can't handle /32 or 31 cidrs
|
||||||
|
ip_range = '192.168.1.1/32'
|
||||||
|
body = {'floating_ips_bulk_create': {'ip_range': ip_range}}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk')
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
|
req, body)
|
||||||
|
|
||||||
|
def test_create_invalid_cidr_fail(self):
|
||||||
|
ip_range = 'not a cidr'
|
||||||
|
body = {'floating_ips_bulk_create': {'ip_range': ip_range}}
|
||||||
|
req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk')
|
||||||
|
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
|
||||||
|
req, body)
|
@ -178,6 +178,7 @@ class ExtensionControllerTest(ExtensionTestCase):
|
|||||||
"FloatingIps",
|
"FloatingIps",
|
||||||
"FloatingIpDns",
|
"FloatingIpDns",
|
||||||
"FloatingIpPools",
|
"FloatingIpPools",
|
||||||
|
"FloatingIpsBulk",
|
||||||
"Fox In Socks",
|
"Fox In Socks",
|
||||||
"Hosts",
|
"Hosts",
|
||||||
"Keypairs",
|
"Keypairs",
|
||||||
|
@ -208,6 +208,14 @@
|
|||||||
"namespace": "http://docs.openstack.org/compute/ext/floating_ips/api/v1.1",
|
"namespace": "http://docs.openstack.org/compute/ext/floating_ips/api/v1.1",
|
||||||
"updated": "%(timestamp)s"
|
"updated": "%(timestamp)s"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"alias": "os-floating-ips-bulk",
|
||||||
|
"description": "%(text)s",
|
||||||
|
"links": [],
|
||||||
|
"name": "FloatingIpsBulk",
|
||||||
|
"namespace": "http://docs.openstack.org/compute/ext/floating_ips_bulk/api/v2",
|
||||||
|
"updated": "%(timestamp)s"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"alias": "os-hosts",
|
"alias": "os-hosts",
|
||||||
"description": "%(text)s",
|
"description": "%(text)s",
|
||||||
|
@ -78,6 +78,9 @@
|
|||||||
<extension alias="os-floating-ips" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/floating_ips/api/v1.1" name="FloatingIps">
|
<extension alias="os-floating-ips" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/floating_ips/api/v1.1" name="FloatingIps">
|
||||||
<description>%(text)s</description>
|
<description>%(text)s</description>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension alias="os-floating-ips-bulk" name="FloatingIpsBulk" namespace="http://docs.openstack.org/compute/ext/floating_ips_bulk/api/v2" updated="2012-10-29T13:25:27-06:00">
|
||||||
|
<description>%(text)s</description>
|
||||||
|
</extension>
|
||||||
<extension alias="os-hosts" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/hosts/api/v1.1" name="Hosts">
|
<extension alias="os-hosts" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/hosts/api/v1.1" name="Hosts">
|
||||||
<description>%(text)s</description>
|
<description>%(text)s</description>
|
||||||
</extension>
|
</extension>
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_create" :
|
||||||
|
{
|
||||||
|
"ip_range": "%(ip_range)s",
|
||||||
|
"pool": "%(pool)s",
|
||||||
|
"interface": "%(interface)s"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_create>
|
||||||
|
<ip_range>%(ip_range)s</ip_range>
|
||||||
|
<pool>%(pool)s</pool>
|
||||||
|
<interface>%(interface)s</interface>
|
||||||
|
</floating_ips_bulk_create>
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_create": {
|
||||||
|
"interface": "eth0",
|
||||||
|
"ip_range": "192.168.1.0/24",
|
||||||
|
"pool": "nova"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_create>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<ip_range>192.168.1.0/24</ip_range>
|
||||||
|
<pool>nova</pool>
|
||||||
|
</floating_ips_bulk_create>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"ip_range": "%(ip_range)s"
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<ip_range>%(ip_range)s</ip_range>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"floating_ips_bulk_delete": "192.168.1.0/24"
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ips_bulk_delete>192.168.1.0/24</floating_ips_bulk_delete>
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"floating_ip_info": [
|
||||||
|
{
|
||||||
|
"address": "10.10.10.3",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ip_info>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.3</address>
|
||||||
|
</item>
|
||||||
|
</floating_ip_info>
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"floating_ip_info": [
|
||||||
|
{
|
||||||
|
"address": "10.10.10.1",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "10.10.10.2",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "10.10.10.3",
|
||||||
|
"instance_uuid": null,
|
||||||
|
"interface": "eth0",
|
||||||
|
"pool": "nova",
|
||||||
|
"project_id": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<floating_ip_info>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.1</address>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.2</address>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<interface>eth0</interface>
|
||||||
|
<instance_uuid>None</instance_uuid>
|
||||||
|
<project_id>None</project_id>
|
||||||
|
<pool>nova</pool>
|
||||||
|
<address>10.10.10.3</address>
|
||||||
|
</item>
|
||||||
|
</floating_ip_info>
|
@ -944,6 +944,80 @@ class FloatingIpsXmlTest(FloatingIpsJsonTest):
|
|||||||
ctype = 'xml'
|
ctype = 'xml'
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingIpsBulkJsonTest(ApiSampleTestBase):
|
||||||
|
extension_name = "nova.api.openstack.compute.contrib." \
|
||||||
|
"floating_ips_bulk.Floating_ips_bulk"
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FloatingIpsBulkJsonTest, self).setUp()
|
||||||
|
pool = CONF.default_floating_pool
|
||||||
|
interface = CONF.public_interface
|
||||||
|
|
||||||
|
self.ip_pool = [
|
||||||
|
{
|
||||||
|
'address': "10.10.10.1",
|
||||||
|
'pool': pool,
|
||||||
|
'interface': interface
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'address': "10.10.10.2",
|
||||||
|
'pool': pool,
|
||||||
|
'interface': interface
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'address': "10.10.10.3",
|
||||||
|
'pool': pool,
|
||||||
|
'interface': interface,
|
||||||
|
'host': "testHost"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
self.compute.db.floating_ip_bulk_create(
|
||||||
|
context.get_admin_context(), self.ip_pool)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.compute.db.floating_ip_bulk_destroy(
|
||||||
|
context.get_admin_context(), self.ip_pool)
|
||||||
|
super(FloatingIpsBulkJsonTest, self).tearDown()
|
||||||
|
|
||||||
|
def test_floating_ips_bulk_list(self):
|
||||||
|
response = self._do_get('os-floating-ips-bulk')
|
||||||
|
self.assertEqual(response.status, 200)
|
||||||
|
subs = self._get_regexes()
|
||||||
|
return self._verify_response('floating-ips-bulk-list-resp', subs,
|
||||||
|
response)
|
||||||
|
|
||||||
|
def test_floating_ips_bulk_list_by_host(self):
|
||||||
|
response = self._do_get('os-floating-ips-bulk/testHost')
|
||||||
|
self.assertEqual(response.status, 200)
|
||||||
|
subs = self._get_regexes()
|
||||||
|
return self._verify_response('floating-ips-bulk-list-by-host-resp',
|
||||||
|
subs, response)
|
||||||
|
|
||||||
|
def test_floating_ips_bulk_create(self):
|
||||||
|
response = self._do_post('os-floating-ips-bulk',
|
||||||
|
'floating-ips-bulk-create-req',
|
||||||
|
{"ip_range": "192.168.1.0/24",
|
||||||
|
"pool": CONF.default_floating_pool,
|
||||||
|
"interface": CONF.public_interface})
|
||||||
|
self.assertEqual(response.status, 200)
|
||||||
|
subs = self._get_regexes()
|
||||||
|
return self._verify_response('floating-ips-bulk-create-resp', subs,
|
||||||
|
response)
|
||||||
|
|
||||||
|
def test_floating_ips_bulk_delete(self):
|
||||||
|
response = self._do_put('os-floating-ips-bulk/delete',
|
||||||
|
'floating-ips-bulk-delete-req',
|
||||||
|
{"ip_range": "192.168.1.0/24"})
|
||||||
|
self.assertEqual(response.status, 200)
|
||||||
|
subs = self._get_regexes()
|
||||||
|
return self._verify_response('floating-ips-bulk-delete-resp', subs,
|
||||||
|
response)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingIpsBulkXmlTest(FloatingIpsBulkJsonTest):
|
||||||
|
ctype = 'xml'
|
||||||
|
|
||||||
|
|
||||||
class KeyPairsSampleJsonTest(ApiSampleTestBase):
|
class KeyPairsSampleJsonTest(ApiSampleTestBase):
|
||||||
extension_name = "nova.api.openstack.compute.contrib.keypairs.Keypairs"
|
extension_name = "nova.api.openstack.compute.contrib.keypairs.Keypairs"
|
||||||
|
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
"compute_extension:floating_ip_dns": "",
|
"compute_extension:floating_ip_dns": "",
|
||||||
"compute_extension:floating_ip_pools": "",
|
"compute_extension:floating_ip_pools": "",
|
||||||
"compute_extension:floating_ips": "",
|
"compute_extension:floating_ips": "",
|
||||||
|
"compute_extension:floating_ips_bulk": "",
|
||||||
"compute_extension:fping": "",
|
"compute_extension:fping": "",
|
||||||
"compute_extension:fping:all_tenants": "is_admin:True",
|
"compute_extension:fping:all_tenants": "is_admin:True",
|
||||||
"compute_extension:hosts": "",
|
"compute_extension:hosts": "",
|
||||||
|
Loading…
Reference in New Issue
Block a user