Adds availability zone support for Nova V3 API
Adds support and tests for the os-availability-zones extension for the Nova V3 API. Also implements sorting for zone host display which was applied to the v1_1 version, but not the v3 version in I9ab25ef52d6d19b45a39f04cbcde864ee225b4cc Partially implements blueprint v3-api Change-Id: I8daa2503a2dc8767e9157bdfa6c9adaedfc8f3c0
This commit is contained in:
parent
1746bbac26
commit
40a1c12828
@ -19,33 +19,43 @@ import six
|
||||
from novaclient.tests import utils
|
||||
from novaclient.tests.v1_1 import fakes
|
||||
from novaclient.v1_1 import availability_zones
|
||||
from novaclient.v1_1 import shell
|
||||
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
class AvailabilityZoneTest(utils.TestCase):
|
||||
# NOTE(cyeoh): import shell here so the V3 version of
|
||||
# this class can inherit off the v3 version of shell
|
||||
from novaclient.v1_1 import shell # noqa
|
||||
|
||||
def setUp(self):
|
||||
super(AvailabilityZoneTest, self).setUp()
|
||||
self.cs = self._get_fake_client()
|
||||
self.availability_zone_type = self._get_availability_zone_type()
|
||||
|
||||
def _get_fake_client(self):
|
||||
return fakes.FakeClient()
|
||||
|
||||
def _get_availability_zone_type(self):
|
||||
return availability_zones.AvailabilityZone
|
||||
|
||||
def _assertZone(self, zone, name, status):
|
||||
self.assertEqual(zone.zoneName, name)
|
||||
self.assertEqual(zone.zoneState, status)
|
||||
|
||||
def test_list_availability_zone(self):
|
||||
zones = cs.availability_zones.list(detailed=False)
|
||||
cs.assert_called('GET', '/os-availability-zone')
|
||||
zones = self.cs.availability_zones.list(detailed=False)
|
||||
self.cs.assert_called('GET', '/os-availability-zone')
|
||||
|
||||
for zone in zones:
|
||||
self.assertTrue(isinstance(zone,
|
||||
availability_zones.AvailabilityZone))
|
||||
self.availability_zone_type))
|
||||
|
||||
self.assertEqual(2, len(zones))
|
||||
|
||||
l0 = [six.u('zone-1'), six.u('available')]
|
||||
l1 = [six.u('zone-2'), six.u('not available')]
|
||||
|
||||
z0 = shell._treeizeAvailabilityZone(zones[0])
|
||||
z1 = shell._treeizeAvailabilityZone(zones[1])
|
||||
z0 = self.shell._treeizeAvailabilityZone(zones[0])
|
||||
z1 = self.shell._treeizeAvailabilityZone(zones[1])
|
||||
|
||||
self.assertEqual((len(z0), len(z1)), (1, 1))
|
||||
|
||||
@ -53,12 +63,12 @@ class AvailabilityZoneTest(utils.TestCase):
|
||||
self._assertZone(z1[0], l1[0], l1[1])
|
||||
|
||||
def test_detail_availability_zone(self):
|
||||
zones = cs.availability_zones.list(detailed=True)
|
||||
cs.assert_called('GET', '/os-availability-zone/detail')
|
||||
zones = self.cs.availability_zones.list(detailed=True)
|
||||
self.cs.assert_called('GET', '/os-availability-zone/detail')
|
||||
|
||||
for zone in zones:
|
||||
self.assertTrue(isinstance(zone,
|
||||
availability_zones.AvailabilityZone))
|
||||
self.availability_zone_type))
|
||||
|
||||
self.assertEqual(3, len(zones))
|
||||
|
||||
@ -75,9 +85,9 @@ class AvailabilityZoneTest(utils.TestCase):
|
||||
six.u('enabled XXX 2012-12-26 14:45:24')]
|
||||
l8 = [six.u('zone-2'), six.u('not available')]
|
||||
|
||||
z0 = shell._treeizeAvailabilityZone(zones[0])
|
||||
z1 = shell._treeizeAvailabilityZone(zones[1])
|
||||
z2 = shell._treeizeAvailabilityZone(zones[2])
|
||||
z0 = self.shell._treeizeAvailabilityZone(zones[0])
|
||||
z1 = self.shell._treeizeAvailabilityZone(zones[1])
|
||||
z2 = self.shell._treeizeAvailabilityZone(zones[2])
|
||||
|
||||
self.assertEqual((len(z0), len(z1), len(z2)), (3, 5, 1))
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from novaclient.openstack.common import strutils
|
||||
from novaclient.tests import fakes
|
||||
from novaclient.tests.v1_1 import fakes as fakes_v1_1
|
||||
@ -228,3 +230,44 @@ class FakeHTTPClient(fakes_v1_1.FakeHTTPClient):
|
||||
|
||||
def delete_servers_1234_os_server_password(self, **kw):
|
||||
return (202, {}, None)
|
||||
|
||||
#
|
||||
# Availability Zones
|
||||
#
|
||||
def get_os_availability_zone(self, **kw):
|
||||
return (200, {}, {"availability_zone_info": [
|
||||
{"zone_name": "zone-1",
|
||||
"zone_state": {"available": True},
|
||||
"hosts": None},
|
||||
{"zone_name": "zone-2",
|
||||
"zone_state": {"available": False},
|
||||
"hosts": None}]})
|
||||
|
||||
def get_os_availability_zone_detail(self, **kw):
|
||||
return (200, {}, {"availability_zone_info": [
|
||||
{"zone_name": "zone-1",
|
||||
"zone_state": {"available": True},
|
||||
"hosts": {
|
||||
"fake_host-1": {
|
||||
"nova-compute": {"active": True,
|
||||
"available": True,
|
||||
"updated_at":
|
||||
datetime(2012, 12, 26, 14, 45, 25, 0)}}}},
|
||||
{"zone_name": "internal",
|
||||
"zone_state": {"available": True},
|
||||
"hosts": {
|
||||
"fake_host-1": {
|
||||
"nova-sched": {
|
||||
"active": True,
|
||||
"available": True,
|
||||
"updated_at":
|
||||
datetime(2012, 12, 26, 14, 45, 25, 0)}},
|
||||
"fake_host-2": {
|
||||
"nova-network": {
|
||||
"active": True,
|
||||
"available": False,
|
||||
"updated_at":
|
||||
datetime(2012, 12, 26, 14, 45, 24, 0)}}}},
|
||||
{"zone_name": "zone-2",
|
||||
"zone_state": {"available": False},
|
||||
"hosts": None}]})
|
||||
|
38
novaclient/tests/v3/test_availability_zone.py
Normal file
38
novaclient/tests/v3/test_availability_zone.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
# Copyright 2013 IBM Corp.
|
||||
# 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 novaclient.tests.v1_1 import test_availability_zone
|
||||
from novaclient.tests.v3 import fakes
|
||||
from novaclient.v3 import availability_zones
|
||||
|
||||
|
||||
class AvailabilityZoneTest(test_availability_zone.AvailabilityZoneTest):
|
||||
from novaclient.v3 import shell # noqa
|
||||
|
||||
def setUp(self):
|
||||
super(AvailabilityZoneTest, self).setUp()
|
||||
self.cs = self._get_fake_client()
|
||||
self.availability_zone_type = self._get_availability_zone_type()
|
||||
|
||||
def _assertZone(self, zone, name, status):
|
||||
self.assertEqual(zone.zone_name, name)
|
||||
self.assertEqual(zone.zone_state, status)
|
||||
|
||||
def _get_fake_client(self):
|
||||
return fakes.FakeClient()
|
||||
|
||||
def _get_availability_zone_type(self):
|
||||
return availability_zones.AvailabilityZone
|
@ -36,6 +36,7 @@ class AvailabilityZoneManager(base.ManagerWithFind):
|
||||
Manage :class:`AvailabilityZone` resources.
|
||||
"""
|
||||
resource_class = AvailabilityZone
|
||||
return_parameter_name = "availabilityZoneInfo"
|
||||
|
||||
def list(self, detailed=True):
|
||||
"""
|
||||
@ -45,6 +46,7 @@ class AvailabilityZoneManager(base.ManagerWithFind):
|
||||
"""
|
||||
if detailed is True:
|
||||
return self._list("/os-availability-zone/detail",
|
||||
"availabilityZoneInfo")
|
||||
self.return_parameter_name)
|
||||
else:
|
||||
return self._list("/os-availability-zone", "availabilityZoneInfo")
|
||||
return self._list("/os-availability-zone",
|
||||
self.return_parameter_name)
|
||||
|
33
novaclient/v3/availability_zones.py
Normal file
33
novaclient/v3/availability_zones.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
# Copyright 2013 IBM Corp.
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Availability Zone interface.
|
||||
"""
|
||||
|
||||
from novaclient.v1_1 import availability_zones
|
||||
|
||||
|
||||
class AvailabilityZone(availability_zones.AvailabilityZone):
|
||||
pass
|
||||
|
||||
|
||||
class AvailabilityZoneManager(availability_zones.AvailabilityZoneManager):
|
||||
"""
|
||||
Manage :class:`AvailabilityZone` resources.
|
||||
"""
|
||||
resource_class = AvailabilityZone
|
||||
return_parameter_name = 'availability_zone_info'
|
@ -16,6 +16,7 @@
|
||||
|
||||
from novaclient import client
|
||||
from novaclient.v3 import agents
|
||||
from novaclient.v3 import availability_zones
|
||||
from novaclient.v3 import flavor_access
|
||||
from novaclient.v3 import flavors
|
||||
from novaclient.v3 import hosts
|
||||
@ -56,6 +57,8 @@ class Client(object):
|
||||
self.os_cache = os_cache or not no_cache
|
||||
#TODO(bnemec): Add back in v3 extensions
|
||||
self.agents = agents.AgentsManager(self)
|
||||
self.availability_zones = \
|
||||
availability_zones.AvailabilityZoneManager(self)
|
||||
self.hosts = hosts.HostManager(self)
|
||||
self.flavors = flavors.FlavorManager(self)
|
||||
self.flavor_access = flavor_access.FlavorAccessManager(self)
|
||||
|
@ -32,8 +32,8 @@ from novaclient.openstack.common import strutils
|
||||
from novaclient.openstack.common import timeutils
|
||||
from novaclient.openstack.common import uuidutils
|
||||
from novaclient import utils
|
||||
from novaclient.v1_1 import availability_zones
|
||||
from novaclient.v1_1 import quotas
|
||||
from novaclient.v3 import availability_zones
|
||||
from novaclient.v3 import servers
|
||||
|
||||
|
||||
@ -1433,7 +1433,7 @@ def _translate_volume_snapshot_keys(collection):
|
||||
|
||||
def _translate_availability_zone_keys(collection):
|
||||
_translate_keys(collection,
|
||||
[('zoneName', 'name'), ('zoneState', 'status')])
|
||||
[('zone_name', 'name'), ('zone_state', 'status')])
|
||||
|
||||
|
||||
@utils.arg('--all-tenants',
|
||||
@ -3161,40 +3161,40 @@ def _treeizeAvailabilityZone(zone):
|
||||
result = []
|
||||
|
||||
# Zone tree view item
|
||||
az.zoneName = zone.zoneName
|
||||
az.zoneState = ('available'
|
||||
if zone.zoneState['available'] else 'not available')
|
||||
az._info['zoneName'] = az.zoneName
|
||||
az._info['zoneState'] = az.zoneState
|
||||
az.zone_name = zone.zone_name
|
||||
az.zone_state = ('available'
|
||||
if zone.zone_state['available'] else 'not available')
|
||||
az._info['zone_name'] = az.zone_name
|
||||
az._info['zone_state'] = az.zone_state
|
||||
result.append(az)
|
||||
|
||||
if zone.hosts is not None:
|
||||
for (host, services) in zone.hosts.items():
|
||||
zone_hosts = sorted(zone.hosts.items(), key=lambda x: x[0])
|
||||
for (host, services) in zone_hosts:
|
||||
# Host tree view item
|
||||
az = AvailabilityZone(zone.manager,
|
||||
copy.deepcopy(zone._info), zone._loaded)
|
||||
az.zoneName = '|- %s' % host
|
||||
az.zoneState = ''
|
||||
az._info['zoneName'] = az.zoneName
|
||||
az._info['zoneState'] = az.zoneState
|
||||
az.zone_name = '|- %s' % host
|
||||
az.zone_state = ''
|
||||
az._info['zone_name'] = az.zone_name
|
||||
az._info['zone_state'] = az.zone_state
|
||||
result.append(az)
|
||||
|
||||
for (svc, state) in services.items():
|
||||
# Service tree view item
|
||||
az = AvailabilityZone(zone.manager,
|
||||
copy.deepcopy(zone._info), zone._loaded)
|
||||
az.zoneName = '| |- %s' % svc
|
||||
az.zoneState = '%s %s %s' % (
|
||||
az.zone_name = '| |- %s' % svc
|
||||
az.zone_state = '%s %s %s' % (
|
||||
'enabled' if state['active'] else 'disabled',
|
||||
':-)' if state['available'] else 'XXX',
|
||||
state['updated_at'])
|
||||
az._info['zoneName'] = az.zoneName
|
||||
az._info['zoneState'] = az.zoneState
|
||||
az._info['zone_name'] = az.zone_name
|
||||
az._info['zone_state'] = az.zone_state
|
||||
result.append(az)
|
||||
return result
|
||||
|
||||
|
||||
@utils.service_type('compute')
|
||||
def do_availability_zone_list(cs, _args):
|
||||
"""List all the availability zones."""
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user