~blamar/nova/gracefull-shutdown

« back to all changes in this revision

Viewing changes to nova/scheduler/zone_aware_scheduler.py

  • Committer: Tarmac
  • Author(s): Sandy Walsh
  • Date: 2011-06-30 18:23:06 UTC
  • mfrom: (1063.9.15 zone_offset)
  • Revision ID: tarmac-20110630182306-xeik58dcp10z39fw
Child Zone Weight adjustment available when adding Child Zones.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
from nova import log as logging
34
34
from nova import rpc
35
35
 
 
36
from nova.compute import api as compute_api
36
37
from nova.scheduler import api
37
38
from nova.scheduler import driver
38
39
 
48
49
class ZoneAwareScheduler(driver.Scheduler):
49
50
    """Base class for creating Zone Aware Schedulers."""
50
51
 
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)
54
55
 
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']
 
61
 
 
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
 
64
        # groups.
 
65
        instance = compute_api.API().create_db_entry_for_new_instance(context,
 
66
            base_options, None, [])
 
67
 
 
68
        instance_id = instance['id']
58
69
        kwargs['instance_id'] = instance_id
 
70
 
59
71
        rpc.cast(context,
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)
117
129
 
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.
122
134
 
132
144
           request."""
133
145
 
134
146
        host_info = None
135
 
        if "blob" in item:
 
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 ...
140
 
            host_info = item
 
152
            host_info = build_plan_item
141
153
 
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)
149
161
        else:
150
 
            self._provision_resource_locally(context, host_info,
151
 
                                             instance_id, kwargs)
 
162
            self._provision_resource_locally(context, host_info, request_spec,
 
163
                                             kwargs)
152
164
 
153
 
    def _provision_resource(self, context, item, instance_id, request_spec,
154
 
                           kwargs):
 
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,
158
 
                            kwargs)
 
168
        if "hostname" in build_plan_item:
 
169
            self._provision_resource_locally(context, build_plan_item,
 
170
                                             request_spec, kwargs)
159
171
            return
160
172
 
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)
 
175
 
 
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.
 
180
        """
 
181
        for zone, result in child_results:
 
182
            if not result:
 
183
                continue
 
184
 
 
185
            for zone_rec in zones:
 
186
                if zone_rec['api_url'] != zone:
 
187
                    continue
 
188
 
 
189
                for item in result:
 
190
                    try:
 
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
 
197
                    except KeyError:
 
198
                        LOG.exception(_("Bad child zone scaling values "
 
199
                                        "for Zone: %(zone)s") % locals())
163
200
 
164
201
    def schedule_run_instance(self, context, instance_id, request_spec,
165
202
                              *args, **kwargs):
261
298
 
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",
265
 
                specs=json_spec)
 
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