Support listing availability zones
Zun has introduced an API endpoint for listing availability zones (https://review.openstack.org/#/c/564670/). This patch is the client side implementation. In particular, this patch does the following: * Python API for listing availability zones * A CLI command for listing availability zones (i.e. zun availability-zone-list) * An OSC command for doing the same (i.e. openstack appcontainer availability zone list) Related-Bug: #1766395 Change-Id: I6c0512816277a63bbf444d0775121bb5d964a36a
This commit is contained in:
@@ -30,6 +30,7 @@ openstack.cli.extension =
|
|||||||
container = zunclient.osc.plugin
|
container = zunclient.osc.plugin
|
||||||
|
|
||||||
openstack.container.v1 =
|
openstack.container.v1 =
|
||||||
|
appcontainer_availability_zone_list = zunclient.osc.v1.availability_zones:ListAvailabilityZone
|
||||||
appcontainer_service_list = zunclient.osc.v1.services:ListService
|
appcontainer_service_list = zunclient.osc.v1.services:ListService
|
||||||
appcontainer_service_delete = zunclient.osc.v1.services:DeleteService
|
appcontainer_service_delete = zunclient.osc.v1.services:DeleteService
|
||||||
appcontainer_service_enable = zunclient.osc.v1.services:EnableService
|
appcontainer_service_enable = zunclient.osc.v1.services:EnableService
|
||||||
|
|||||||
@@ -189,6 +189,13 @@ def list_containers(containers):
|
|||||||
sortby_index=None)
|
sortby_index=None)
|
||||||
|
|
||||||
|
|
||||||
|
def list_availability_zones(zones):
|
||||||
|
columns = ('availability_zone',)
|
||||||
|
utils.print_list(zones, columns,
|
||||||
|
{'versions': print_list_field('versions')},
|
||||||
|
sortby_index=None)
|
||||||
|
|
||||||
|
|
||||||
def parse_command(command):
|
def parse_command(command):
|
||||||
output = []
|
output = []
|
||||||
if command:
|
if command:
|
||||||
|
|||||||
38
zunclient/osc/v1/availability_zones.py
Normal file
38
zunclient/osc/v1/availability_zones.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# 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 oslo_log import log as logging
|
||||||
|
|
||||||
|
from osc_lib.command import command
|
||||||
|
from osc_lib import utils
|
||||||
|
|
||||||
|
|
||||||
|
def _get_client(obj, parsed_args):
|
||||||
|
obj.log.debug("take_action(%s)" % parsed_args)
|
||||||
|
return obj.app.client_manager.container
|
||||||
|
|
||||||
|
|
||||||
|
class ListAvailabilityZone(command.Lister):
|
||||||
|
"""List availability zones"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".ListAvailabilityZones")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ListAvailabilityZone, self).get_parser(prog_name)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
client = _get_client(self, parsed_args)
|
||||||
|
zones = client.availability_zones.list()
|
||||||
|
columns = ('availability_zone',)
|
||||||
|
return (columns, (utils.get_item_properties(zone, columns)
|
||||||
|
for zone in zones))
|
||||||
46
zunclient/tests/unit/v1/test_availability_zones.py
Normal file
46
zunclient/tests/unit/v1/test_availability_zones.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# 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 testtools
|
||||||
|
from testtools import matchers
|
||||||
|
from zunclient.tests.unit import utils
|
||||||
|
from zunclient.v1 import availability_zones as az
|
||||||
|
|
||||||
|
AZ1 = {'availability_zone': 'fake-az-1'}
|
||||||
|
|
||||||
|
AZ2 = {'availability_zone': 'fake-az-2'}
|
||||||
|
|
||||||
|
fake_responses = {
|
||||||
|
'/v1/availability_zones':
|
||||||
|
{
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{'availability_zones': [AZ1, AZ2]},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AZManagerTest(testtools.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(AZManagerTest, self).setUp()
|
||||||
|
self.api = utils.FakeAPI(fake_responses)
|
||||||
|
self.mgr = az.AvailabilityZoneManager(self.api)
|
||||||
|
|
||||||
|
def test_availability_zones_list(self):
|
||||||
|
zones = self.mgr.list()
|
||||||
|
expect = [
|
||||||
|
('GET', '/v1/availability_zones', {}, None),
|
||||||
|
]
|
||||||
|
self.assertEqual(expect, self.api.calls)
|
||||||
|
self.assertThat(zones, matchers.HasLength(2))
|
||||||
29
zunclient/tests/unit/v1/test_availability_zones_shell.py
Normal file
29
zunclient/tests/unit/v1/test_availability_zones_shell.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# 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 zunclient.tests.unit.v1 import shell_test_base
|
||||||
|
|
||||||
|
|
||||||
|
class ShellTest(shell_test_base.TestCommandLineArgument):
|
||||||
|
|
||||||
|
@mock.patch('zunclient.v1.availability_zones.AvailabilityZoneManager.list')
|
||||||
|
def test_zun_service_list_success(self, mock_list):
|
||||||
|
self._test_arg_success('availability-zone-list')
|
||||||
|
self.assertTrue(mock_list.called)
|
||||||
|
|
||||||
|
@mock.patch('zunclient.v1.availability_zones.AvailabilityZoneManager.list')
|
||||||
|
def test_zun_service_list_failure(self, mock_list):
|
||||||
|
self._test_arg_failure('availability-zone-list --wrong',
|
||||||
|
self._unrecognized_arg_error)
|
||||||
|
self.assertFalse(mock_list.called)
|
||||||
31
zunclient/v1/availability_zones.py
Normal file
31
zunclient/v1/availability_zones.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Copyright 2014 NEC Corporation. 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.
|
||||||
|
|
||||||
|
from zunclient.common import base
|
||||||
|
|
||||||
|
|
||||||
|
class AvailabilityZone(base.Resource):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<AvailabilityZone %s>" % self._info
|
||||||
|
|
||||||
|
|
||||||
|
class AvailabilityZoneManager(base.Manager):
|
||||||
|
resource_class = AvailabilityZone
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _path():
|
||||||
|
return '/v1/availability_zones'
|
||||||
|
|
||||||
|
def list(self, **kwargs):
|
||||||
|
return self._list(self._path(), "availability_zones", qparams=kwargs)
|
||||||
21
zunclient/v1/availability_zones_shell.py
Normal file
21
zunclient/v1/availability_zones_shell.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright 2015 NEC Corporation. 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.
|
||||||
|
|
||||||
|
from zunclient.common import utils as zun_utils
|
||||||
|
|
||||||
|
|
||||||
|
def do_availability_zone_list(cs, args):
|
||||||
|
"""Print a list of availability zones."""
|
||||||
|
zones = cs.availability_zones.list()
|
||||||
|
zun_utils.list_availability_zones(zones)
|
||||||
@@ -17,6 +17,7 @@ from keystoneauth1 import loading
|
|||||||
from keystoneauth1 import session as ksa_session
|
from keystoneauth1 import session as ksa_session
|
||||||
|
|
||||||
from zunclient.common import httpclient
|
from zunclient.common import httpclient
|
||||||
|
from zunclient.v1 import availability_zones as az
|
||||||
from zunclient.v1 import capsules
|
from zunclient.v1 import capsules
|
||||||
from zunclient.v1 import containers
|
from zunclient.v1 import containers
|
||||||
from zunclient.v1 import hosts
|
from zunclient.v1 import hosts
|
||||||
@@ -127,6 +128,7 @@ class Client(object):
|
|||||||
self.hosts = hosts.HostManager(self.http_client)
|
self.hosts = hosts.HostManager(self.http_client)
|
||||||
self.versions = versions.VersionManager(self.http_client)
|
self.versions = versions.VersionManager(self.http_client)
|
||||||
self.capsules = capsules.CapsuleManager(self.http_client)
|
self.capsules = capsules.CapsuleManager(self.http_client)
|
||||||
|
self.availability_zones = az.AvailabilityZoneManager(self.http_client)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_version(self):
|
def api_version(self):
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from zunclient.v1 import availability_zones_shell
|
||||||
from zunclient.v1 import capsules_shell
|
from zunclient.v1 import capsules_shell
|
||||||
from zunclient.v1 import containers_shell
|
from zunclient.v1 import containers_shell
|
||||||
from zunclient.v1 import hosts_shell
|
from zunclient.v1 import hosts_shell
|
||||||
@@ -21,6 +22,7 @@ from zunclient.v1 import services_shell
|
|||||||
from zunclient.v1 import versions_shell
|
from zunclient.v1 import versions_shell
|
||||||
|
|
||||||
COMMAND_MODULES = [
|
COMMAND_MODULES = [
|
||||||
|
availability_zones_shell,
|
||||||
containers_shell,
|
containers_shell,
|
||||||
images_shell,
|
images_shell,
|
||||||
services_shell,
|
services_shell,
|
||||||
|
|||||||
Reference in New Issue
Block a user