text: # Copyright (c) 2011 OpenStack, LLC
  # All Rights Reserved.
  #
  #    Licensed under the Apache License, Version 2.0 (the "License"); you may
  #    not use this file except in compliance with the License. You may obtain
  #    a copy of the License at
  #
  #         http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  #    License for the specific language governing permissions and limitations
  #    under the License.
  """
  Tests For HostManager
  """
  
  import datetime
  
  from nova import db
  from nova import exception
  from nova.openstack.common import timeutils
  from nova.scheduler import host_manager
  from nova import test
  from nova.tests.scheduler import fakes
  
  
  class ComputeFilterClass1(object):
      def host_passes(self, *args, **kwargs):
          pass
  
  
  class ComputeFilterClass2(object):
      def host_passes(self, *args, **kwargs):
          pass
  
  
  class HostManagerTestCase(test.TestCase):
      """Test case for HostManager class"""
  
      def setUp(self):
          super(HostManagerTestCase, self).setUp()
          self.host_manager = host_manager.HostManager()
  
      def test_choose_host_filters_not_found(self):
          self.flags(scheduler_default_filters='ComputeFilterClass3')
          self.host_manager.filter_classes = [ComputeFilterClass1,
                  ComputeFilterClass2]
          self.assertRaises(exception.SchedulerHostFilterNotFound,
                  self.host_manager._choose_host_filters, None)
  
      def test_choose_host_filters(self):
          self.flags(scheduler_default_filters=['ComputeFilterClass2'])
          self.host_manager.filter_classes = [ComputeFilterClass1,
                  ComputeFilterClass2]
  
          # Test 'compute' returns 1 correct function
          filter_fns = self.host_manager._choose_host_filters(None)
          self.assertEqual(len(filter_fns), 1)
          self.assertEqual(filter_fns[0].__func__,
                  ComputeFilterClass2.host_passes.__func__)
  
      def test_filter_hosts(self):
          topic = 'fake_topic'
  
          filters = ['fake-filter1', 'fake-filter2']
          fake_host1 = host_manager.HostState('host1', topic)
          fake_host2 = host_manager.HostState('host2', topic)
          hosts = [fake_host1, fake_host2]
          filter_properties = 'fake_properties'
  
          self.mox.StubOutWithMock(self.host_manager,
                  '_choose_host_filters')
          self.mox.StubOutWithMock(fake_host1, 'passes_filters')
          self.mox.StubOutWithMock(fake_host2, 'passes_filters')
  
          self.host_manager._choose_host_filters(None).AndReturn(filters)
          fake_host1.passes_filters(filters, filter_properties).AndReturn(
                  False)
          fake_host2.passes_filters(filters, filter_properties).AndReturn(
                  True)
  
          self.mox.ReplayAll()
          filtered_hosts = self.host_manager.filter_hosts(hosts,
                  filter_properties, filters=None)
          self.assertEqual(len(filtered_hosts), 1)
          self.assertEqual(filtered_hosts[0], fake_host2)
  
      def test_update_service_capabilities(self):
          service_states = self.host_manager.service_states
          self.assertDictMatch(service_states, {})
          self.mox.StubOutWithMock(timeutils, 'utcnow')
          timeutils.utcnow().AndReturn(31337)
          timeutils.utcnow().AndReturn(31338)
          timeutils.utcnow().AndReturn(31339)
  
          host1_compute_capabs = dict(free_memory=1234, host_memory=5678,
                  timestamp=1)
          host1_volume_capabs = dict(free_disk=4321, timestamp=1)
          host2_compute_capabs = dict(free_memory=8756, timestamp=1)
  
          self.mox.ReplayAll()
          self.host_manager.update_service_capabilities('compute', 'host1',
                  host1_compute_capabs)
          self.host_manager.update_service_capabilities('volume', 'host1',
                  host1_volume_capabs)
          self.host_manager.update_service_capabilities('compute', 'host2',
                  host2_compute_capabs)
  
          # Make sure dictionary isn't re-assigned
          self.assertEqual(self.host_manager.service_states, service_states)
          # Make sure original dictionary wasn't copied
          self.assertEqual(host1_compute_capabs['timestamp'], 1)
  
          host1_compute_capabs['timestamp'] = 31337
          host1_volume_capabs['timestamp'] = 31338
          host2_compute_capabs['timestamp'] = 31339
  
          expected = {'host1': {'compute': host1_compute_capabs,
                                'volume': host1_volume_capabs},
                      'host2': {'compute': host2_compute_capabs}}
          self.assertDictMatch(service_states, expected)
  
      def test_host_service_caps_stale(self):
          self.flags(periodic_interval=5)
  
          host1_compute_capabs = dict(free_memory=1234, host_memory=5678,
                  timestamp=datetime.datetime.fromtimestamp(3000))
          host1_volume_capabs = dict(free_disk=4321,
                  timestamp=datetime.datetime.fromtimestamp(3005))
          host2_compute_capabs = dict(free_memory=8756,
                  timestamp=datetime.datetime.fromtimestamp(3010))
  
          service_states = {'host1': {'compute': host1_compute_capabs,
                                      'volume': host1_volume_capabs},
                            'host2': {'compute': host2_compute_capabs}}
  
          self.host_manager.service_states = service_states
  
          self.mox.StubOutWithMock(timeutils, 'utcnow')
          timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
          timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
          timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
  
          self.mox.ReplayAll()
          res1 = self.host_manager.host_service_caps_stale('host1', 'compute')
          res2 = self.host_manager.host_service_caps_stale('host1', 'volume')
          res3 = self.host_manager.host_service_caps_stale('host2', 'compute')
  
          self.assertEqual(res1, True)
          self.assertEqual(res2, False)
          self.assertEqual(res3, False)
  
      def test_delete_expired_host_services(self):
          host1_compute_capabs = dict(free_memory=1234, host_memory=5678,
                  timestamp=datetime.datetime.fromtimestamp(3000))
          host1_volume_capabs = dict(free_disk=4321,
                  timestamp=datetime.datetime.fromtimestamp(3005))
          host2_compute_capabs = dict(free_memory=8756,
                  timestamp=datetime.datetime.fromtimestamp(3010))
  
          service_states = {'host1': {'compute': host1_compute_capabs,
                                      'volume': host1_volume_capabs},
                            'host2': {'compute': host2_compute_capabs}}
          self.host_manager.service_states = service_states
  
          to_delete = {'host1': {'volume': host1_volume_capabs},
                       'host2': {'compute': host2_compute_capabs}}
  
          self.host_manager.delete_expired_host_services(to_delete)
          # Make sure dictionary isn't re-assigned
          self.assertEqual(self.host_manager.service_states, service_states)
  
          expected = {'host1': {'compute': host1_compute_capabs}}
          self.assertEqual(service_states, expected)
  
      def test_get_service_capabilities(self):
          host1_compute_capabs = dict(free_memory=1000, host_memory=5678,
                  timestamp=datetime.datetime.fromtimestamp(3000))
          host1_volume_capabs = dict(free_disk=4321,
                  timestamp=datetime.datetime.fromtimestamp(3005))
          host2_compute_capabs = dict(free_memory=8756,
                  timestamp=datetime.datetime.fromtimestamp(3010))
          host2_volume_capabs = dict(free_disk=8756,
                  enabled=False,
                  timestamp=datetime.datetime.fromtimestamp(3010))
          host3_compute_capabs = dict(free_memory=1234, host_memory=4000,
                  timestamp=datetime.datetime.fromtimestamp(3010))
          host3_volume_capabs = dict(free_disk=2000,
                  timestamp=datetime.datetime.fromtimestamp(3010))
  
          service_states = {'host1': {'compute': host1_compute_capabs,
                                      'volume': host1_volume_capabs},
                            'host2': {'compute': host2_compute_capabs,
                                      'volume': host2_volume_capabs},
                            'host3': {'compute': host3_compute_capabs,
                                      'volume': host3_volume_capabs}}
          self.host_manager.service_states = service_states
  
          info = {'called': 0}
  
          # This tests with 1 volume disabled (host2), and 1 volume node
          # as stale (host1)
          def _fake_host_service_caps_stale(host, service):
              info['called'] += 1
              if host == 'host1':
                  if service == 'compute':
                      return False
                  elif service == 'volume':
                      return True
              elif host == 'host2':
                  # Shouldn't get here for 'volume' because the service
                  # is disabled
                  self.assertEqual(service, 'compute')
                  return False
              self.assertEqual(host, 'host3')
              return False
  
          self.stubs.Set(self.host_manager, 'host_service_caps_stale',
                  _fake_host_service_caps_stale)
  
          self.mox.StubOutWithMock(self.host_manager,
                  'delete_expired_host_services')
          self.host_manager.delete_expired_host_services({'host1': ['volume']})
  
          self.mox.ReplayAll()
          result = self.host_manager.get_service_capabilities()
  
          self.assertEqual(info['called'], 5)
  
          # only 1 volume node active == 'host3', so min/max is 2000
          expected = {'volume_free_disk': (2000, 2000),
                      'compute_host_memory': (4000, 5678),
                      'compute_free_memory': (1000, 8756)}
  
          self.assertDictMatch(result, expected)
  
      def test_get_all_host_states(self):
          self.flags(reserved_host_memory_mb=512,
                  reserved_host_disk_mb=1024)
  
          context = 'fake_context'
          topic = 'compute'
  
          self.mox.StubOutWithMock(db, 'compute_node_get_all')
          self.mox.StubOutWithMock(host_manager.LOG, 'warn')
          self.mox.StubOutWithMock(db, 'instance_get_all')
  
          db.compute_node_get_all(context).AndReturn(fakes.COMPUTE_NODES)
          # Invalid service
          host_manager.LOG.warn("No service for compute ID 5")
          db.instance_get_all(context,
                  columns_to_join=['instance_type']).AndReturn(
                          fakes.INSTANCES)
  
          self.mox.ReplayAll()
          host_states = self.host_manager.get_all_host_states(context, topic)
  
          self.assertEqual(len(host_states), 4)
          # Check that .service is set properly
          for i in xrange(4):
              compute_node = fakes.COMPUTE_NODES[i]
              host = compute_node['service']['host']
              self.assertEqual(host_states[host].service,
                      compute_node['service'])
          self.assertEqual(host_states['host1'].free_ram_mb, 0)
          # 511GB
          self.assertEqual(host_states['host1'].free_disk_mb, 523264)
          self.assertEqual(host_states['host2'].free_ram_mb, 512)
          # 1023GB
          self.assertEqual(host_states['host2'].free_disk_mb, 1047552)
          self.assertEqual(host_states['host3'].free_ram_mb, 2560)
          # 3071GB
          self.assertEqual(host_states['host3'].free_disk_mb, 3144704)
          self.assertEqual(host_states['host4'].free_ram_mb, 7680)
          # 8191GB
          self.assertEqual(host_states['host4'].free_disk_mb, 8387584)
  
  
  class HostStateTestCase(test.TestCase):
      """Test case for HostState class"""
  
      # update_from_compute_node() and consume_from_instance() are tested
      # in HostManagerTestCase.test_get_all_host_states()
  
      def test_host_state_passes_filters_passes(self):
          fake_host = host_manager.HostState('host1', 'compute')
          filter_properties = {}
  
          cls1 = ComputeFilterClass1()
          cls2 = ComputeFilterClass2()
          self.mox.StubOutWithMock(cls1, 'host_passes')
          self.mox.StubOutWithMock(cls2, 'host_passes')
          filter_fns = [cls1.host_passes, cls2.host_passes]
  
          cls1.host_passes(fake_host, filter_properties).AndReturn(True)
          cls2.host_passes(fake_host, filter_properties).AndReturn(True)
  
          self.mox.ReplayAll()
          result = fake_host.passes_filters(filter_fns, filter_properties)
          self.assertTrue(result)
  
      def test_host_state_passes_filters_passes_with_ignore(self):
          fake_host = host_manager.HostState('host1', 'compute')
          filter_properties = {'ignore_hosts': ['host2']}
  
          cls1 = ComputeFilterClass1()
          cls2 = ComputeFilterClass2()
          self.mox.StubOutWithMock(cls1, 'host_passes')
          self.mox.StubOutWithMock(cls2, 'host_passes')
          filter_fns = [cls1.host_passes, cls2.host_passes]
  
          cls1.host_passes(fake_host, filter_properties).AndReturn(True)
          cls2.host_passes(fake_host, filter_properties).AndReturn(True)
  
          self.mox.ReplayAll()
          result = fake_host.passes_filters(filter_fns, filter_properties)
          self.assertTrue(result)
  
      def test_host_state_passes_filters_fails(self):
          fake_host = host_manager.HostState('host1', 'compute')
          filter_properties = {}
  
          cls1 = ComputeFilterClass1()
          cls2 = ComputeFilterClass2()
          self.mox.StubOutWithMock(cls1, 'host_passes')
          self.mox.StubOutWithMock(cls2, 'host_passes')
          filter_fns = [cls1.host_passes, cls2.host_passes]
  
          cls1.host_passes(fake_host, filter_properties).AndReturn(False)
          # cls2.host_passes() not called because of short circuit
  
          self.mox.ReplayAll()
          result = fake_host.passes_filters(filter_fns, filter_properties)
          self.assertFalse(result)
  
      def test_host_state_passes_filters_fails_from_ignore(self):
          fake_host = host_manager.HostState('host1', 'compute')
          filter_properties = {'ignore_hosts': ['host1']}
  
          cls1 = ComputeFilterClass1()
          cls2 = ComputeFilterClass2()
          self.mox.StubOutWithMock(cls1, 'host_passes')
          self.mox.StubOutWithMock(cls2, 'host_passes')
          filter_fns = [cls1.host_passes, cls2.host_passes]
  
          # cls[12].host_passes() not called because of short circuit
          # with matching host to ignore
  
          self.mox.ReplayAll()
          result = fake_host.passes_filters(filter_fns, filter_properties)
          self.assertFalse(result)
  
      def test_host_state_passes_filters_skipped_from_force(self):
          fake_host = host_manager.HostState('host1', 'compute')
          filter_properties = {'force_hosts': ['host1']}
  
          cls1 = ComputeFilterClass1()
          cls2 = ComputeFilterClass2()
          self.mox.StubOutWithMock(cls1, 'host_passes')
          self.mox.StubOutWithMock(cls2, 'host_passes')
          filter_fns = [cls1.host_passes, cls2.host_passes]
  
          # cls[12].host_passes() not called because of short circuit
          # with matching host to force
  
          self.mox.ReplayAll()
          result = fake_host.passes_filters(filter_fns, filter_properties)
          self.assertTrue(result)
  