Skip to content

Commit 44cf963

Browse files
committed
Migrate 'availability zone list' to SDK
This is a bit of an odd one. Because this is a "common" command, there are three clients in play here: a compute client, a block storage client, and a networking client. The networking aspects of this command are already using SDK though the tests were mistakenly using a fake version of the legacy neutron client (albeit one with the correct SDK properties). We were still using legacy clients for the other two. Correct the networking tests and migrate the compute and block storage aspects of the command. Change-Id: I292e1a712bca97e1270e8a97606e02a8a44c2954 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
1 parent 78988d1 commit 44cf963

File tree

5 files changed

+113
-142
lines changed

5 files changed

+113
-142
lines changed

openstackclient/common/availability_zone.py

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,20 @@
2626
LOG = logging.getLogger(__name__)
2727

2828

29-
def _xform_common_availability_zone(az, zone_info):
30-
if hasattr(az, 'zoneState'):
31-
zone_info['zone_status'] = (
32-
'available' if az.zoneState['available'] else 'not available'
33-
)
34-
if hasattr(az, 'zoneName'):
35-
zone_info['zone_name'] = az.zoneName
36-
37-
zone_info['zone_resource'] = ''
38-
39-
4029
def _xform_compute_availability_zone(az, include_extra):
4130
result = []
42-
zone_info = {}
43-
_xform_common_availability_zone(az, zone_info)
31+
zone_info = {
32+
'zone_name': az.name,
33+
'zone_status': (
34+
'available' if az.state['available'] else 'not available'
35+
),
36+
}
4437

4538
if not include_extra:
4639
result.append(zone_info)
4740
return result
4841

49-
if hasattr(az, 'hosts') and az.hosts:
42+
if az.hosts:
5043
for host, services in az.hosts.items():
5144
host_info = copy.deepcopy(zone_info)
5245
host_info['host_name'] = host
@@ -70,20 +63,24 @@ def _xform_compute_availability_zone(az, include_extra):
7063

7164
def _xform_volume_availability_zone(az):
7265
result = []
73-
zone_info = {}
74-
_xform_common_availability_zone(az, zone_info)
66+
zone_info = {
67+
'zone_name': az.name,
68+
'zone_status': (
69+
'available' if az.state['available'] else 'not available'
70+
),
71+
}
7572
result.append(zone_info)
7673
return result
7774

7875

7976
def _xform_network_availability_zone(az):
8077
result = []
8178
zone_info = {}
82-
zone_info['zone_name'] = getattr(az, 'name', '')
83-
zone_info['zone_status'] = getattr(az, 'state', '')
79+
zone_info['zone_name'] = az.name
80+
zone_info['zone_status'] = az.state
8481
if 'unavailable' == zone_info['zone_status']:
8582
zone_info['zone_status'] = 'not available'
86-
zone_info['zone_resource'] = getattr(az, 'resource', '')
83+
zone_info['zone_resource'] = az.resource
8784
result.append(zone_info)
8885
return result
8986

@@ -92,7 +89,7 @@ class ListAvailabilityZone(command.Lister):
9289
_description = _("List availability zones and their status")
9390

9491
def get_parser(self, prog_name):
95-
parser = super(ListAvailabilityZone, self).get_parser(prog_name)
92+
parser = super().get_parser(prog_name)
9693
parser.add_argument(
9794
'--compute',
9895
action='store_true',
@@ -120,26 +117,25 @@ def get_parser(self, prog_name):
120117
return parser
121118

122119
def _get_compute_availability_zones(self, parsed_args):
123-
compute_client = self.app.client_manager.compute
120+
compute_client = self.app.client_manager.sdk_connection.compute
124121
try:
125-
data = compute_client.availability_zones.list()
122+
data = compute_client.availability_zones(details=True)
126123
except nova_exceptions.Forbidden: # policy doesn't allow
127124
try:
128-
data = compute_client.availability_zones.list(detailed=False)
125+
data = compute_client.availability_zones(details=False)
129126
except Exception:
130127
raise
131128

132-
# Argh, the availability zones are not iterable...
133129
result = []
134130
for zone in data:
135131
result += _xform_compute_availability_zone(zone, parsed_args.long)
136132
return result
137133

138134
def _get_volume_availability_zones(self, parsed_args):
139-
volume_client = self.app.client_manager.volume
135+
volume_client = self.app.client_manager.sdk_connection.volume
140136
data = []
141137
try:
142-
data = volume_client.availability_zones.list()
138+
data = volume_client.availability_zones()
143139
except Exception as e:
144140
LOG.debug('Volume availability zone exception: %s', e)
145141
if parsed_args.volume:
@@ -165,7 +161,7 @@ def _get_network_availability_zones(self, parsed_args):
165161
LOG.debug('Network availability zone exception: ', e)
166162
if parsed_args.network:
167163
message = _(
168-
"Availability zones list not supported by " "Network API"
164+
"Availability zones list not supported by Network API"
169165
)
170166
LOG.warning(message)
171167
return []

openstackclient/tests/unit/common/test_availability_zone.py

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,23 @@
1515

1616
from openstackclient.common import availability_zone
1717
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
18-
from openstackclient.tests.unit import fakes
1918
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
2019
from openstackclient.tests.unit import utils
21-
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
20+
from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
2221

2322

2423
def _build_compute_az_datalist(compute_az, long_datalist=False):
2524
datalist = ()
2625
if not long_datalist:
2726
datalist = (
28-
compute_az.zoneName,
27+
compute_az.name,
2928
'available',
3029
)
3130
else:
3231
for host, services in compute_az.hosts.items():
3332
for service, state in services.items():
3433
datalist += (
35-
compute_az.zoneName,
34+
compute_az.name,
3635
'available',
3736
'',
3837
host,
@@ -46,12 +45,12 @@ def _build_volume_az_datalist(volume_az, long_datalist=False):
4645
datalist = ()
4746
if not long_datalist:
4847
datalist = (
49-
volume_az.zoneName,
48+
volume_az.name,
5049
'available',
5150
)
5251
else:
5352
datalist = (
54-
volume_az.zoneName,
53+
volume_az.name,
5554
'available',
5655
'',
5756
'',
@@ -84,33 +83,20 @@ class TestAvailabilityZone(utils.TestCommand):
8483
def setUp(self):
8584
super().setUp()
8685

87-
compute_client = compute_fakes.FakeComputev2Client(
88-
endpoint=fakes.AUTH_URL,
89-
token=fakes.AUTH_TOKEN,
90-
)
91-
self.app.client_manager.compute = compute_client
92-
93-
self.compute_azs_mock = compute_client.availability_zones
94-
self.compute_azs_mock.reset_mock()
86+
self.app.client_manager.sdk_connection = mock.Mock()
9587

96-
volume_client = volume_fakes.FakeVolumeClient(
97-
endpoint=fakes.AUTH_URL,
98-
token=fakes.AUTH_TOKEN,
99-
)
100-
self.app.client_manager.volume = volume_client
88+
self.app.client_manager.sdk_connection.compute = mock.Mock()
89+
self.compute_client = self.app.client_manager.sdk_connection.compute
90+
self.compute_client.availability_zones = mock.Mock()
10191

102-
self.volume_azs_mock = volume_client.availability_zones
103-
self.volume_azs_mock.reset_mock()
104-
105-
network_client = network_fakes.FakeNetworkV2Client(
106-
endpoint=fakes.AUTH_URL,
107-
token=fakes.AUTH_TOKEN,
108-
)
109-
self.app.client_manager.network = network_client
92+
self.app.client_manager.sdk_connection.volume = mock.Mock()
93+
self.volume_client = self.app.client_manager.sdk_connection.volume
94+
self.volume_client.availability_zones = mock.Mock()
11095

111-
network_client.availability_zones = mock.Mock()
112-
network_client.find_extension = mock.Mock()
113-
self.network_azs_mock = network_client.availability_zones
96+
self.app.client_manager.network = mock.Mock()
97+
self.network_client = self.app.client_manager.network
98+
self.network_client.availability_zones = mock.Mock()
99+
self.network_client.find_extension = mock.Mock()
114100

115101

116102
class TestAvailabilityZoneList(TestAvailabilityZone):
@@ -131,9 +117,9 @@ class TestAvailabilityZoneList(TestAvailabilityZone):
131117
def setUp(self):
132118
super().setUp()
133119

134-
self.compute_azs_mock.list.return_value = self.compute_azs
135-
self.volume_azs_mock.list.return_value = self.volume_azs
136-
self.network_azs_mock.return_value = self.network_azs
120+
self.compute_client.availability_zones.return_value = self.compute_azs
121+
self.volume_client.availability_zones.return_value = self.volume_azs
122+
self.network_client.availability_zones.return_value = self.network_azs
137123

138124
# Get the command object to test
139125
self.cmd = availability_zone.ListAvailabilityZone(self.app, None)
@@ -148,9 +134,9 @@ def test_availability_zone_list_no_options(self):
148134
# containing the data to be listed.
149135
columns, data = self.cmd.take_action(parsed_args)
150136

151-
self.compute_azs_mock.list.assert_called_with()
152-
self.volume_azs_mock.list.assert_called_with()
153-
self.network_azs_mock.assert_called_with()
137+
self.compute_client.availability_zones.assert_called_with(details=True)
138+
self.volume_client.availability_zones.assert_called_with()
139+
self.network_client.availability_zones.assert_called_with()
154140

155141
self.assertEqual(self.short_columnslist, columns)
156142
datalist = ()
@@ -176,9 +162,9 @@ def test_availability_zone_list_long(self):
176162
# containing the data to be listed.
177163
columns, data = self.cmd.take_action(parsed_args)
178164

179-
self.compute_azs_mock.list.assert_called_with()
180-
self.volume_azs_mock.list.assert_called_with()
181-
self.network_azs_mock.assert_called_with()
165+
self.compute_client.availability_zones.assert_called_with(details=True)
166+
self.volume_client.availability_zones.assert_called_with()
167+
self.network_client.availability_zones.assert_called_with()
182168

183169
self.assertEqual(self.long_columnslist, columns)
184170
datalist = ()
@@ -210,9 +196,9 @@ def test_availability_zone_list_compute(self):
210196
# containing the data to be listed.
211197
columns, data = self.cmd.take_action(parsed_args)
212198

213-
self.compute_azs_mock.list.assert_called_with()
214-
self.volume_azs_mock.list.assert_not_called()
215-
self.network_azs_mock.assert_not_called()
199+
self.compute_client.availability_zones.assert_called_with(details=True)
200+
self.volume_client.availability_zones.assert_not_called()
201+
self.network_client.availability_zones.assert_not_called()
216202

217203
self.assertEqual(self.short_columnslist, columns)
218204
datalist = ()
@@ -234,9 +220,9 @@ def test_availability_zone_list_volume(self):
234220
# containing the data to be listed.
235221
columns, data = self.cmd.take_action(parsed_args)
236222

237-
self.compute_azs_mock.list.assert_not_called()
238-
self.volume_azs_mock.list.assert_called_with()
239-
self.network_azs_mock.assert_not_called()
223+
self.compute_client.availability_zones.assert_not_called()
224+
self.volume_client.availability_zones.assert_called_with()
225+
self.network_client.availability_zones.assert_not_called()
240226

241227
self.assertEqual(self.short_columnslist, columns)
242228
datalist = ()
@@ -258,9 +244,9 @@ def test_availability_zone_list_network(self):
258244
# containing the data to be listed.
259245
columns, data = self.cmd.take_action(parsed_args)
260246

261-
self.compute_azs_mock.list.assert_not_called()
262-
self.volume_azs_mock.list.assert_not_called()
263-
self.network_azs_mock.assert_called_with()
247+
self.compute_client.availability_zones.assert_not_called()
248+
self.volume_client.availability_zones.assert_not_called()
249+
self.network_client.availability_zones.assert_called_with()
264250

265251
self.assertEqual(self.short_columnslist, columns)
266252
datalist = ()

openstackclient/tests/unit/compute/v2/fakes.py

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from novaclient import api_versions
2222
from openstack.compute.v2 import aggregate as _aggregate
23+
from openstack.compute.v2 import availability_zone as _availability_zone
2324
from openstack.compute.v2 import flavor as _flavor
2425
from openstack.compute.v2 import hypervisor as _hypervisor
2526
from openstack.compute.v2 import keypair as _keypair
@@ -83,12 +84,6 @@ def __init__(self, **kwargs):
8384
self.agents = mock.Mock()
8485
self.agents.resource_class = fakes.FakeResource(None, {})
8586

86-
self.aggregates = mock.Mock()
87-
self.aggregates.resource_class = fakes.FakeResource(None, {})
88-
89-
self.availability_zones = mock.Mock()
90-
self.availability_zones.resource_class = fakes.FakeResource(None, {})
91-
9287
self.images = mock.Mock()
9388
self.images.resource_class = fakes.FakeResource(None, {})
9489

@@ -783,49 +778,45 @@ def get_keypairs(keypairs=None, count=2):
783778
def create_one_availability_zone(attrs=None):
784779
"""Create a fake AZ.
785780
786-
:param dict attrs:
787-
A dictionary with all attributes
788-
:return:
789-
A FakeResource object with zoneName, zoneState, etc.
781+
:param dict attrs: A dictionary with all attributes
782+
:return: A fake openstack.compute.v2.availability_zone.AvailabilityZone
783+
object
790784
"""
791785
attrs = attrs or {}
792786

793787
# Set default attributes.
794788
host_name = uuid.uuid4().hex
795789
service_name = uuid.uuid4().hex
796-
service_updated_at = uuid.uuid4().hex
797-
availability_zone = {
798-
'zoneName': uuid.uuid4().hex,
799-
'zoneState': {'available': True},
790+
availability_zone_info = {
791+
'name': uuid.uuid4().hex,
792+
'state': {'available': True},
800793
'hosts': {
801794
host_name: {
802795
service_name: {
803796
'available': True,
804797
'active': True,
805-
'updated_at': service_updated_at,
798+
'updated_at': '2023-01-01T00:00:00.000000',
806799
}
807800
}
808801
},
809802
}
810803

811804
# Overwrite default attributes.
812-
availability_zone.update(attrs)
805+
availability_zone_info.update(attrs)
813806

814-
availability_zone = fakes.FakeResource(
815-
info=copy.deepcopy(availability_zone), loaded=True
807+
availability_zone = _availability_zone.AvailabilityZone(
808+
**availability_zone_info
816809
)
817810
return availability_zone
818811

819812

820813
def create_availability_zones(attrs=None, count=2):
821814
"""Create multiple fake AZs.
822815
823-
:param dict attrs:
824-
A dictionary with all attributes
825-
:param int count:
826-
The number of AZs to fake
827-
:return:
828-
A list of FakeResource objects faking the AZs
816+
:param dict attrs: A dictionary with all attributes
817+
:param int count: The number of availability zones to fake
818+
:return: A list of fake
819+
openstack.compute.v2.availability_zone.AvailabilityZone objects
829820
"""
830821
availability_zones = []
831822
for i in range(0, count):

0 commit comments

Comments
 (0)