Add support for floating IP reservation

Change-Id: I7a73a4e7d2026eba2d0a3d6dfe9db42879ff6416
This commit is contained in:
Pierre Riteau 2019-05-30 11:29:04 +01:00
parent 2ea393fb6a
commit ea96686ffb
6 changed files with 285 additions and 1 deletions

View File

@ -33,6 +33,7 @@ import six
from blazarclient import client as blazar_client
from blazarclient import exception
from blazarclient import utils
from blazarclient.v1.shell_commands import floatingips
from blazarclient.v1.shell_commands import hosts
from blazarclient.v1.shell_commands import leases
from blazarclient import version as base_version
@ -47,7 +48,11 @@ COMMANDS_V1 = {
'host-show': hosts.ShowHost,
'host-create': hosts.CreateHost,
'host-update': hosts.UpdateHost,
'host-delete': hosts.DeleteHost
'host-delete': hosts.DeleteHost,
'floatingip-list': floatingips.ListFloatingIPs,
'floatingip-show': floatingips.ShowFloatingIP,
'floatingip-create': floatingips.CreateFloatingIP,
'floatingip-delete': floatingips.DeleteFloatingIP,
}
VERSION = 1

View File

@ -0,0 +1,142 @@
# Copyright (c) 2019 StackHPC Ltd.
#
# 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 argparse
import mock
from blazarclient import shell
from blazarclient import tests
from blazarclient.v1.shell_commands import floatingips
class CreateFloatingIPTest(tests.TestCase):
def setUp(self):
super(CreateFloatingIPTest, self).setUp()
self.create_floatingip = floatingips.CreateFloatingIP(
shell.BlazarShell(), mock.Mock())
def test_args2body(self):
args = argparse.Namespace(
network_id='1e17587e-a7ed-4b82-a17b-4beb32523e28',
floating_ip_address='172.24.4.101',
)
expected = {
'network_id': '1e17587e-a7ed-4b82-a17b-4beb32523e28',
'floating_ip_address': '172.24.4.101',
}
ret = self.create_floatingip.args2body(args)
self.assertDictEqual(ret, expected)
class ListFloatingIPsTest(tests.TestCase):
def create_list_command(self, list_value):
mock_floatingip_manager = mock.Mock()
mock_floatingip_manager.list.return_value = list_value
mock_client = mock.Mock()
mock_client.floatingip = mock_floatingip_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return (floatingips.ListFloatingIPs(blazar_shell, mock.Mock()),
mock_floatingip_manager)
def test_list_floatingips(self):
list_value = [
{'id': '84c4d37e-1f8b-45ce-897b-16ad7f49b0e9'},
{'id': 'f180cf4c-f886-4dd1-8c36-854d17fbefb5'},
]
list_floatingips, floatingip_manager = self.create_list_command(
list_value)
args = argparse.Namespace(sort_by='id', columns=['id'])
expected = [['id'], [('84c4d37e-1f8b-45ce-897b-16ad7f49b0e9',),
('f180cf4c-f886-4dd1-8c36-854d17fbefb5',)]]
ret = list_floatingips.get_data(args)
self.assertEqual(expected[0], ret[0])
self.assertEqual(expected[1], [x for x in ret[1]])
floatingip_manager.list.assert_called_once_with(sort_by='id')
class ShowFloatingIPTest(tests.TestCase):
def create_show_command(self, list_value, get_value):
mock_floatingip_manager = mock.Mock()
mock_floatingip_manager.list.return_value = list_value
mock_floatingip_manager.get.return_value = get_value
mock_client = mock.Mock()
mock_client.floatingip = mock_floatingip_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return (floatingips.ShowFloatingIP(blazar_shell, mock.Mock()),
mock_floatingip_manager)
def test_show_floatingip(self):
list_value = [
{'id': '84c4d37e-1f8b-45ce-897b-16ad7f49b0e9'},
{'id': 'f180cf4c-f886-4dd1-8c36-854d17fbefb5'},
]
get_value = {
'id': '84c4d37e-1f8b-45ce-897b-16ad7f49b0e9'}
show_floatingip, floatingip_manager = self.create_show_command(
list_value, get_value)
args = argparse.Namespace(id='84c4d37e-1f8b-45ce-897b-16ad7f49b0e9')
expected = [('id',), ('84c4d37e-1f8b-45ce-897b-16ad7f49b0e9',)]
ret = show_floatingip.get_data(args)
self.assertEqual(ret, expected)
floatingip_manager.get.assert_called_once_with(
'84c4d37e-1f8b-45ce-897b-16ad7f49b0e9')
class DeleteFloatingIPTest(tests.TestCase):
def create_delete_command(self, list_value):
mock_floatingip_manager = mock.Mock()
mock_floatingip_manager.list.return_value = list_value
mock_client = mock.Mock()
mock_client.floatingip = mock_floatingip_manager
blazar_shell = shell.BlazarShell()
blazar_shell.client = mock_client
return (floatingips.DeleteFloatingIP(blazar_shell, mock.Mock()),
mock_floatingip_manager)
def test_delete_floatingip(self):
list_value = [
{'id': '84c4d37e-1f8b-45ce-897b-16ad7f49b0e9'},
{'id': 'f180cf4c-f886-4dd1-8c36-854d17fbefb5'},
]
delete_floatingip, floatingip_manager = self.create_delete_command(
list_value)
args = argparse.Namespace(id='84c4d37e-1f8b-45ce-897b-16ad7f49b0e9')
delete_floatingip.run(args)
floatingip_manager.delete.assert_called_once_with(
'84c4d37e-1f8b-45ce-897b-16ad7f49b0e9')

View File

@ -15,6 +15,7 @@
import logging
from blazarclient.v1 import floatingips
from blazarclient.v1 import hosts
from blazarclient.v1 import leases
@ -55,3 +56,9 @@ class Client(object):
session=self.session,
version=self.version,
**kwargs)
self.floatingip = floatingips.FloatingIPClientManager(
blazar_url=self.blazar_url,
auth_token=self.auth_token,
session=self.session,
version=self.version,
**kwargs)

View File

@ -0,0 +1,47 @@
# Copyright (c) 2019 StackHPC Ltd.
#
# 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 blazarclient import base
class FloatingIPClientManager(base.BaseClientManager):
"""Manager for floating IP requests."""
def create(self, network_id, floating_ip_address, **kwargs):
"""Creates a floating IP from values passed."""
values = {'floating_network_id': network_id,
'floating_ip_address': floating_ip_address}
values.update(**kwargs)
resp, body = self.request_manager.post('/floatingips', body=values)
return body['floatingip']
def get(self, floatingip_id):
"""Show floating IP details."""
resp, body = self.request_manager.get(
'/floatingips/%s' % floatingip_id)
return body['floatingip']
def delete(self, floatingip_id):
"""Deletes floating IP with specified ID."""
resp, body = self.request_manager.delete(
'/floatingips/%s' % floatingip_id)
def list(self, sort_by=None):
"""List all floating IPs."""
resp, body = self.request_manager.get('/floatingips')
floatingips = body['floatingips']
if sort_by:
floatingips = sorted(floatingips, key=lambda l: l[sort_by])
return floatingips

View File

@ -0,0 +1,76 @@
# Copyright (c) 2019 StackHPC Ltd.
#
# 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 logging
from blazarclient import command
class ListFloatingIPs(command.ListCommand):
"""Print a list of floating IPs."""
resource = 'floatingip'
log = logging.getLogger(__name__ + '.ListFloatingIPs')
list_columns = ['id', 'floating_ip_address', 'floating_network_id']
def get_parser(self, prog_name):
parser = super(ListFloatingIPs, self).get_parser(prog_name)
parser.add_argument(
'--sort-by', metavar="<floatingip_column>",
help='column name used to sort result',
default='id'
)
return parser
class ShowFloatingIP(command.ShowCommand):
"""Show floating IP details."""
resource = 'floatingip'
allow_names = False
json_indent = 4
log = logging.getLogger(__name__ + '.ShowFloatingIP')
class CreateFloatingIP(command.CreateCommand):
"""Create a floating IP."""
resource = 'floatingip'
json_indent = 4
log = logging.getLogger(__name__ + '.CreateFloatingIP')
def get_parser(self, prog_name):
parser = super(CreateFloatingIP, self).get_parser(prog_name)
parser.add_argument(
'network_id', metavar='NETWORK_ID',
help='External network ID to which the floating IP belongs'
)
parser.add_argument(
'floating_ip_address', metavar='FLOATING_IP_ADDRESS',
help='Floating IP address to add to Blazar'
)
return parser
def args2body(self, parsed_args):
params = {}
if parsed_args.network_id:
params['network_id'] = parsed_args.network_id
if parsed_args.floating_ip_address:
params['floating_ip_address'] = parsed_args.floating_ip_address
return params
class DeleteFloatingIP(command.DeleteCommand):
"""Delete a floating IP."""
resource = 'floatingip'
allow_names = False
log = logging.getLogger(__name__ + '.DeleteFloatingIP')

View File

@ -33,6 +33,11 @@ CREATE_RESERVATION_KEYS = {
"before_end": None,
"resource_type": 'physical:host'
},
"virtual:floatingip": {
"amount": 1,
"required_floatingips": [],
"resource_type": 'virtual:floatingip'
},
"virtual:instance": {
"vcpus": "",
"memory_mb": "",
@ -275,6 +280,8 @@ class CreateLease(command.CreateCommand):
defaults = CREATE_RESERVATION_KEYS['physical:host']
elif "virtual:instance" in res_str:
defaults = CREATE_RESERVATION_KEYS['virtual:instance']
elif "virtual:floatingip" in res_str:
defaults = CREATE_RESERVATION_KEYS['virtual:floatingip']
else:
defaults = CREATE_RESERVATION_KEYS['others']