Files
gantt/nova/livemigration_test/UT/schedulerManager.test.py
masumotok 7660bfc125 merge recent revision(version of 2010/12/28)
Change: 
   1. Use greenthread instead of defer at nova.virt.libvirt_conn.live_migration.
   2. Move nova.scheduler.manager.live_migration to nova.scheduler.driver
   3. Move nova.scheduler.manager.has_enough_resource to nova.scheduler.driver
   4. Any check routine in nova-manage.instance.live_migration is moved to
      nova.scheduler.driver.schedule_live_migration.
2010-12-31 04:03:37 +09:00

457 lines
17 KiB
Python

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import os
import unittest
import commands
import re
import libvirt
from mock import Mock
# getting /nova-inst-dir
NOVA_DIR = os.path.abspath(sys.argv[0])
for i in range(4):
NOVA_DIR = os.path.dirname(NOVA_DIR)
try :
print
print 'Checking %s/bin/nova-manage exists, set the NOVA_DIR properly..' % NOVA_DIR
print
sys.path.append(NOVA_DIR)
from nova.scheduler.manager import SchedulerManager
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import quota
from nova import utils
from nova.auth import manager
from nova.cloudpipe import pipelib
from nova import rpc
from nova.api.ec2 import cloud
from nova.compute import power_state
from nova.db.sqlalchemy.models import *
except:
print 'set correct NOVA_DIR in this script. '
raise
class tmpStdout:
def __init__(self):
self.buffer = ""
def write(self,arg):
self.buffer += arg
def flush(self):
self.buffer = ''
class SchedulerTestFunctions(unittest.TestCase):
manager = None
# 共通の初期化処理
def setUp(self):
"""common init method. """
self.host = 'openstack2-api'
if self.manager is None:
self.manager = SchedulerManager(host=self.host)
self.setTestData()
self.setMocks()
def setTestData(self):
self.host1 = Host()
self.host1.__setitem__('name', 'host1')
self.host1.__setitem__('vcpus', 5)
self.host1.__setitem__('memory_mb', 20480)
self.host1.__setitem__('local_gb', 876)
self.host1.__setitem__('cpu_info', 1)
self.host2 = Host()
self.host2.__setitem__('name', 'host2')
self.host2.__setitem__('vcpus', 5)
self.host2.__setitem__('memory_mb', 20480)
self.host2.__setitem__('local_gb', 876)
self.host2.__setitem__('hypervisor_type', 'QEMU')
self.host2.__setitem__('hypervisor_version', 12003)
xml="<cpu><arch>x86_64</arch><model>Nehalem</model><vendor>Intel</vendor><topology sockets='2' cores='4' threads='2'/><feature name='rdtscp'/><feature name='dca'/><feature name='xtpr'/><feature name='tm2'/><feature name='est'/><feature name='vmx'/><feature name='ds_cpl'/><feature name='monitor'/><feature name='pbe'/><feature name='tm'/><feature name='ht'/><feature name='ss'/><feature name='acpi'/><feature name='ds'/><feature name='vme'/></cpu>"
self.host2.__setitem__('cpu_info', xml)
self.instance1 = Instance()
for key, val in [ ('id', 1), ('host', 'host1'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ'),
('vcpus', 3), ('memory_mb', 1024), ('local_gb', 5) ]:
self.instance1.__setitem__(key, val)
self.instance2 = Instance()
for key, val in [ ('id', 2), ('host', 'host1'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ'),
('vcpus', 3), ('memory_mb', 1024), ('local_gb', 5) ]:
self.instance2.__setitem__(key, val)
self.instance3 = Instance()
for key, val in [ ('id', 3), ('host', 'host1'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ2'),
('vcpus', 1), ('memory_mb', 1024), ('local_gb', 5),
('internal_id', 123456), ('state', 1),
('state_description', 'running') ]:
self.instance3.__setitem__(key, val)
self.instance4 = Instance()
for key, val in [ ('id', 4), ('host', 'host2'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ2'),
('vcpus', 1), ('memory_mb', 1024), ('local_gb', 5),
('internal_id', 123456), ('state', 0),
('state_description', 'running') ]:
self.instance4.__setitem__(key, val)
self.instance5 = Instance()
for key, val in [ ('id', 5), ('host', 'host2'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ2'),
('vcpus', 1), ('memory_mb', 1024), ('local_gb', 5),
('internal_id', 123456), ('state', 1),
('state_description', 'migrating') ]:
self.instance5.__setitem__(key, val)
self.instance6 = Instance()
for key, val in [ ('id', 6), ('host', 'host2'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ2'),
('vcpus', 3), ('memory_mb', 1024), ('local_gb', 5) ]:
self.instance6.__setitem__(key, val)
self.instance7 = Instance()
for key, val in [ ('id', 7), ('host', 'host1'), ('hostname', 'i-12345'),
('state', power_state.RUNNING), ('project_id', 'testPJ2'),
('vcpus', 1), ('memory_mb', 18432), ('local_gb', 5) ]:
self.instance7.__setitem__(key, val)
self.instance8 = Instance()
for key, val in [ ('id', 8), ('host', 'host1'), ('hostname', 'i-12345'),
('state', power_state.RUNNING),
('state_description', 'running'),('project_id', 'testPJ2'),
('vcpus', 1), ('memory_mb', 1024), ('local_gb', 866) ]:
self.instance8.__setitem__(key, val)
self.service1 = Service()
for key, val in [ ('id', 1), ('host', 'host1'), ('binary', 'nova-compute'),
('topic', 'compute')]:
self.service1.__setitem__(key, val)
self.service2 = Service()
for key, val in [ ('id', 2), ('host', 'host2'), ('binary', 'nova-compute'),
('topic', 'compute')]:
self.service1.__setitem__(key, val)
def setMocks(self):
self.ctxt = context.get_admin_context()
# Mocks for has_enough_resource()
db.instance_get = Mock(return_value = self.instance3)
db.host_get_by_name = Mock(return_value = self.host2)
db.instance_get_all_by_host = Mock(return_value = [self.instance4, self.instance5] )
# Mocks for live_migration
db.service_get_all_by_topic = Mock(return_value = [self.service1] )
self.manager.service_ip_up = Mock(return_value = True)
rpc.call = Mock(return_value=1)
db.instance_set_state = Mock(return_value = True)
self.manager.driver.service_is_up = Mock(return_value = True)
def check_format(self, val):
"""check result format of show_host_resource """
if dict != type(val) :
sys.stderr.write('return value is not dict')
return False
if not val.has_key('ret'):
sys.stderr.write('invalid format(missing "ret"). ')
return False
if not val['ret'] :
if not val.has_key('msg') :
sys.stderr.write( 'invalid format(missing "msg").' )
return False
else :
if not val.has_key('phy_resource') :
sys.stderr.write('invalid format(missing "phy_resource"). ')
return False
if not val.has_key('usage'):
sys.stderr.write('invalid format(missing "usage"). ')
return False
if not self._check_format(val['phy_resource']):
return False
for key, dic in val['usage'].items() :
if not self._check_format(dic):
return False
return True
def _check_format(self, val):
if dict != type(val) :
sys.stderr.write('return value is not dict')
return False
for key in ['vcpus', 'memory_mb', 'local_gb']:
if not val.has_key(key) :
sys.stderr.write('invalid format(missing "%s"). ' % key )
return False
return True
# ---> test for nova.scheduler.manager.show_host_resource()
def test01(self):
"""01: get NotFound exception when dest host not found on DB """
db.host_get_by_name = Mock( side_effect=exception.NotFound('ERR') )
result = self.manager.show_host_resource(self.ctxt, 'not-registered-host')
c1 = ( not result['ret'] )
c2 = ( 0 == result['msg'].find('No such') )
self.assertEqual(c1 and c2, True)
def test02(self):
"""02: get other exception if unexpected err. """
db.host_get_by_name = Mock( side_effect=TypeError('ERR') )
self.assertRaises(TypeError, self.manager.show_host_resource, self.ctxt, 'host1' )
def test03(self):
"""03: no instance found on dest host. """
db.host_get_by_name = Mock( return_value = self.host1 )
db.instance_get_all_by_host = Mock( return_value=[])
ret= self.manager.show_host_resource(self.ctxt, 'host1')
c1 = self.check_format(ret)
v = ret['phy_resource']
c2 = ( (5 == v['vcpus']) and (20480 == v['memory_mb']) and (876 == v['local_gb']))
c3 = ( 0 == len(ret['usage']) )
self.assertEqual(c1 and c2 and c3, True)
def test04(self):
"""04: some instance found on dest host. """
db.host_get_by_name = Mock( return_value = self.host1 )
db.instance_get_all_by_host = Mock( return_value=[ self.instance1,
self.instance2,
self.instance3] )
db.instance_get_vcpu_sum_by_host_and_project = Mock(return_value=3)
db.instance_get_memory_sum_by_host_and_project = Mock(return_value=1024)
db.instance_get_disk_sum_by_host_and_project = Mock(return_value=5)
ret= self.manager.show_host_resource(self.ctxt, 'host1')
c1 = self.check_format(ret)
v = ret['phy_resource']
c2 = ( (5 == v['vcpus']) and (20480 == v['memory_mb']) and (876 == v['local_gb']))
c3 = ( 2 == len(ret['usage']) )
c4 = ( self.instance1['project_id'] in ret['usage'].keys())
c5 = ( self.instance3['project_id'] in ret['usage'].keys())
self.assertEqual(c1 and c2 and c3 and c4 and c5, True)
# ---> test for nova.scheduler.manager.has_enough_resource()
def test05(self):
"""05: when cpu is exccded some instance found on dest host. """
db.instance_get = Mock(return_value = self.instance6)
try :
self.manager.driver.has_enough_resource(self.ctxt, 'i-12345', 'host1')
except exception.NotEmpty, e:
# dont do e.message.find(), because the below message is occured.
# DeprecationWarning: BaseException.message has been deprecated
# as of Python 2.6
c1 = ( 0 < str(e.args).find('doesnt have enough resource') )
self.assertTrue(c1, True)
return False
def test06(self):
"""06: when memory is exccded some instance found on dest host. """
db.instance_get = Mock(return_value = self.instance7)
try :
self.manager.driver.has_enough_resource(self.ctxt, 'i-12345', 'host1')
except exception.NotEmpty, e:
c1 = ( 0 <= str(e.args).find('doesnt have enough resource') )
self.assertTrue(c1, True)
return False
def test07(self):
"""07: when hdd is exccded some instance found on dest host. """
db.instance_get = Mock(return_value = self.instance8)
try :
self.manager.driver.has_enough_resource(self.ctxt, 'i-12345', 'host1')
except exception.NotEmpty, e:
c1 = ( 0 <= str(e.args).find('doesnt have enough resource') )
self.assertTrue(c1, True)
return False
def test08(self):
"""08: everything goes well. (instance_get_all_by_host returns list)"""
ret= self.manager.driver.has_enough_resource(self.ctxt, 'i-12345', 'host1')
self.assertEqual(ret, None)
def test09(self):
"""09: everything goes well(instance_get_all_by_host returns[]). """
db.instance_get_all_by_host = Mock(return_value = [] )
ret= self.manager.driver.has_enough_resource(self.ctxt, 'i-12345', 'host1')
self.assertEqual(ret, None)
# ---> test for nova.scheduler.manager.live_migration()
def test10(self):
"""10: instance_get issues NotFound. """
db.instance_get = Mock(side_effect=exception.NotFound("ERR"))
self.assertRaises(exception.NotFound,
self.manager.driver.schedule_live_migration,
self.ctxt,
'i-12345',
'host1')
def test11(self):
"""11: instance_get issues Unexpected error. """
db.instance_get = Mock(side_effect=TypeError("ERR"))
self.assertRaises(TypeError,
self.manager.driver.schedule_live_migration,
self.ctxt,
'i-12345',
'host1')
def test12(self):
"""12: instance state is not power_state.RUNNING. """
db.instance_get = Mock(return_value=self.instance4)
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host1')
except exception.Invalid, e:
c1 = (0 <= str(e.args).find('is not running'))
self.assertTrue(c1, True)
return False
def test13(self):
"""13: instance state_description is not running. """
db.instance_get = Mock(return_value=self.instance5)
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host1')
except exception.Invalid, e:
c1 = (0 <= str(e.args).find('is not running'))
self.assertTrue(c1, True)
return False
def test14(self):
"""14: dest is not compute node.
(dest is not included in the result of db.service_get_all_by_topic)
"""
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
except exception.Invalid, e:
c1 = (0 <= str(e.args).find('must be compute node'))
self.assertTrue(c1, True)
return False
def test15(self):
""" 15: dest is not alive.(service_is up returns False) """
self.manager.driver.service_is_up = Mock(return_value=False)
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
except exception.Invalid, e:
c1 = (0 <= str(e.args).find('is not alive'))
self.assertTrue(c1, True)
return False
# Cannot test the case of hypervisor type difference and hypervisor
# version difference, since we cannot set different mocks to same method..
def test16(self):
""" 16: stored "cpuinfo" is not string """
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
except exception.Invalid, e:
c1 = (0 <= str(e.args).find('Unexpected err') )
self.assertTrue(c1, True)
return False
def test17(self):
"""17: rpc.call raises RemoteError(Unexpected error occurs when executing compareCPU) """
rpc.call = Mock(return_value = rpc.RemoteError(libvirt.libvirtError, 'val', 'traceback'))
self.assertRaises(rpc.RemoteError,
self.manager.driver.schedule_live_migration,
self.ctxt,
'i-12345',
'host2')
def test18(self):
"""18: rpc.call returns 0 (cpu is not compatible between src and dest) """
rpc.call = Mock(return_value = 0)
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
except exception.Invalid, e:
c1 = ( 0 <= str(e.args).find('doesnt have compatibility to'))
self.assertTrue(c1, True)
return False
def test19(self):
"""19: raise NotEmpty if host doesnt have enough resource. """
db.instance_get = Mock(return_value = self.instance8)
try :
self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
except exception.NotEmpty, e:
c1 = ( 0 <= str(e.args).find('doesnt have enough resource') )
self.assertTrue(c1, True)
return False
def test20(self):
"""20: everything goes well. """
#db.instance_get = Mock(return_value = self.instance8)
ret= self.manager.driver.schedule_live_migration(self.ctxt, 'i-12345', 'host2')
self.assertEqual(ret, self.instance8['host'])
def tearDown(self):
"""common terminating method. """
#sys.stdout = self.stdoutBak
pass
if __name__ == '__main__':
#unittest.main()
suite = unittest.TestLoader().loadTestsFromTestCase(SchedulerTestFunctions)
unittest.TextTestRunner(verbosity=3).run(suite)