-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
availability_zone.py
145 lines (120 loc) · 5.6 KB
/
availability_zone.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Copyright 2012 OpenStack Foundation
#
# 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_config import cfg
from nova.api.openstack.compute.schemas.v3 import availability_zone as schema
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova import availability_zones
from nova import objects
from nova import servicegroup
CONF = cfg.CONF
ALIAS = "os-availability-zone"
ATTRIBUTE_NAME = "availability_zone"
authorize = extensions.os_compute_authorizer(ALIAS)
class AvailabilityZoneController(wsgi.Controller):
"""The Availability Zone API controller for the OpenStack API."""
def __init__(self):
super(AvailabilityZoneController, self).__init__()
self.servicegroup_api = servicegroup.API()
def _get_filtered_availability_zones(self, zones, is_available):
result = []
for zone in zones:
# Hide internal_service_availability_zone
if zone == CONF.internal_service_availability_zone:
continue
result.append({'zoneName': zone,
'zoneState': {'available': is_available},
"hosts": None})
return result
def _describe_availability_zones(self, context, **kwargs):
ctxt = context.elevated()
available_zones, not_available_zones = \
availability_zones.get_availability_zones(ctxt)
filtered_available_zones = \
self._get_filtered_availability_zones(available_zones, True)
filtered_not_available_zones = \
self._get_filtered_availability_zones(not_available_zones, False)
return {'availabilityZoneInfo': filtered_available_zones +
filtered_not_available_zones}
def _describe_availability_zones_verbose(self, context, **kwargs):
ctxt = context.elevated()
available_zones, not_available_zones = \
availability_zones.get_availability_zones(ctxt)
# Available services
enabled_services = objects.ServiceList.get_all(context, disabled=False,
set_zones=True)
zone_hosts = {}
host_services = {}
for service in enabled_services:
zone_hosts.setdefault(service['availability_zone'], [])
if service['host'] not in zone_hosts[service['availability_zone']]:
zone_hosts[service['availability_zone']].append(
service['host'])
host_services.setdefault(service['availability_zone'] +
service['host'], [])
host_services[service['availability_zone'] + service['host']].\
append(service)
result = []
for zone in available_zones:
hosts = {}
for host in zone_hosts.get(zone, []):
hosts[host] = {}
for service in host_services[zone + host]:
alive = self.servicegroup_api.service_is_up(service)
hosts[host][service['binary']] = {'available': alive,
'active': True != service['disabled'],
'updated_at': service['updated_at']}
result.append({'zoneName': zone,
'zoneState': {'available': True},
"hosts": hosts})
for zone in not_available_zones:
result.append({'zoneName': zone,
'zoneState': {'available': False},
"hosts": None})
return {'availabilityZoneInfo': result}
@extensions.expected_errors(())
def index(self, req):
"""Returns a summary list of availability zone."""
context = req.environ['nova.context']
authorize(context, action='list')
return self._describe_availability_zones(context)
@extensions.expected_errors(())
def detail(self, req):
"""Returns a detailed list of availability zone."""
context = req.environ['nova.context']
authorize(context, action='detail')
return self._describe_availability_zones_verbose(context)
class AvailabilityZone(extensions.V3APIExtensionBase):
"""1. Add availability_zone to the Create Server API.
2. Add availability zones describing.
"""
name = "AvailabilityZone"
alias = ALIAS
version = 1
def get_resources(self):
resource = [extensions.ResourceExtension(ALIAS,
AvailabilityZoneController(),
collection_actions={'detail': 'GET'})]
return resource
def get_controller_extensions(self):
"""It's an abstract function V3APIExtensionBase and the extension
will not be loaded without it.
"""
return []
# NOTE(gmann): This function is not supposed to use 'body_deprecated_param'
# parameter as this is placed to handle scheduler_hint extension for V2.1.
def server_create(self, server_dict, create_kwargs, body_deprecated_param):
create_kwargs['availability_zone'] = server_dict.get(ATTRIBUTE_NAME)
def get_server_create_schema(self):
return schema.server_create