def test_sort_combinations(self): combo1 = utils.Combination(provider='host1', instances=['server1'], leftovers=object_fakes.make_resources( vcpu=2, memory=256, disk=10)) combo2 = utils.Combination(provider='host2', instances=['server2'], leftovers=object_fakes.make_resources( vcpu=1, memory=512, disk=10)) combo3 = utils.Combination(provider='host3', instances=['server3'], leftovers=object_fakes.make_resources( vcpu=1, memory=512, disk=20)) combinations = [combo1, combo2, combo3] CONF.reaper.vcpu_sorting_priority = 2 CONF.reaper.ram_sorting_priority = 1 CONF.reaper.disk_sorting_priority = 3 result = utils.sort_combinations(combinations) self.assertEqual(combo1, result) CONF.reaper.vcpu_sorting_priority = 1 CONF.reaper.ram_sorting_priority = 2 CONF.reaper.disk_sorting_priority = 3 result = utils.sort_combinations(combinations) self.assertEqual(combo2, result) CONF.reaper.vcpu_sorting_priority = 2 CONF.reaper.ram_sorting_priority = 3 CONF.reaper.disk_sorting_priority = 1 result = utils.sort_combinations(combinations) self.assertEqual(combo2, result)
def test_get_preemptible_servers_multiple_hosts(self, mocked_find): used = object_fakes.make_resources(vcpu=7, memory=1800, disk=35) total = object_fakes.make_resources(vcpu=8, memory=2056, disk=40) rp_capabilities = object_fakes.make_capabilities(used=used, total=total) host1 = object_fakes.make_resource_provider( uuid='1', name='rp1', capabilities=rp_capabilities) host2 = object_fakes.make_resource_provider( uuid='2', name='rp2', capabilities=rp_capabilities) server1 = object_fakes.make_server( resources=object_fakes.make_resources(vcpu=1, memory=256, disk=10), uuid='server1') server2 = object_fakes.make_server( resources=object_fakes.make_resources(vcpu=1, memory=256, disk=10), uuid='server2') server3 = object_fakes.make_server( resources=object_fakes.make_resources(vcpu=1, memory=256, disk=10), uuid='server3') combo1 = utils.Combination(provider=host1, instances=[server1], leftovers=object_fakes.make_resources( vcpu=2, memory=256, disk=10)) combo2 = utils.Combination(provider=host2, instances=[server2, server3], leftovers=object_fakes.make_resources( vcpu=2, memory=256, disk=10)) mocked_find.side_effect = [combo1, combo2, None] fake_hosts = [mock.Mock()] fake_projects = [mock.Mock()] requested = object_fakes.make_resources(vcpu=2, memory=512, disk=10) # Make sure that in watermark mode even if we don't have enough # resources, no exception is raised. sel_hosts, sel_servers = self.strategy.get_preemptible_servers( requested, fake_hosts, 2, fake_projects) self.assertEqual([host1, host2], sel_hosts) self.assertEqual([server1, server2, server3], sel_servers)
def test_get_preemptible_servers(self, mocked_find): used = object_fakes.make_resources(vcpu=7, memory=1800, disk=35) total = object_fakes.make_resources(vcpu=8, memory=2056, disk=40) rp_capabilities = object_fakes.make_capabilities(used=used, total=total) host = object_fakes.make_resource_provider( uuid='1', name='rp1', capabilities=rp_capabilities) server = object_fakes.make_server( resources=object_fakes.make_resources(vcpu=1, memory=256, disk=10), uuid='server1') combo = utils.Combination(provider=host, instances=[server], leftovers=object_fakes.make_resources( vcpu=2, memory=256, disk=10)) mocked_find.return_value = combo fake_hosts = [mock.Mock()] fake_projects = [mock.Mock()] requested = object_fakes.make_resources(vcpu=2, memory=512, disk=10) sel_hosts, sel_servers = self.strategy.get_preemptible_servers( requested, fake_hosts, 1, fake_projects) self.assertEqual([host], sel_hosts) self.assertEqual([server], sel_servers)
def find_matching_server_combinations(self, hosts, requested, projects): """Find the best matching combination The purpose of this feature is to eliminate the idle resources. So the best matching combination is the one that makes use of the most available space on a host. """ only_free = False combinations = list() timeout = CONF.reaper.parallel_timeout @aardvark_utils.timeit @aardvark_utils.parallelize(max_results=len(hosts), timeout=timeout) def populate_hosts(hosts): valid = [] for host in hosts: if host.disabled: LOG.info("Skipping host %s because it is disabled", host.name) continue self.populate_host(host, projects) valid.append(host) return valid valid = [h for h in populate_hosts(hosts)] for host in valid: LOG.debug("Checing host %s", host.name) # NOTE(ttsiouts): If free space is enough for the new server # then we should not delete any of the existing servers LOG.debug('Requested: %s, Free: %s', requested, host.free_resources) if requested <= host.free_resources: LOG.debug('Free resources enough. Requested: %s, Free: %s', requested, host.free_resources) leftovers = host.free_resources - requested combinations.append( utils.Combination(provider=host, leftovers=leftovers, instances=[])) only_free = True continue preemptible = self.filter_servers(host, requested) LOG.debug('Preemptibles: %s', preemptible) end = len(preemptible) + 1 for num in range(1, end): num_combinations = itertools.combinations(preemptible, num) for combo in num_combinations: resources = (utils.sum_resources(combo) + host.free_resources) if requested <= resources: instances = [x for x in combo] leftovers = resources - requested combinations.append( utils.Combination(provider=host, leftovers=leftovers, instances=instances)) else: LOG.debug( "Requested: %s resources: %s. combo %s, not " "selected", requested, resources, combo) if not combinations: return None if only_free: # NOTE(ttsiouts): if there is a host with free space avoid # deleting running VMs. combinations = [x for x in combinations if len(x.instances) == 0] return utils.sort_combinations(combinations)