diff --git a/neat/globals/manager.py b/neat/globals/manager.py index 7b99511..5ec6199 100644 --- a/neat/globals/manager.py +++ b/neat/globals/manager.py @@ -364,19 +364,11 @@ def execute_underload(config, state, host): if log.isEnabledFor(logging.INFO): log.info('Underload: obtained a new placement %s', str(placement)) - active_hosts = hosts_cpu_total.keys() - inactive_hosts = list(set(state['compute_hosts']) - set(active_hosts)) if not placement: log.info('Nothing to migrate') else: migrate_vms(state['nova'], placement) - active_hosts.remove(underloaded_host) - inaction_hosts.append(underloaded_host) - - log_host_states(state['db'], active_hosts, inactive_hosts) - - # TODO: initiate VM migrations according to the obtained placement - # Switch of the underloaded host when the migrations are completed + switch_hosts_off(config['sleep_command'], [underloaded_host]) return state @@ -585,16 +577,12 @@ def execute_overload(config, state, vm_uuids): if not placement: log.info('Nothing to migrate') else: + activated_hosts = list( + set(inactive_hosts_cpu.keys()).intersection( + set(placement.values()))) + switch_hosts_on(activated_hosts) migrate_vms(state['nova'], placement) - inactive_hosts = list(set(inactive_hosts_cpu.keys()) - \ - set(placement.values()) - active_hosts = list(set(state['compute_hosts']) - set(inactive_hosts)) - log_host_states(state['db'], active_hosts, inactive_hosts) - - # Switch on the inactive hosts required to accommodate the VMs - # TODO: initiate VM migrations according to the obtained placement - return state @@ -672,19 +660,30 @@ def migrate_vms(nova, placement): @contract -def log_host_states(db, active_hosts, inactive_hosts): - """ Log the host states into the database. +def switch_hosts_off(db, sleep_command, hosts): + """ Switch hosts to a low-power mode. :param db: The database object. :type db: Database - :param active_hosts: A list of active hosts. - :type active_hosts: list(str) + :param sleep_command: A Shell command to switch off a host. + :type sleep_command: str - :param inactive_hosts: A list of inactive hosts. - :type inactive_hosts: list(str) + :param hosts: A list of hosts to switch off. + :type hosts: list(str) """ - hosts = dict((x, 1) for x in active_hosts) - hosts.update(dict((x, 0) for x in inactive_hosts)) - db.insert_host_states(hosts) - + # TODO: implement running the sleep command over SSH + db.insert_host_states(dict((x, 0) for x in hosts)) + + +@contract +def switch_hosts_on(db, hosts): + """ Switch hosts to the active mode. + + :param db: The database object. + :type db: Database + + :param hosts: A list of hosts to switch on. + :type hosts: list(str) + """ + db.insert_host_states(dict((x, 1) for x in hosts)) diff --git a/tests/globals/test_manager.py b/tests/globals/test_manager.py index b19da3b..a744434 100644 --- a/tests/globals/test_manager.py +++ b/tests/globals/test_manager.py @@ -227,32 +227,32 @@ class GlobalManager(TestCase): once() manager.service() - # @qc(20) - # def vms_by_host( - # x=dict_( - # keys=str_(of='abc123-', min_length=36, max_length=36), - # values=str_(of='abc123-', min_length=10, max_length=10), - # min_length=0, max_length=3 - # ), - # y=list_(str_(of='abc123-', min_length=36, max_length=36), - # min_length=0, max_length=3), - # host=str_(of='abc123-', min_length=5, max_length=5) - # ): - # with MockTransaction: - # extra_vms = {} - # for vm in y: - # extra_vms[vm] = host - # x.update(extra_vms) - # vms = [] - # for vm_uuid, h in x.items(): - # vm = mock(vm_uuid) - # vm.id = vm_uuid - # expect(manager).vm_hostname(vm).and_return(h).once() - # vms.append(vm) - # nova = mock('nova') - # nova.servers = mock('servers') - # expect(nova.servers).list().and_return(vms).once() - # assert set(manager.vms_by_host(nova, host)) == set(y) + @qc(20) + def vms_by_host( + x=dict_( + keys=str_(of='abc123-', min_length=36, max_length=36), + values=str_(of='abc123-', min_length=10, max_length=10), + min_length=0, max_length=3 + ), + y=list_(str_(of='abc123-', min_length=36, max_length=36), + min_length=0, max_length=3), + host=str_(of='abc123-', min_length=5, max_length=5) + ): + with MockTransaction: + extra_vms = {} + for vm in y: + extra_vms[vm] = host + x.update(extra_vms) + vms = [] + for vm_uuid, h in x.items(): + vm = mock(vm_uuid) + vm.id = vm_uuid + expect(manager).vm_hostname(vm).and_return(h).once() + vms.append(vm) + nova = mock('nova') + nova.servers = mock('servers') + expect(nova.servers).list().and_return(vms).once() + assert set(manager.vms_by_host(nova, host)) == set(y) @qc(1) def vms_by_hosts( @@ -344,13 +344,18 @@ class GlobalManager(TestCase): assert manager.vms_ram_limit(nova, ['vm1', 'vm2']) == \ {'vm1': 512, 'vm2': 1024} - def test_log_host_states(self): + def test_switch_hosts_off(self): with MockTransaction: - db = db_utils.init_db('sqlite:///:memory:') - + db = db_utils.init_db('sqlite:///:memory:') expect(db).insert_host_states({ 'h1': 0, - 'h2': 1, - 'h3': 1, - 'h4': 0}).once() - manager.log_host_states(db, ['h2', 'h3'], ['h1', 'h4']) + 'h2': 0}).once() + manager.switch_hosts_off(db, 'sleep', ['h1', 'h2']) + + def test_switch_hosts_on(self): + with MockTransaction: + db = db_utils.init_db('sqlite:///:memory:') + expect(db).insert_host_states({ + 'h1': 1, + 'h2': 1}).once() + manager.switch_hosts_on(db, ['h1', 'h2'])