def test_aggregate_metadata_get_by_host(self): self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host') db.aggregate_metadata_get_by_host(self.context, 'host', 'key').AndReturn('result') self.mox.ReplayAll() result = self.conductor.aggregate_metadata_get_by_host(self.context, 'host', 'key') self.assertEqual(result, 'result')
def test_aggregate_metadata_get_by_host(self): self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host') db.aggregate_metadata_get_by_host(self.context, 'host', 'key').AndReturn('result') self.mox.ReplayAll() result = self.conductor.aggregate_metadata_get_by_host( self.context, 'host', 'key') self.assertEqual(result, 'result')
def _get_cost(self, metadata, extra_specs): ctxt = context.RequestContext('user', 'project') host = 'host' self.mox.StubOutWithMock(db, 'aggregate_metadata_get_by_host') db.aggregate_metadata_get_by_host(mox.IgnoreArg(), host).\ AndReturn(metadata) self.mox.ReplayAll() host_state = host_manager.HostState(host, 'sometopic') weighing_properties = {'context': ctxt, "instance_type": {"extra_specs": extra_specs}} return aggregate.compute_aggregate_metadata_cost_more_fn(host_state, weighing_properties)
def get_coefficient_vectors(self, variables, hosts, instance_uuids, request_spec, filter_properties): # Coefficients are 0 for hosts in the availability zone, 1 for others props = request_spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') coefficient_vectors = [] for host in hosts: if availability_zone: context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host( context, host.host, key='availability_zone') if 'availability_zone' in metadata: if availability_zone in metadata['availability_zone']: coefficient_vectors.append( [0 for j in range(self.num_instances)]) else: coefficient_vectors.append( [1 for j in range(self.num_instances)]) elif availability_zone == CONF.default_availability_zone: coefficient_vectors.append( [0 for j in range(self.num_instances)]) else: coefficient_vectors.append( [1 for j in range(self.num_instances)]) else: coefficient_vectors.append( [0 for j in range(self.num_instances)]) return coefficient_vectors
def host_passes(self, host_state, filter_properties): """Checks a host in an aggregate that metadata key/value match with image properties. """ cfg_namespace = CONF.aggregate_image_properties_isolation_namespace cfg_separator = CONF.aggregate_image_properties_isolation_separator spec = filter_properties.get("request_spec", {}) image_props = spec.get("image", {}).get("properties", {}) context = filter_properties["context"].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, options in metadata.iteritems(): if cfg_namespace and not key.startswith(cfg_namespace + cfg_separator): continue prop = image_props.get(key) if prop and prop not in options: LOG.debug( "%(host_state)s fails image aggregate properties " "requirements. Property %(prop)s does not " "match %(options)s.", {"host_state": host_state, "prop": prop, "options": options}, ) return False return True
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get('instance_type') if 'extra_specs' not in instance_type: return True context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, req in instance_type['extra_specs'].iteritems(): if key.count(':'): continue aggregate_vals = metadata.get(key, None) if not aggregate_vals: LOG.debug(_("%(host_state)s fails instance_type extra_specs " "requirements"), locals()) return False for aggregate_val in aggregate_vals: if extra_specs_ops.match(aggregate_val, req): break else: LOG.debug(_("%(host_state)s fails instance_type extra_specs " "requirements"), locals()) return False return True
def get_coefficient_vectors(self, variables, hosts, instance_uuids, request_spec, filter_properties): # Coefficients are 0 for hosts in the availability zone, 1 for others props = request_spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') coefficient_vectors = [] for host in hosts: if availability_zone: context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host.host, key='availability_zone') if 'availability_zone' in metadata: if availability_zone in metadata['availability_zone']: coefficient_vectors.append([0 for j in range( self.num_instances)]) else: coefficient_vectors.append([1 for j in range( self.num_instances)]) elif availability_zone == CONF.default_availability_zone: coefficient_vectors.append([0 for j in range( self.num_instances)]) else: coefficient_vectors.append([1 for j in range( self.num_instances)]) else: coefficient_vectors.append([0 for j in range( self.num_instances)]) return coefficient_vectors
def host_passes(self, host_state, filter_properties): instance_type = filter_properties.get('instance_type') context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='instance_type') return (len(metadata) == 0 or instance_type['name'] in metadata['instance_type'])
def host_passes(self, host_state, filter_properties): """Checks a host in an aggregate that metadata key/value match with image properties. """ cfg_namespace = CONF.aggregate_image_properties_isolation_namespace cfg_separator = CONF.aggregate_image_properties_isolation_separator spec = filter_properties.get('request_spec', {}) image_props = spec.get('image', {}).get('properties', {}) context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, options in metadata.iteritems(): if (cfg_namespace and not key.startswith(cfg_namespace + cfg_separator)): continue prop = image_props.get(key) if prop and prop not in options: LOG.debug( "%(host_state)s fails image aggregate properties " "requirements. Property %(prop)s does not " "match %(options)s.", { 'host_state': host_state, 'prop': prop, 'options': options }) return False return True
def get_host_availability_zone(context, host): metadata = db.aggregate_metadata_get_by_host( context, host, key='availability_zone') if 'availability_zone' in metadata: return list(metadata['availability_zone'])[0] else: return CONF.default_availability_zone
def host_passes(self, host_state, filter_properties): spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') if not availability_zone: return True context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='availability_zone') if 'availability_zone' in metadata: hosts_passes = availability_zone in metadata['availability_zone'] host_az = metadata['availability_zone'] else: hosts_passes = availability_zone == CONF.default_availability_zone host_az = CONF.default_availability_zone if not hosts_passes: LOG.debug("Availability Zone '%(az)s' requested. " "%(host_state)s has AZs: %(host_az)s", {'host_state': host_state, 'az': availability_zone, 'host_az': host_az}) return hosts_passes
def _get_cpu_allocation_ratio(self, host_state, filter_properties): context = filter_properties['context'] # TODO(uni): DB query in filter is a performance hit, especially for # system with lots of hosts. Will need a general solution here to fix # all filters with aggregate DB call things. metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='cpu_allocation_ratio') aggregate_vals = metadata.get('cpu_allocation_ratio', set()) num_values = len(aggregate_vals) if num_values == 0: return CONF.cpu_allocation_ratio if num_values > 1: LOG.warning( _("%(num_values)d ratio values found, " "of which the minimum value will be used."), {'num_values': num_values}) try: ratio = float(min(aggregate_vals)) except ValueError as e: LOG.warning(_("Could not decode cpu_allocation_ratio: '%s'"), e) ratio = CONF.cpu_allocation_ratio return ratio
def host_passes(self, host_state, filter_properties): spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') if not availability_zone: return True context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key='availability_zone') if 'availability_zone' in metadata: hosts_passes = availability_zone in metadata['availability_zone'] host_az = metadata['availability_zone'] else: hosts_passes = availability_zone == CONF.default_availability_zone host_az = CONF.default_availability_zone if not hosts_passes: LOG.debug( "Availability Zone '%(az)s' requested. " "%(host_state)s has AZs: %(host_az)s", { 'host_state': host_state, 'az': availability_zone, 'host_az': host_az }) return hosts_passes
def _get_cpu_allocation_ratio(self, host_state, filter_properties): context = filter_properties['context'].elevated() # TODO(uni): DB query in filter is a performance hit, especially for # system with lots of hosts. Will need a general solution here to fix # all filters with aggregate DB call things. metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='cpu_allocation_ratio') aggregate_vals = metadata.get('cpu_allocation_ratio', set()) num_values = len(aggregate_vals) if num_values == 0: return CONF.cpu_allocation_ratio if num_values > 1: LOG.warning(_("%(num_values)d ratio values found, " "of which the minimum value will be used."), {'num_values': num_values}) try: ratio = min(map(float, aggregate_vals)) except ValueError as e: LOG.warning(_("Could not decode cpu_allocation_ratio: '%s'"), e) ratio = CONF.cpu_allocation_ratio return ratio
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get('instance_type') if 'extra_specs' not in instance_type: return True context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, req in instance_type['extra_specs'].iteritems(): # NOTE(jogo) any key containing a scope (scope is terminated # by a `:') will be ignored by this filter. (bug 1039386) if key.count(':'): continue aggregate_vals = metadata.get(key, None) if not aggregate_vals: LOG.debug(_("%(host_state)s fails instance_type extra_specs " "requirements. Extra_spec %(key)s is not in aggregate."), {'host_state': host_state, 'key': key}) return False for aggregate_val in aggregate_vals: if extra_specs_ops.match(aggregate_val, req): break else: LOG.debug(_("%(host_state)s fails instance_type extra_specs " "requirements. '%(aggregate_vals)s' do not " "match '%(req)s'"), {'host_state': host_state, 'req': req, 'aggregate_vals': aggregate_vals}) return False return True
def get_host_availability_zone(context, host): metadata = db.aggregate_metadata_get_by_host(context, host, key='availability_zone') if 'availability_zone' in metadata: return list(metadata['availability_zone'])[0] else: return CONF.default_availability_zone
def test_aggregate_metdata_get_by_host_with_key(self): """Ensure we can get aggregates by host.""" ctxt = context.get_admin_context() values = {"name": "fake_aggregate2", "availability_zone": "fake_avail_zone"} values2 = {"name": "fake_aggregate3", "availability_zone": "fake_avail_zone"} a1 = _create_aggregate_with_hosts(context=ctxt) a2 = _create_aggregate_with_hosts(context=ctxt, values=values) a3 = _create_aggregate_with_hosts( context=ctxt, values=values2, hosts=["foo.openstack.org"], metadata={"good": "value"} ) r1 = db.aggregate_metadata_get_by_host(ctxt, "foo.openstack.org", key="good") self.assertEqual(r1["good"], set(["value"])) self.assertFalse("fake_key1" in r1) # Delete metadata db.aggregate_metadata_delete(ctxt, a3.id, "good") r2 = db.aggregate_metadata_get_by_host(ctxt, "foo.openstack.org", key="good") self.assertFalse("good" in r2)
def host_passes(self, host_state, filter_properties): context = filter_properties["context"].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key="availability_zone") if CONF.cloud_burst: return CONF.cloud_burst_availability_zone in metadata["availability_zone"] else: return CONF.cloud_burst_availability_zone not in metadata["availability_zone"] return True
def host_passes(self, host_state, filter_properties): context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key='availability_zone') if CONF.cloud_burst: return CONF.cloud_burst_availability_zone in metadata['availability_zone'] else: return CONF.cloud_burst_availability_zone not in metadata['availability_zone'] return True
def get_host_availability_zone(context, host, conductor_api=None): if conductor_api: metadata = conductor_api.aggregate_metadata_get_by_host(context, host, key="availability_zone") else: metadata = db.aggregate_metadata_get_by_host(context, host, key="availability_zone") if "availability_zone" in metadata: az = list(metadata["availability_zone"])[0] else: az = CONF.default_availability_zone return az
def test_aggregate_metdata_get_by_host_with_key(self): """Ensure we can get aggregates by host.""" ctxt = context.get_admin_context() values = {'name': 'fake_aggregate2', 'availability_zone': 'fake_avail_zone', } values2 = {'name': 'fake_aggregate3', 'availability_zone': 'fake_avail_zone', } a1 = _create_aggregate_with_hosts(context=ctxt) a2 = _create_aggregate_with_hosts(context=ctxt, values=values) a3 = _create_aggregate_with_hosts(context=ctxt, values=values2, hosts=['foo.openstack.org'], metadata={'good': 'value'}) r1 = db.aggregate_metadata_get_by_host(ctxt, 'foo.openstack.org', key='good') self.assertEqual(r1['good'], set(['value'])) self.assertFalse('fake_key1' in r1) # Delete metadata db.aggregate_metadata_delete(ctxt, a3.id, 'good') r2 = db.aggregate_metadata_get_by_host(ctxt, 'foo.openstack.org', key='good') self.assertFalse('good' in r2)
def get_host_availability_zone(context, host, conductor_api=None): if conductor_api: metadata = conductor_api.aggregate_metadata_get_by_host( context, host, key='availability_zone') else: metadata = db.aggregate_metadata_get_by_host( context, host, key='availability_zone') if 'availability_zone' in metadata: return list(metadata['availability_zone'])[0] else: return CONF.default_availability_zone
def get_host_availability_zone(context, host, conductor_api=None): if conductor_api: metadata = conductor_api.aggregate_metadata_get_by_host( context, host, key='availability_zone') else: metadata = db.aggregate_metadata_get_by_host( context, host, key='availability_zone') if 'availability_zone' in metadata: return list(metadata['availability_zone'])[0] else: return CONF.default_availability_zone
def test_aggregate_metdata_get_by_host(self): """Ensure we can get aggregates by host.""" ctxt = context.get_admin_context() values = {"name": "fake_aggregate2", "availability_zone": "fake_avail_zone"} values2 = {"name": "fake_aggregate3", "availability_zone": "fake_avail_zone"} a1 = _create_aggregate_with_hosts(context=ctxt) a2 = _create_aggregate_with_hosts(context=ctxt, values=values) a3 = _create_aggregate_with_hosts( context=ctxt, values=values2, hosts=["bar.openstack.org"], metadata={"badkey": "bad"} ) r1 = db.aggregate_metadata_get_by_host(ctxt, "foo.openstack.org") self.assertEqual(r1["fake_key1"], set(["fake_value1"])) self.assertFalse("badkey" in r1)
def test_aggregate_metdata_get_by_host(self): """Ensure we can get aggregates by host.""" ctxt = context.get_admin_context() values = {'name': 'fake_aggregate2', 'availability_zone': 'fake_avail_zone', } values2 = {'name': 'fake_aggregate3', 'availability_zone': 'fake_avail_zone', } a1 = _create_aggregate_with_hosts(context=ctxt) a2 = _create_aggregate_with_hosts(context=ctxt, values=values) a3 = _create_aggregate_with_hosts(context=ctxt, values=values2, hosts=['bar.openstack.org'], metadata={'badkey': 'bad'}) r1 = db.aggregate_metadata_get_by_host(ctxt, 'foo.openstack.org') self.assertEqual(r1['fake_key1'], set(['fake_value1'])) self.assertFalse('badkey' in r1)
def host_passes(self, host_state, filter_properties): spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') if availability_zone: context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='availability_zone') if 'availability_zone' in metadata: return availability_zone in metadata['availability_zone'] else: return availability_zone == CONF.default_availability_zone return False return True
def host_passes(self, host_state, filter_properties): spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') if availability_zone: context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host( context, host_state.host, key='availability_zone') if 'availability_zone' in metadata: return availability_zone in metadata['availability_zone'] else: return availability_zone == CONF.default_availability_zone return True
def host_passes(self, host_state, filter_properties): spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) availability_zone = props.get('availability_zone') # Must provide an availability zone if not availability_zone: return False context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key='availability_zone') if 'availability_zone' in metadata: return self.match(availability_zone, metadata['availability_zone']) else: return availability_zone == CONF.default_availability_zone
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get("instance_type") if "extra_specs" not in instance_type: return True context = filter_properties["context"].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, req in instance_type["extra_specs"].iteritems(): # Either not scope format, or aggregate_instance_extra_specs scope scope = key.split(":", 1) if len(scope) > 1: if scope[0] != _SCOPE: continue else: del scope[0] key = scope[0] aggregate_vals = metadata.get(key, None) if not aggregate_vals: LOG.debug( _( "%(host_state)s fails instance_type extra_specs " "requirements. Extra_spec %(key)s is not in aggregate." ), {"host_state": host_state, "key": key}, ) return False for aggregate_val in aggregate_vals: if extra_specs_ops.match(aggregate_val, req): break else: LOG.debug( _( "%(host_state)s fails instance_type extra_specs " "requirements. '%(aggregate_vals)s' do not " "match '%(req)s'" ), {"host_state": host_state, "req": req, "aggregate_vals": aggregate_vals}, ) return False return True
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get('instance_type') if 'extra_specs' not in instance_type: return True context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, req in instance_type['extra_specs'].iteritems(): # Either not scope format, or aggregate_instance_extra_specs scope scope = key.split(':', 1) if len(scope) > 1: if scope[0] != _SCOPE: continue else: del scope[0] key = scope[0] aggregate_vals = metadata.get(key, None) if not aggregate_vals: LOG.debug( _("%(host_state)s fails instance_type extra_specs " "requirements. Extra_spec %(key)s is not in aggregate."), { 'host_state': host_state, 'key': key }) return False for aggregate_val in aggregate_vals: if extra_specs_ops.match(aggregate_val, req): break else: LOG.debug( _("%(host_state)s fails instance_type extra_specs " "requirements. '%(aggregate_vals)s' do not " "match '%(req)s'"), { 'host_state': host_state, 'req': req, 'aggregate_vals': aggregate_vals }) return False return True
def host_passes(self, host_state, filter_properties): """If a host is in an aggregate that has the metadata key "filter_tenant_id" it can only create instances from that tenant(s). A host can be in different aggregates. If a host doesn't belong to an aggregate with the metadata key "filter_tenant_id" it can create instances from all tenants. """ spec = filter_properties.get("request_spec", {}) props = spec.get("instance_properties", {}) tenant_id = props.get("project_id") context = filter_properties["context"].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key="filter_tenant_id") if metadata != {}: if tenant_id not in metadata["filter_tenant_id"]: LOG.debug(_("%(host_state)s fails tenant id on " "aggregate"), locals()) return False return True
def host_passes(self, host_state, filter_properties): """If a host is in an aggregate that has the metadata key "filter_tenant_id" it can only create instances from that tenant(s). A host can be in different aggregates. If a host doesn't belong to an aggregate with the metadata key "filter_tenant_id" it can create instances from all tenants. """ spec = filter_properties.get('request_spec', {}) props = spec.get('instance_properties', {}) tenant_id = props.get('project_id') context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host, key="filter_tenant_id") if metadata != {}: if tenant_id not in metadata["filter_tenant_id"]: LOG.debug(_("%s fails tenant id on aggregate"), host_state) return False return True
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get('instance_type') if 'extra_specs' not in instance_type: return True context = filter_properties['context'].elevated() metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, value in instance_type['extra_specs'].iteritems(): aggregate_value = metadata.get(key, None) if not aggregate_value or value not in aggregate_value: LOG.debug(_("%(host_state)s fails " "AggregateInstanceExtraSpecsFilter requirements, " "missing %(key)s,'%(value)s'=" "'%(aggregate_value)s'"), locals()) return False return True
def host_passes(self, host_state, filter_properties): """Return a list of hosts that can create instance_type Check that the extra specs associated with the instance type match the metadata provided by aggregates. If not present return False. """ instance_type = filter_properties.get('instance_type') if 'extra_specs' not in instance_type: return True context = filter_properties['context'] metadata = db.aggregate_metadata_get_by_host(context, host_state.host) for key, req in instance_type['extra_specs'].iteritems(): # Either not scope format, or aggregate_instance_extra_specs scope scope = key.split(':', 1) if len(scope) > 1: if scope[0] != _SCOPE: continue else: del scope[0] key = scope[0] aggregate_vals = metadata.get(key, None) if not aggregate_vals: LOG.debug("%(host_state)s fails instance_type extra_specs " "requirements. Extra_spec %(key)s is not in aggregate.", {'host_state': host_state, 'key': key}) return False for aggregate_val in aggregate_vals: if extra_specs_ops.match(aggregate_val, req): break else: LOG.debug("%(host_state)s fails instance_type extra_specs " "requirements. '%(aggregate_vals)s' do not " "match '%(req)s'", {'host_state': host_state, 'req': req, 'aggregate_vals': aggregate_vals}) return False return True
def get_host_availability_zone(context, host): metadata = db.aggregate_metadata_get_by_host(context.get_admin_context(), host, key="availability_zone") if "availability_zone" in metadata: return list(metadata["availability_zone"])[0] else: return CONF.default_availability_zone
def test_aggregate_metadata_get_by_host(self): self.mox.StubOutWithMock(db, "aggregate_metadata_get_by_host") db.aggregate_metadata_get_by_host(self.context, "host", "key").AndReturn("result") self.mox.ReplayAll() result = self.conductor.aggregate_metadata_get_by_host(self.context, "host", "key") self.assertEqual(result, "result")