48
49
class ZoneAwareScheduler(driver.Scheduler):
49
50
"""Base class for creating Zone Aware Schedulers."""
51
def _call_zone_method(self, context, method, specs):
52
def _call_zone_method(self, context, method, specs, zones):
52
53
"""Call novaclient zone method. Broken out for testing."""
53
return api.call_zone_method(context, method, specs=specs)
54
return api.call_zone_method(context, method, specs=specs, zones=zones)
55
def _provision_resource_locally(self, context, item, instance_id, kwargs):
56
def _provision_resource_locally(self, context, build_plan_item,
57
request_spec, kwargs):
56
58
"""Create the requested resource in this Zone."""
57
host = item['hostname']
59
host = build_plan_item['hostname']
60
base_options = request_spec['instance_properties']
62
# TODO(sandy): I guess someone needs to add block_device_mapping
63
# support at some point? Also, OS API has no concept of security
65
instance = compute_api.API().create_db_entry_for_new_instance(context,
66
base_options, None, [])
68
instance_id = instance['id']
58
69
kwargs['instance_id'] = instance_id
60
72
db.queue_get_for(context, "compute", host),
61
73
{"method": "run_instance",
115
127
nova.servers.create(name, image_ref, flavor_id, ipgroup, meta, files,
116
128
child_blob, reservation_id=reservation_id)
118
def _provision_resource_from_blob(self, context, item, instance_id,
119
request_spec, kwargs):
130
def _provision_resource_from_blob(self, context, build_plan_item,
131
instance_id, request_spec, kwargs):
120
132
"""Create the requested resource locally or in a child zone
121
133
based on what is stored in the zone blob info.
147
if "blob" in build_plan_item:
136
148
# Request was passed in from above. Is it for us?
137
host_info = self._decrypt_blob(item['blob'])
138
elif "child_blob" in item:
149
host_info = self._decrypt_blob(build_plan_item['blob'])
150
elif "child_blob" in build_plan_item:
139
151
# Our immediate child zone provided this info ...
152
host_info = build_plan_item
142
154
if not host_info:
143
155
raise InvalidBlob()
147
159
self._ask_child_zone_to_create_instance(context, host_info,
148
160
request_spec, kwargs)
150
self._provision_resource_locally(context, host_info,
162
self._provision_resource_locally(context, host_info, request_spec,
153
def _provision_resource(self, context, item, instance_id, request_spec,
165
def _provision_resource(self, context, build_plan_item, instance_id,
166
request_spec, kwargs):
155
167
"""Create the requested resource in this Zone or a child zone."""
156
if "hostname" in item:
157
self._provision_resource_locally(context, item, instance_id,
168
if "hostname" in build_plan_item:
169
self._provision_resource_locally(context, build_plan_item,
170
request_spec, kwargs)
161
self._provision_resource_from_blob(context, item, instance_id,
162
request_spec, kwargs)
173
self._provision_resource_from_blob(context, build_plan_item,
174
instance_id, request_spec, kwargs)
176
def _adjust_child_weights(self, child_results, zones):
177
"""Apply the Scale and Offset values from the Zone definition
178
to adjust the weights returned from the child zones. Alters
179
child_results in place.
181
for zone, result in child_results:
185
for zone_rec in zones:
186
if zone_rec['api_url'] != zone:
191
offset = zone_rec['weight_offset']
192
scale = zone_rec['weight_scale']
193
raw_weight = item['weight']
194
cooked_weight = offset + scale * raw_weight
195
item['weight'] = cooked_weight
196
item['raw_weight'] = raw_weight
198
LOG.exception(_("Bad child zone scaling values "
199
"for Zone: %(zone)s") % locals())
164
201
def schedule_run_instance(self, context, instance_id, request_spec,
165
202
*args, **kwargs):
262
299
# Next, tack on the best weights from the child zones ...
263
300
json_spec = json.dumps(request_spec)
301
all_zones = db.zone_get_all(context)
264
302
child_results = self._call_zone_method(context, "select",
303
specs=json_spec, zones=all_zones)
304
self._adjust_child_weights(child_results, all_zones)
266
305
for child_zone, result in child_results:
267
306
for weighting in result:
268
307
# Remember the child_zone so we can get back to