diff options
| author | masumotok <masumotok@nttdata.co.jp> | 2010-12-24 16:06:11 +0900 |
|---|---|---|
| committer | masumotok <masumotok@nttdata.co.jp> | 2010-12-24 16:06:11 +0900 |
| commit | a32ccff2e224d0d2bf72a0471d9e9599ba4d8990 (patch) | |
| tree | 1e36103969ae096146614e1721d4d73dc94af6ef | |
| parent | 21c1ba77cdb95b95a13a81c243ac13e0cf8a632f (diff) | |
テスト項目表を再び追加した状態でコミット
| -rw-r--r-- | nova/livemigration_test/SI/picture.pptx | bin | 0 -> 137730 bytes | |||
| -rw-r--r-- | nova/livemigration_test/SI/testCase_SI.xls | bin | 0 -> 43520 bytes | |||
| -rw-r--r-- | nova/livemigration_test/SI/testParameterSheet_SI.xls | bin | 0 -> 464384 bytes | |||
| -rwxr-xr-x | nova/livemigration_test/SI/utils/demo-firstboot.sh | 39 | ||||
| -rwxr-xr-x | nova/livemigration_test/SI/utils/demo-runInstance.sh | 57 | ||||
| -rw-r--r-- | nova/livemigration_test/SI/utils/nova-manage.conf | 18 | ||||
| -rw-r--r-- | nova/livemigration_test/SI/utils/nova.conf | 10 | ||||
| -rwxr-xr-x | nova/livemigration_test/SI/utils/nova.sh | 180 | ||||
| -rwxr-xr-x | nova/livemigration_test/SI/utils/nova.sh.compute | 37 | ||||
| -rw-r--r-- | nova/livemigration_test/UT/computeManager.test.py | 411 | ||||
| -rw-r--r-- | nova/livemigration_test/UT/libvirtConnection.test.py | 372 | ||||
| -rw-r--r-- | nova/livemigration_test/UT/nova-manage.test.py | 351 | ||||
| -rw-r--r-- | nova/livemigration_test/UT/schedulerManager.test.py | 408 | ||||
| -rw-r--r-- | nova/livemigration_test/UT/testCase_UT.xls | bin | 0 -> 202752 bytes |
14 files changed, 1883 insertions, 0 deletions
diff --git a/nova/livemigration_test/SI/picture.pptx b/nova/livemigration_test/SI/picture.pptx Binary files differnew file mode 100644 index 000000000..b47bec9b5 --- /dev/null +++ b/nova/livemigration_test/SI/picture.pptx diff --git a/nova/livemigration_test/SI/testCase_SI.xls b/nova/livemigration_test/SI/testCase_SI.xls Binary files differnew file mode 100644 index 000000000..65cf96fd7 --- /dev/null +++ b/nova/livemigration_test/SI/testCase_SI.xls diff --git a/nova/livemigration_test/SI/testParameterSheet_SI.xls b/nova/livemigration_test/SI/testParameterSheet_SI.xls Binary files differnew file mode 100644 index 000000000..400b43b43 --- /dev/null +++ b/nova/livemigration_test/SI/testParameterSheet_SI.xls diff --git a/nova/livemigration_test/SI/utils/demo-firstboot.sh b/nova/livemigration_test/SI/utils/demo-firstboot.sh new file mode 100755 index 000000000..3a6f7fb0b --- /dev/null +++ b/nova/livemigration_test/SI/utils/demo-firstboot.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +DIR=/opt/nova-2010.1 + +# 1. 管理者ユーザを作成する +# nova-manage user admin ユーザ名 access-key secret-key +# +#$DIR/bin/nova-manage user admin admin admin admin + +# 2. プロジェクトを作成する +# nova-manage create project プロジェクト名 プロジェクトに属するユーザ名 +# +#$DIR/bin/nova-manage project create admin admin + +# 3. クラウドを使うための認証情報を生成する +# nova-manage project environment プロジェクト名 ユーザ名 認証情報を格納するファイル +# +#$DIR/bin/nova-manage project environment admin admin $DIR/novarc + +# 4. 認証情報の読み込み +. $DIR/novarc + +# 5. プロジェクト用仮想マシンネットワークの作成を行う +# nova-manage user admin ユーザ名 access-key secret-key +# +$DIR/bin/nova-manage network create 10.0.0.0/8 3 16 + +# 6. 初回ログインにはSSHの公開鍵認証が必要 +# +if [ "" == "`euca-describe-keypairs | grep testkey`" ]; then + euca-add-keypair testkey > testkey.pem +fi + +# 7. +for i in 172.19.0.134 172.19.0.135 172.19.0.136 172.19.0.137 ; do + sudo ip addr del $i dev eth0 2> /dev/null +done + + diff --git a/nova/livemigration_test/SI/utils/demo-runInstance.sh b/nova/livemigration_test/SI/utils/demo-runInstance.sh new file mode 100755 index 000000000..171291262 --- /dev/null +++ b/nova/livemigration_test/SI/utils/demo-runInstance.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +DIR=/opt/nova-2010.1 + +function inc_assigned(){ + assigned=`expr $assigned + 1` +} + + +# 1. 認証情報の読み込み +. $DIR/novarc + +# 3. 仮想マシンの起動 +# +ret=`euca-run-instances -t m1.small -k testkey ami-centos` +#ret=`euca-run-instances -t m1.small -k testkey ami-tiny` + +# 4. 仮想マシン用IPの確保 +# 未登録なら登録しておく +registered=`euca-describe-addresses` +for ip in 172.19.0.134 172.19.0.135 172.19.0.136 172.19.0.137 ; do + + not_registered=`echo $registered | grep $ip` + if [ "" == "$not_registered" ]; then + echo "[INFO] registed $ip" + $DIR/bin/nova-manage floating create `hostname` $ip + fi +done + +# 5. IPの割当 +echo 0 > /tmp/demo-runinstance +euca-describe-addresses | grep -v reserved | while read line; do + # 割り当てられてないものを仮想マシンに割り当てる + ip=`echo $line | cut -d ' ' -f 2` + id=`echo $ret | cut -d ' ' -f 5` + if [ "" == "`echo $id | grep i- `" ] ; then + echo "[INFO] try again" $ret + break + fi + echo "[INFO] assigned to ipaddr($ip) to instance($id) " + euca-associate-address -i $id $ip + echo 1 > /tmp/demo-runinstance + break +done + +echo $assigned +if [ 0 -eq "`cat /tmp/demo-runinstance`" ] ; then + echo "[INFO] address is full." +fi +rm -rf /tmp/demo-runinstance + + +# 6. FWの設定 +euca-authorize -P tcp -p 22 default 2> /dev/null > /dev/null +euca-authorize -P tcp -p 80 default 2> /dev/null > /dev/null +euca-authorize -P tcp -p 5555 default 2> /dev/null > /dev/null + diff --git a/nova/livemigration_test/SI/utils/nova-manage.conf b/nova/livemigration_test/SI/utils/nova-manage.conf new file mode 100644 index 000000000..9f8a02b96 --- /dev/null +++ b/nova/livemigration_test/SI/utils/nova-manage.conf @@ -0,0 +1,18 @@ +--verbose +--nodaemon +--dhcpbridge_flagfile=/etc/nova/nova-manage.conf +--FAKE_subdomain=ec2 +--libvirt_type=qemu +--no_internet_conn=True +--public_netif=eth0 +--public_interface=eth0 + +--cc-host=172.19.0.131 +--routing_source_ip=172.19.0.131 +--sql_connection=mysql://root:nova@172.19.0.131/nova +--rabbit_host=172.19.0.131 +--redis_host=172.19.0.131 +--s3_host=172.19.0.131 +--auth_driver=nova.auth.ldapdriver.LdapDriver +--ldap_url=ldap://172.19.0.131 + diff --git a/nova/livemigration_test/SI/utils/nova.conf b/nova/livemigration_test/SI/utils/nova.conf new file mode 100644 index 000000000..c66bfbc53 --- /dev/null +++ b/nova/livemigration_test/SI/utils/nova.conf @@ -0,0 +1,10 @@ +--verbose +--nodaemon +--dhcpbridge_flagfile=/opt/nova-2010.4//bin/nova.conf +--network_manager=nova.network.manager.VlanManager +--cc_host=172.19.0.131 +--routing_source_ip=172.19.0.131 +--sql_connection=mysql://root:nova@localhost/nova +--auth_driver=nova.auth.ldapdriver.LdapDriver +--libvirt_type=qemu +--public_interface=eth0 diff --git a/nova/livemigration_test/SI/utils/nova.sh b/nova/livemigration_test/SI/utils/nova.sh new file mode 100755 index 000000000..b8e2e9f26 --- /dev/null +++ b/nova/livemigration_test/SI/utils/nova.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash +DIR=`pwd` +CMD=$1 +SOURCE_BRANCH=lp:nova +if [ -n "$2" ]; then + SOURCE_BRANCH=$2 +fi +#DIRNAME=nova +DIRNAME="" +NOVA_DIR=$DIR/$DIRNAME +if [ -n "$3" ]; then + NOVA_DIR=$DIR/$3 +fi + +if [ ! -n "$HOST_IP" ]; then + # NOTE(vish): This will just get the first ip in the list, so if you + # have more than one eth device set up, this will fail, and + # you should explicitly set HOST_IP in your environment + HOST_IP=`ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` +fi + +#USE_MYSQL=${USE_MYSQL:-0} +USE_MYSQL=1 +MYSQL_PASS=${MYSQL_PASS:-nova} +TEST=${TEST:-0} +#USE_LDAP=${USE_LDAP:-0} +USE_LDAP=1 +LIBVIRT_TYPE=${LIBVIRT_TYPE:-qemu} +NET_MAN=${NET_MAN:-VlanManager} +# NOTE(vish): If you are using FlatDHCP on multiple hosts, set the interface +# below but make sure that the interface doesn't already have an +# ip or you risk breaking things. +# FLAT_INTERFACE=eth0 + +if [ "$USE_MYSQL" == 1 ]; then + SQL_CONN=mysql://root:$MYSQL_PASS@localhost/nova +else + SQL_CONN=sqlite:///$NOVA_DIR/nova.sqlite +fi + +if [ "$USE_LDAP" == 1 ]; then + AUTH=ldapdriver.LdapDriver +else + AUTH=dbdriver.DbDriver +fi + +mkdir -p /etc/nova +cat >$NOVA_DIR/bin/nova.conf << NOVA_CONF_EOF +--verbose +--nodaemon +--dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf +--network_manager=nova.network.manager.$NET_MAN +--cc_host=$HOST_IP +--routing_source_ip=$HOST_IP +--sql_connection=$SQL_CONN +--auth_driver=nova.auth.$AUTH +--libvirt_type=$LIBVIRT_TYPE +--public_interface=eth0 +NOVA_CONF_EOF + +if [ -n "$FLAT_INTERFACE" ]; then + echo "--flat_interface=$FLAT_INTERFACE" >>$NOVA_DIR/bin/nova.conf +fi + +if [ "$CMD" == "branch" ]; then + sudo apt-get install -y bzr + rm -rf $NOVA_DIR + bzr branch $SOURCE_BRANCH $NOVA_DIR + cd $NOVA_DIR + mkdir -p $NOVA_DIR/instances + mkdir -p $NOVA_DIR/networks +fi + +# You should only have to run this once +if [ "$CMD" == "install" ]; then + sudo apt-get install -y python-software-properties + sudo add-apt-repository ppa:nova-core/ppa + sudo apt-get update + sudo apt-get install -y dnsmasq kpartx kvm gawk iptables ebtables + sudo apt-get install -y user-mode-linux kvm libvirt-bin + sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server + sudo apt-get install -y lvm2 iscsitarget open-iscsi + echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget + sudo /etc/init.d/iscsitarget restart + sudo modprobe kvm + sudo /etc/init.d/libvirt-bin restart + sudo apt-get install -y python-twisted python-sqlalchemy python-mox python-greenlet python-carrot + sudo apt-get install -y python-daemon python-eventlet python-gflags python-tornado python-ipy + sudo apt-get install -y python-libvirt python-libxml2 python-routes + if [ "$USE_MYSQL" == 1 ]; then + cat <<MYSQL_PRESEED | debconf-set-selections +mysql-server-5.1 mysql-server/root_password password $MYSQL_PASS +mysql-server-5.1 mysql-server/root_password_again password $MYSQL_PASS +mysql-server-5.1 mysql-server/start_on_boot boolean true +MYSQL_PRESEED + apt-get install -y mysql-server python-mysqldb + fi + wget http://c2477062.cdn.cloudfiles.rackspacecloud.com/images.tgz + tar -C $DIR -zxf images.tgz +fi + +NL=`echo -ne '\015'` + +function screen_it { + screen -S nova -X screen -t $1 + screen -S nova -p $1 -X stuff "$2$NL" +} + +if [ "$CMD" == "run" ]; then + killall dnsmasq + screen -d -m -S nova -t nova + sleep 1 + if [ "$USE_MYSQL" == 1 ]; then + mysql -p$MYSQL_PASS -e 'DROP DATABASE nova;' + mysql -p$MYSQL_PASS -e 'CREATE DATABASE nova;' + else + rm $NOVA_DIR/nova.sqlite + fi + if [ "$USE_LDAP" == 1 ]; then + sudo $NOVA_DIR/nova/auth/slap.sh + fi + rm -rf $NOVA_DIR/instances + mkdir -p $NOVA_DIR/instances + rm -rf $NOVA_DIR/networks + mkdir -p $NOVA_DIR/networks + $NOVA_DIR/tools/clean-vlans + if [ ! -d "$NOVA_DIR/images" ]; then + #ln -s $DIR/images $NOVA_DIR/images + ln -s /opt/images $NOVA_DIR/images + fi + + if [ "$TEST" == 1 ]; then + cd $NOVA_DIR + python $NOVA_DIR/run_tests.py + cd $DIR + fi + + # create an admin user called 'admin' + $NOVA_DIR/bin/nova-manage user admin admin admin admin + # create a project called 'admin' with project manager of 'admin' + $NOVA_DIR/bin/nova-manage project create admin admin + # export environment variables for project 'admin' and user 'admin' + $NOVA_DIR/bin/nova-manage project environment admin admin $NOVA_DIR/novarc + # create a small network + $NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 1 32 + + # nova api crashes if we start it with a regular screen command, + # so send the start command by forcing text into the window. + screen_it api "$NOVA_DIR/bin/nova-api" + screen_it objectstore "$NOVA_DIR/bin/nova-objectstore" + #screen_it compute "$NOVA_DIR/bin/nova-compute" + screen_it network "$NOVA_DIR/bin/nova-network" + screen_it scheduler "$NOVA_DIR/bin/nova-scheduler" + screen_it volume "$NOVA_DIR/bin/nova-volume" + #screen_it test ". $NOVA_DIR/novarc" + screen -S nova -x +fi + +if [ "$CMD" == "run" ] || [ "$CMD" == "terminate" ]; then + # shutdown instances + . $NOVA_DIR/novarc; euca-describe-instances | grep i- | cut -f2 | xargs euca-terminate-instances + sleep 2 + # delete volumes + . $NOVA_DIR/novarc; euca-describe-volumes | grep vol- | cut -f2 | xargs -n1 euca-delete-volume +fi + +if [ "$CMD" == "run" ] || [ "$CMD" == "clean" ]; then + screen -S nova -X quit + rm *.pid* +fi + +if [ "$CMD" == "scrub" ]; then + $NOVA_DIR/tools/clean-vlans + if [ "$LIBVIRT_TYPE" == "uml" ]; then + virsh -c uml:///system list | grep i- | awk '{print \$1}' | xargs -n1 virsh -c uml:///system destroy + else + virsh list | grep i- | awk '{print \$1}' | xargs -n1 virsh destroy + fi + vblade-persist ls | grep vol- | awk '{print \$1\" \"\$2}' | xargs -n2 vblade-persist destroy +fi diff --git a/nova/livemigration_test/SI/utils/nova.sh.compute b/nova/livemigration_test/SI/utils/nova.sh.compute new file mode 100755 index 000000000..ede38ba20 --- /dev/null +++ b/nova/livemigration_test/SI/utils/nova.sh.compute @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +DIRNAME=nova +NOVA_DIR=$DIR/$DIRNAME +if [ -n "$3" ]; then + NOVA_DIR=$DIR/$3 +fi + +DIR=/opt/nova-2010.4 +REDIS_DIR=/opt/redis-2.0.0-rc4/ +NOVA_DIR=$DIR/nova +HOST_IP=172.19.0.131 + +mkdir -p /etc/nova +cat >/etc/nova/nova-manage.conf << NOVA_CONF_EOF +--verbose +--nodaemon +--dhcpbridge_flagfile=/etc/nova/nova-manage.conf +--FAKE_subdomain=ec2 +--libvirt_type=qemu +--no_internet_conn=True +--public_netif=eth0 +--public_interface=eth0 + +--cc-host=$HOST_IP +--routing_source_ip=$HOST_IP +--sql_connection=mysql://root:nova@$HOST_IP/nova +--rabbit_host=$HOST_IP +--redis_host=$HOST_IP +--s3_host=$HOST_IP +--auth_driver=nova.auth.ldapdriver.LdapDriver +--ldap_url=ldap://$HOST_IP + +NOVA_CONF_EOF + +$DIR/bin/nova-compute --flagfile=/etc/nova/nova-manage.conf + diff --git a/nova/livemigration_test/UT/computeManager.test.py b/nova/livemigration_test/UT/computeManager.test.py new file mode 100644 index 000000000..69ee876d1 --- /dev/null +++ b/nova/livemigration_test/UT/computeManager.test.py @@ -0,0 +1,411 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + + +import sys +import os +import unittest +import commands +import re +import logging + +from mock import Mock +import twisted + +# 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.compute.manager import ComputeManager + from nova.virt.libvirt_conn import LibvirtConnection + + 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 writelines(self, arg): + self.buffer += arg + + def flush(self): + print 'flush' + self.buffer = '' + + +class tmpStderr(tmpStdout): + def write(self, arg): + self.buffer += arg + + def flush(self): + pass + + def realFlush(self): + self.buffer = '' + +dummyCallReturnValue={ 0:True } +dummyCallCount=0 +def dummyCall(context, topic, method): + global dummyCallReturnValue, dummyCallCount + if dummyCallCount in dummyCallReturnValue.keys() : + ret = dummyCallReturnValue[ dummyCallCount ] + dummyCallCount += 1 + return ret + else : + dummyCallCount += 1 + return False + + +class ComputeTestFunctions(unittest.TestCase): + + stdout = None + stdoutBak = None + stderr = None + stderrBak = None + manager = None + + # 共通の初期化処理 + def setUp(self): + """common init method. """ + + #if self.stdout is None: + # self.__class__.stdout = tmpStdout() + #self.stdoutBak = sys.stdout + #sys.stdout = self.stdout + if self.stderr is None: + self.__class__.stderr = tmpStderr() + self.stderrBak = sys.stderr + sys.stderr = self.stderr + + self.host = 'openstack2-api' + if self.manager is None: + self.__class__.manager = ComputeManager(host=self.host) + + self.setTestData() + self.setMocks() + + def setTestData(self): + + self.host1 = Host() + for key, val in [('name', 'host1'), ('cpu', 5), + ('memory_mb', 20480), ('hdd_gb', 876)]: + self.host1.__setitem__(key, val) + + self.host2 = Host() + for key, val in [('name', 'host2'), ('cpu', 5), + ('memory_mb', 20480), ('hdd_gb', 876)]: + self.host2.__setitem__(key, val) + + 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), + ('hdd_gb', 5), ('internal_id', 12345)]: + 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), + ('hdd_gb', 5)]: + self.instance2.__setitem__(key, val) + + self.fixed_ip1 = FixedIp() + for key, val in [('id', 1), ('address', '1.1.1.1'), + ('network_id', '1'), ('instance_id', 1)]: + self.fixed_ip1.__setitem__(key, val) + + self.vol1 = Volume() + for key, val in [('id', 1), ('ec2_id', 'vol-qijjuc7e'), + ('availability_zone', 'nova'), ('host', 'host1')]: + self.vol1.__setitem__(key, val) + + self.vol2 = Volume() + for key, val in [('id', 2), ('ec2_id', 'vol-qi22222'), + ('availability_zone', 'nova'), ('host', 'host1')]: + self.vol2.__setitem__(key, val) + + self.secgrp1 = Volume() + for key, val in [('id', 1), ('ec2_id', 'default')]: + self.secgrp1.__setitem__(key, val) + + self.secgrp2 = Volume() + for key, val in [('id', 2), ('ec2_id', 'def2')]: + self.secgrp2.__setitem__(key, val) + + self.netref1 = Network() + + def setMocks(self): + + # mocks for pre_live_migration + self.ctxt = context.get_admin_context() + db.instance_get = Mock(return_value=self.instance1) + db.volume_get_by_ec2_id = Mock(return_value=[self.vol1, self.vol2]) + db.volume_get_shelf_and_blade = Mock(return_value=(3, 4)) + db.instance_get_fixed_address = Mock(return_value=self.fixed_ip1) + db.security_group_get_by_instance \ + = Mock(return_value=[self.secgrp1, self.secgrp2]) + self.manager.driver.setup_nwfilters_for_instance \ + = Mock(return_value=None) + self.manager.driver.nwfilter_for_instance_exists = Mock(return_value=None) + self.manager.network_manager.setup_compute_network \ + = Mock(return_value=None) + # mocks for live_migration_ + rpc.call = Mock(return_value=True) + db.instance_set_state = Mock(return_value=True) + + # ---> test for nova.compute.manager.pre_live_migration() + def test01(self): + """01: NotFound error occurs on finding instance on DB. """ + + db.instance_get = Mock(side_effect=exception.NotFound('ERR')) + + self.assertRaises(exception.NotFound, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test02(self): + """02: NotAuthrized occurs on finding volume on DB. """ + + db.volume_get_by_ec2_id \ + = Mock(side_effect=exception.NotAuthorized('ERR')) + + self.assertRaises(exception.NotAuthorized, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test03(self): + """03: Unexpected exception occurs on finding volume on DB. """ + + db.volume_get_by_ec2_id = Mock(side_effect=TypeError('ERR')) + + self.assertRaises(TypeError, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test04(self): + """04: no volume and fixed ip found on DB, """ + + db.volume_get_by_ec2_id = Mock(side_effect=exception.NotFound('ERR')) + db.instance_get_fixed_address = Mock(return_value=None) + + self.assertRaises(rpc.RemoteError, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + c1 = (0 <= sys.stderr.buffer.find('has no volume')) + + self.assertEqual(c1, True) + + def test05(self): + """05: volume found and no fixed_ip found on DB. """ + + db.instance_get_fixed_address \ + = Mock(side_effect=exception.NotFound('ERR')) + + self.assertRaises(exception.NotFound, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test06(self): + """06: self.driver.setup_nwfilters_for_instance causes NotFound. """ + self.manager.driver.setup_nwfilters_for_instance \ + = Mock(side_effect=exception.NotFound("ERR")) + + self.assertRaises(exception.NotFound, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test07(self): + """07: self.network_manager.setup_compute_network causes ProcessExecutionError. """ + self.manager.network_manager.setup_compute_network \ + = Mock(side_effect=exception.ProcessExecutionError("ERR")) + + self.assertRaises(exception.ProcessExecutionError, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + + def test08(self): + """08: self.manager.network_manager.setup_compute_network + exception.NotFound. """ + self.manager.network_manager.setup_compute_network \ + = Mock(side_effect=exception.NotFound("ERR")) + + self.assertRaises(exception.NotFound, + self.manager.pre_live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + # those 2 cases are omitted : + # self.driver.setup_nwfilters_for_instance causes + # twisted.python.failure.Failure. + # self.driver.refresh_security_group causes twisted.python.failure.Failure. + # + # twisted.python.failure.Failure can not be used with assertRaises, + # it doesnt have __call___ + # + + def test09(self): + """09: volume/fixed_ip found on DB, all procedure finish + successfully.. """ + + result = self.manager.pre_live_migration(self.ctxt, 'dummy_ec2_id', + 'host2') + self.assertEqual(result, True) + + # ---> test for nova.compute.manager.live_migration() + + def test10(self): + """10: rpc.call(pre_live_migration returns Error(Not None). """ + rpc.call = Mock(side_effect=exception.NotFound("ERR")) + + self.assertRaises(exception.NotFound, + self.manager.live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test11(self): + """11: if rpc.call returns rpc.RemoteError. """ + + rpc.call = Mock(return_value=rpc.RemoteError(None, None, None)) + db.instance_set_state = Mock(return_value=True) + result = self.manager.live_migration(self.ctxt, 'dummy_ec2_id', + 'host2') + c1 = (None == result) + c2 = (0 <= sys.stderr.buffer.find('err at')) + self.assertEqual(c1 and c2, True) + + def test12(self): + """12: if rpc.call returns rpc.RemoteError and instance_set_state + also ends up err. (then , unexpected err occurs, in this case + TypeError) + """ + rpc.call = Mock(return_value=rpc.RemoteError(None, None, None)) + db.instance_set_state = Mock(side_effect=TypeError("ERR")) + self.assertRaises(TypeError, + self.manager.live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test13(self): + """13: if wait for pre_live_migration, but timeout. """ + rpc.call = dummyCall + + db.instance_get = Mock(return_value=self.instance1) + + result = self.manager.live_migration(self.ctxt, 'dummy_ec2_id', + 'host2') + c1 = (None == result) + c2 = (0 <= sys.stderr.buffer.find('Timeout for')) + self.assertEqual(c1 and c2, True) + + def test14(self): + """14: if db_instance_get issues NotFound. + """ + rpc.call = Mock(return_value=True) + db.instance_get = Mock(side_effect=exception.NotFound("ERR")) + self.assertRaises(exception.NotFound, + self.manager.live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test15(self): + """15: if rpc.call returns True, and instance_get() cause other + exception. (Unexpected case - b/c it already checked by + nova-manage) + """ + rpc.call = Mock(return_value=True) + db.instance_get = Mock(side_effect=TypeError("ERR")) + + self.assertRaises(TypeError, + self.manager.live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test16(self): + """16: if rpc.call returns True, and live_migration issues + ProcessExecutionError. """ + rpc.call = Mock(return_value=True) + db.instance_get = Mock(return_value=self.instance1) + ret = self.manager.driver.live_migration \ + = Mock(side_effect=utils.ProcessExecutionError("ERR")) + + self.assertRaises(utils.ProcessExecutionError, + self.manager.live_migration, + self.ctxt, + 'dummy_ec2_id', + 'host2') + + def test17(self): + """17: everything goes well. """ + self.manager.driver.live_migration = Mock(return_value=True) + ret = self.manager.live_migration(self.ctxt, 'i-12345', 'host1') + self.assertEqual(True, True) + + def tearDown(self): + """common terminating method. """ + self.stderr.realFlush() + sys.stderr = self.stderrBak + #sys.stdout = self.stdoutBak + +if __name__ == '__main__': + logging.getLogger().setLevel(logging.DEBUG) + #unittest.main() + + suite = unittest.TestLoader().loadTestsFromTestCase(ComputeTestFunctions) + unittest.TextTestRunner(verbosity=2).run(suite) + + #suite = unittest.TestSuite() + #suite.addTest(ComputeTestFunctions("test15")) + #suite.addTest(ComputeTestFunctions("test16")) + #unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/nova/livemigration_test/UT/libvirtConnection.test.py b/nova/livemigration_test/UT/libvirtConnection.test.py new file mode 100644 index 000000000..5dfe8702c --- /dev/null +++ b/nova/livemigration_test/UT/libvirtConnection.test.py @@ -0,0 +1,372 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + + +import sys +import os +import unittest +import commands +import re +import logging +import libvirt + +from mock import Mock +import twisted + +# 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.compute.manager import ComputeManager + from nova.virt import libvirt_conn + + 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 import process + 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 writelines(self, arg): + self.buffer += arg + def flush(self): + print 'flush' + self.buffer = '' + +class tmpStderr(tmpStdout): + def write(self,arg): + self.buffer += arg + def flush(self): + pass + def realFlush(self): + self.buffer = '' + +class DummyLibvirtConn(object): + nwfilterLookupByName = None + def __init__(self): + pass + + +class LibvirtConnectionTestFunctions(unittest.TestCase): + + stdout = None + stdoutBak = None + stderr = None + stderrBak = None + manager = None + + # 共通の初期化処理 + def setUp(self): + """common init method. """ + + #if self.stdout is None: + # self.__class__.stdout = tmpStdout() + #self.stdoutBak = sys.stdout + #sys.stdout = self.stdout + if self.stderr is None: + self.__class__.stderr = tmpStderr() + self.stderrBak = sys.stderr + sys.stderr = self.stderr + + self.host = 'openstack2-api' + if self.manager is None: + self.__class__.manager = libvirt_conn.get_connection(False) + + self.setTestData() + self.setMocks() + + def setTestData(self): + + self.host1 = Host() + for key, val in [ ('name', 'host1'), ('cpu', 5), ('memory_mb', 20480), ('hdd_gb', 876) ]: + self.host1.__setitem__(key, val) + + 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), ('hdd_gb', 5), ('internal_id',12345) ]: + 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), ('hdd_gb', 5) ]: + self.instance2.__setitem__(key, val) + + + self.fixed_ip1 = FixedIp() + for key, val in [ ('id', 1), ('address', '1.1.1.1'), ('network_id', '1'), + ('instance_id', 1)]: + self.fixed_ip1.__setitem__(key, val) + + self.floating_ip1 = FloatingIp() + for key, val in [ ('id', 1), ('address', '1.1.1.200') ]: + self.floating_ip1.__setitem__(key, val) + + self.netref1 = Network() + for key, val in [ ('id', 1) ]: + self.netref1.__setitem__(key, val) + + + def setMocks(self): + + self.ctxt = context.get_admin_context() + db.instance_get_fixed_address = Mock(return_value = '1.1.1.1') + db.fixed_ip_update = Mock(return_value = None) + db.fixed_ip_get_network = Mock(return_value = self.netref1) + db.network_update = Mock(return_value = None) + db.instance_get_floating_address = Mock(return_value = '1.1.1.200') + db.floating_ip_get_by_address = Mock(return_value = self.floating_ip1) + db.floating_ip_update = Mock(return_value = None) + db.instance_update = Mock(return_value = None) + + + # ---> test for nova.virt.libvirt_conn.nwfilter_for_instance_exists() + + def test01(self): + """01: libvirt.libvirtError occurs. """ + + self.manager._wrapped_conn = DummyLibvirtConn() + self.manager._test_connection = Mock(return_value=True) + self.manager._conn.nwfilterLookupByName = \ + Mock(side_effect=libvirt.libvirtError("ERR")) + ret = self.manager.nwfilter_for_instance_exists(self.instance1) + self.assertEqual(ret, False) + + def test02(self): + """02: libvirt.libvirtError not occurs. """ + + self.manager._wrapped_conn = DummyLibvirtConn() + self.manager._test_connection = Mock(return_value=True) + self.manager._conn.nwfilterLookupByName = \ + Mock(return_value=True) + ret = self.manager.nwfilter_for_instance_exists(self.instance1) + self.assertEqual(ret, True) + + # ---> test for nova.virt.libvirt_conn.live_migraiton() + + def test03(self): + """03: Unexpected exception occurs on finding volume on DB. """ + + utils.execute = Mock( side_effect=process.ProcessExecutionError('ERR') ) + + self.assertRaises(process.ProcessExecutionError, + self.manager.live_migration, + self.instance1, + 'host2') + + # ---> other case cannot be tested because live_migraiton + # is synchronized/asynchronized method are mixed together + + + # ---> test for nova.virt.libvirt_conn._post_live_migraiton + + def test04(self): + """04: instance_ref is not nova.db.sqlalchemy.models.Instances""" + + self.assertRaises(TypeError, + self.manager._post_live_migration, + "dummy string", + 'host2') + + def test05(self): + """05: db.instance_get_fixed_address return None""" + + db.instance_get_fixed_address = Mock( return_value=None ) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('fixed_ip is not found')) + self.assertEqual(c1 and c2, True) + + def test06(self): + """06: db.instance_get_fixed_address raises NotFound""" + + db.instance_get_fixed_address = Mock( side_effect=exception.NotFound('ERR') ) + self.assertRaises(exception.NotFound, + self.manager._post_live_migration, + self.instance1, + 'host2') + + def test07(self): + """07: db.instance_get_fixed_address raises Unknown exception""" + + db.instance_get_fixed_address = Mock( side_effect=TypeError('ERR') ) + self.assertRaises(TypeError, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test08(self): + """08: db.fixed_ip_update return NotFound. """ + + db.fixed_ip_update = Mock( side_effect=exception.NotFound('ERR') ) + self.assertRaises(exception.NotFound, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test09(self): + """09: db.fixed_ip_update return NotAuthorized. """ + db.fixed_ip_update = Mock( side_effect=exception.NotAuthorized('ERR') ) + self.assertRaises(exception.NotAuthorized, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test10(self): + """10: db.fixed_ip_update return Unknown exception. """ + db.fixed_ip_update = Mock( side_effect=TypeError('ERR') ) + self.assertRaises(TypeError, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test11(self): + """11: db.fixed_ip_get_network causes NotFound. """ + + db.fixed_ip_get_network = Mock( side_effect=exception.NotFound('ERR') ) + self.assertRaises(exception.NotFound, + self.manager._post_live_migration, + self.instance1, + 'host1') + + # not tested db.fixed_ip_get_network raises NotAuthorized + # because same test has been done at previous test. + + def test12(self): + """12: db.fixed_ip_get_network causes Unknown exception. """ + + db.fixed_ip_get_network = Mock( side_effect=TypeError('ERR') ) + self.assertRaises(TypeError, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test13(self): + """13: db.network_update raises Unknown exception. """ + db.network_update = Mock( side_effect=TypeError('ERR') ) + self.assertRaises(TypeError, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def test14(self): + """14: db.instance_get_floating_address raises NotFound. """ + db.instance_get_floating_address = Mock(side_effect=exception.NotFound("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('doesnt have floating_ip')) + self.assertEqual(c1 and c2, True) + + + def test15(self): + """15: db.instance_get_floating_address returns None. """ + + db.instance_get_floating_address = Mock( return_value=None ) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('floating_ip is not found')) + self.assertEqual(c1 and c2, True) + + def test16(self): + """16: db.instance_get_floating_address raises NotFound. """ + + db.instance_get_floating_address = Mock(side_effect=exception.NotFound("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('doesnt have floating_ip')) + self.assertEqual(c1 and c2, True) + + def test17(self): + """17: db.instance_get_floating_address raises Unknown exception. """ + db.instance_get_floating_address = Mock(side_effect=TypeError("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('Live migration: Unexpected error')) + self.assertEqual(c1 and c2, True) + + + def test18(self): + """18: db.floating_ip_get_by_address raises NotFound """ + + db.floating_ip_get_by_address = Mock(side_effect=exception.NotFound("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('doesnt have floating_ip')) + self.assertEqual(c1 and c2, True) + + def test19(self): + """19: db.floating_ip_get_by_address raises Unknown exception. """ + db.floating_ip_get_by_address = Mock(side_effect=TypeError("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('Live migration: Unexpected error')) + self.assertEqual(c1 and c2, True) + + + def test20(self): + """20: db.floating_ip_update raises Unknown exception. + """ + db.floating_ip_update = Mock(side_effect=TypeError("ERR")) + ret = self.manager._post_live_migration(self.instance1, 'host1') + c1 = (ret == None) + c2 = (0 <= sys.stderr.buffer.find('Live migration: Unexpected error')) + self.assertEqual(c1 and c2, True) + + def test21(self): + """21: db.instance_update raises unknown exception. """ + + db.instance_update = Mock(side_effect=TypeError("ERR")) + self.assertRaises(TypeError, + self.manager._post_live_migration, + self.instance1, + 'host1') + + def tearDown(self): + """common terminating method. """ + self.stderr.realFlush() + sys.stderr = self.stderrBak + #sys.stdout = self.stdoutBak + +if __name__ == '__main__': + logging.getLogger().setLevel(logging.DEBUG) + #unittest.main() + + suite = unittest.TestLoader().loadTestsFromTestCase(LibvirtConnectionTestFunctions) + unittest.TextTestRunner(verbosity=2).run(suite) + + #suite = unittest.TestSuite() + #suite.addTest(LibvirtConnectionTestFunctions("test14")) + #suite.addTest(LibvirtConnectionTestFunctions("test16")) + #unittest.TextTestRunner(verbosity=2).run(suite) + + diff --git a/nova/livemigration_test/UT/nova-manage.test.py b/nova/livemigration_test/UT/nova-manage.test.py new file mode 100644 index 000000000..f1653d21a --- /dev/null +++ b/nova/livemigration_test/UT/nova-manage.test.py @@ -0,0 +1,351 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +NOVA_DIR='/opt/nova-2010.4' + +import sys +import os +import unittest +import commands +import re + +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 'Testing %s/bin/nova-manage, set the NOVA_DIR properly..' % NOVA_DIR + print + + sys.path.append(NOVA_DIR) + + 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 tmpStderr(tmpStdout): + def write(self, arg): + self.buffer += arg + def flush(self): + pass + def realFlush(self): + self.buffer = '' + + +class NovaManageTestFunctions(unittest.TestCase): + + stdout = None + stdoutBak = None + stderr = None + stderrBak = None + + hostCmds = None + + # 共通の初期化処理 + def setUp(self): + """common init method. """ + + commands.getstatusoutput('cp -f %s/bin/nova-manage %s' % ( NOVA_DIR, self.getNovaManageCopyPath() )) + commands.getstatusoutput('touch %s' % self.getInitpyPath() ) + try : + import bin.novamanagetest + except: + print 'Fail to import nova-manage . check bin/nova-manage exists' + raise + + # replace stdout for checking nova-manage output + if self.stdout is None : + self.__class__.stdout = tmpStdout() + self.stdoutBak = sys.stdout + sys.stdout = self.stdout + + # replace stderr for checking nova-manage output + if self.stderr is None: + self.__class__.stderr = tmpStderr() + self.stderrBak = sys.stderr + sys.stderr = self.stderr + + # prepare test data + self.setTestData() + + + def setTestData(self): + import bin.novamanagetest + + if self.hostCmds is None : + self.__class__.hostCmds = bin.novamanagetest.HostCommands() + self.instanceCmds = bin.novamanagetest.InstanceCommands() + + self.host1 = Host() + self.host1.__setitem__('name', 'host1') + + self.host2 = Host() + self.host2.__setitem__('name', 'host2') + + self.instance1 = Instance() + self.instance1.__setitem__('id', 1) + self.instance1.__setitem__('host', 'host1') + self.instance1.__setitem__('hostname', 'i-12345') + self.instance1.__setitem__('state', power_state.NOSTATE) + self.instance1.__setitem__('state_description', 'running') + + self.instance2 = Instance() + self.instance2.__setitem__('id', 2) + self.instance2.__setitem__('host', 'host1') + self.instance2.__setitem__('hostname', 'i-12345') + self.instance2.__setitem__('state', power_state.RUNNING) + self.instance2.__setitem__('state_description', 'pending') + + self.instance3 = Instance() + self.instance3.__setitem__('id', 3) + self.instance3.__setitem__('host', 'host1') + self.instance3.__setitem__('hostname', 'i-12345') + self.instance3.__setitem__('state', power_state.RUNNING) + self.instance3.__setitem__('state_description', 'running') + + db.host_get_all = Mock(return_value=[self.host1, self.host2]) + + def getInitpyPath(self): + return '%s/bin/__init__.py' % NOVA_DIR + + def getNovaManageCopyPath(self): + return '%s/bin/novamanagetest.py' % NOVA_DIR + + # -----> Test for nova-manage host list + + def test01(self): + """01: Got some host lists. """ + + self.hostCmds.list() + + c1 = (2 == self.stdout.buffer.count('\n')) + c2 = (0 <= self.stdout.buffer.find('host1')) + c3 = (0 <= self.stdout.buffer.find('host2')) + self.assertEqual(c1 and c2 and c3, True) + + def test02(self): + """02: Got empty lsit. """ + + db.host_get_all = Mock(return_value=[]) + self.hostCmds.list() + + # result should be empty + c = (0 == len(self.stdout.buffer) ) + self.assertEqual(c, True) + + def test03(self): + """03: Got notFound """ + + db.host_get_all = Mock(side_effect=exception.NotFound("ERR")) + self.assertRaises(exception.NotFound, self.hostCmds.list) + + # --------> Test For nova-manage host show + + def test04(self): + """04: args are not enough(nova-manage host show) """ + self.assertRaises(TypeError, self.hostCmds.show ) + + + def test05(self): + """05: nova-manage host show not-registered-host, and got an error""" + + rpc.call = Mock(return_value={'ret' : False, 'msg': 'ERR'} ) + self.hostCmds.show('host1') + self.assertEqual( self.stdout.buffer[:3]=='ERR', True ) + + + def test06(self): + """06: nova-manage host show registerd-host, and no project uses the host""" + + dic = {'ret': True, + 'phy_resource': {'vcpus':1, 'memory_mb':2, 'local_gb':3}, + 'usage': {}} + + rpc.call = Mock(return_value=dic ) + self.hostCmds.show('host1') + + # result should be : + # HOST PROJECT cpu mem(mb) disk(gb) + # host1 1 2 3 + line = self.stdout.buffer.split('\n')[1] + line = re.compile('\t+').sub(' ', line).strip() + c1 = ( 'host1 1 2 3' == line ) + c2 = ( self.stdout.buffer.count('\n') == 2 ) + + self.assertEqual( c1 and c2, True ) + + def test07(self): + """07: nova-manage host show registerd-host, + and some projects use the host + """ + dic = {'ret': True, + 'phy_resource': {'vcpus':1, 'memory_mb':2, 'local_gb':3}, + 'usage': {'p1': {'vcpus':1, 'memory_mb':2, 'local_gb':3}, + 'p2': {'vcpus':1, 'memory_mb':2, 'local_gb':3} }} + + rpc.call = Mock(return_value=dic ) + self.hostCmds.show('host1') + + # result should be : + # HOST PROJECT cpu mem(mb) disk(gb) + # host1 1 2 3 + # host1 p1 1 2 3 + # host1 p2 4 5 6 + line = self.stdout.buffer.split('\n')[1] + ret = re.compile('\t+').sub(' ', line).strip() + c1 = ( 'host1 1 2 3' == ret ) + + line = self.stdout.buffer.split('\n')[2] + line = re.compile('\t+').sub(' ', line).strip() + c2 = ( 'host1 p1 1 2 3' == line ) or ( 'host1 p2 1 2 3' == line ) + + line = self.stdout.buffer.split('\n')[3] + ret = re.compile('\t+').sub(' ', line).strip() + c3 = ( 'host1 p1 1 2 3' == ret ) or ( 'host1 p2 1 2 3' == ret ) + + self.assertEqual( c1 and c2 and c3, True ) + + def test08(self): + """08: nova-manage host show registerd-host, and rpc.call returns None + (unexpected error) + """ + rpc.call = Mock(return_value=None ) + self.hostCmds.show('host1') + c1 = ( 0 <= self.stdout.buffer.find('Unexpected error') ) + self.assertEqual( c1, True ) + + # ----------> Test for bin/nova-manage instance live_migration + + def test09(self): + """09: arguments are not enough(nova-manage instances live_migration) + """ + self.assertRaises(TypeError, self.instanceCmds.live_migration ) + + def test10(self): + """10: arguments are not enough(nova-manage instances live_migration ec2_id) + """ + self.assertRaises(TypeError, self.instanceCmds.live_migration, 'i-xxx' ) + + def test11(self): + """11: nova-manage instances live_migration ec2_id host, + where hostname is invalid + """ + db.host_get_by_name = Mock( side_effect=exception.NotFound('ERR') ) + self.assertRaises(exception.NotFound, self.instanceCmds.live_migration, 'i-xxx', 'host1' ) + + def test12(self): + """12: nova-manage instances live_migration ec2_id(invalid id) host""" + + db.host_get_by_name = Mock(return_value = self.host1) + db.instance_get_by_internal_id = Mock( side_effect=exception.NotFound('ERR') ) + + self.assertRaises(exception.NotFound, self.instanceCmds.live_migration, 'i-xxx', 'host1' ) + + def test13(self): + """13: nova-manage instances live_migration ec2_id host, + but instance specifed by ec2 id is not running (state is not power_state.RUNNING) + """ + db.host_get_by_name = Mock(return_value = self.host1) + db.instance_get_by_internal_id = Mock( return_value = self.instance1 ) + try : + self.instanceCmds.live_migration('i-12345', 'host1') + except exception.Invalid, e: + c1 = (0 < e.message.find('is not running') ) + self.assertTrue(c1, True) + return False + + + def test14(self): + """14: nova-manage instances live_migration ec2_id host, + but instance specifed by ec2 id is not running (state_description is not running) + """ + db.host_get_by_name = Mock(return_value = self.host2) + db.instance_get_by_internal_id = Mock( return_value = self.instance1 ) + try : + self.instanceCmds.live_migration('i-12345', 'host2') + except exception.Invalid, e: + c1 = (0 < e.message.find('is not running') ) + self.assertTrue(c1, True) + return False + + def test15(self): + """15: nova-manage instances live_migration ec2_id host, + but instance is running at the same host specifed above, so err should be occured. + """ + db.host_get_by_name = Mock(return_value = self.host1) + db.instance_get_by_internal_id = Mock( return_value = self.instance3 ) + try : + self.instanceCmds.live_migration('i-12345', 'host1') + except exception.Invalid, e: + c1 = ( 0 <= e.message.find('is running now') ) + self.assertTrue(c1, True) + return False + + + def test16(self): + """16: nova-manage instances live_migration ec2_id host, + rpc.call raises RemoteError because destination doesnt have enough resource. + """ + db.host_get_by_name = Mock(return_value = self.host1) + db.instance_get_by_internal_id = Mock( return_value = self.instance3 ) + rpc.call = Mock(return_value = rpc.RemoteError(TypeError, 'val', 'traceback')) + self.assertRaises(rpc.RemoteError, self.instanceCmds.live_migration, 'i-xxx', 'host2' ) + + + def test17(self): + """17: nova-manage instances live_migration ec2_id host, + everything goes well, ang gets success messages. + """ + db.host_get_by_name = Mock(return_value = self.host1) + db.instance_get_by_internal_id = Mock( return_value = self.instance3 ) + rpc.call = Mock(return_value = None) + + self.instanceCmds.live_migration('i-12345', 'host2') + c1 = (0 <= self.stdout.buffer.find('Finished all procedure') ) + self.assertEqual( c1, True ) + + + def tearDown(self): + """common terminating method. """ + commands.getstatusoutput('rm -rf %s' % self.getInitpyPath() ) + commands.getstatusoutput('rm -rf %s' % self.getNovaManageCopyPath() ) + sys.stdout.flush() + sys.stdout = self.stdoutBak + self.stderr.realFlush() + sys.stderr = self.stderrBak + +if __name__ == '__main__': + #unittest.main() + suite = unittest.TestLoader().loadTestsFromTestCase(NovaManageTestFunctions) + unittest.TextTestRunner(verbosity=3).run(suite) + + diff --git a/nova/livemigration_test/UT/schedulerManager.test.py b/nova/livemigration_test/UT/schedulerManager.test.py new file mode 100644 index 000000000..a0b76c918 --- /dev/null +++ b/nova/livemigration_test/UT/schedulerManager.test.py @@ -0,0 +1,408 @@ +#!/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): + + # 共通の初期化処理 + def setUp(self): + """common init method. """ + + self.host = 'openstack2-api' + 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.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), ('hdd_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), ('hdd_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), ('hdd_gb', 5) ]: + 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) ]: + 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) ]: + self.instance5.__setitem__(key, val) + + self.instance6 = Instance() + for key, val in [ ('id', 6), ('host', 'host1'), ('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), ('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) + + + 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.instance_get_by_internal_id = Mock(return_value = self.instance1) + # db.host_get_by_name <- defined above. + db.service_get_all_by_topic = Mock(return_value = [self.service1] ) + rpc.call = Mock(return_value=1) + + 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.has_enough_resource(self.ctxt, 'i-12345', 'host1') + except exception.NotEmpty, e: + c1 = ( 0 < e.message.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.has_enough_resource(self.ctxt, 'i-12345', 'host1') + except exception.NotEmpty, e: + c1 = ( 0 <= e.message.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.has_enough_resource(self.ctxt, 'i-12345', 'host1') + except exception.NotEmpty, e: + c1 = ( 0 <= e.message.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.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.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_by_internal_id issue NotFound. """ + + # Mocks for has_enough_resource() + db.instance_get = Mock(return_value = self.instance8) + # Mocks for live_migration()db.instance_get_by_internal_id + # (any Mock is ok here. important mock is all above) + db.instance_get_by_internal_id = Mock(side_effect=exception.NotFound("ERR")) + + self.assertRaises(exception.NotFound, + self.manager.live_migration, + self.ctxt, + 'i-12345', + 'host1') + + + def test11(self): + """11: get NotFound exception when dest host not found on DB """ + + db.host_get_by_name = Mock( side_effect=exception.NotFound('ERR') ) + self.assertRaises(exception.NotFound, + self.manager.live_migration, + self.ctxt, + 'i-12345', + 'host1') + + + def test12(self): + """12: Destination host is not compute node """ + self.assertRaises(exception.Invalid, + self.manager.live_migration, + self.ctxt, + 'i-12345', + 'host2') + + + # Cannot test the case of hypervisor type difference and hypervisor + # version difference, since we cannot set different mocks to same method.. + + def test13(self): + """13: 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.live_migration, + self.ctxt, + 'i-12345', + 'host1') + + def test14(self): + """14: rpc.call returns 0 (cpu is not compatible between src and dest) """ + rpc.call = Mock(return_value = 0) + try : + self.manager.live_migration(self.ctxt, 'i-12345', 'host1') + except exception.Invalid, e: + c1 = ( 0 <= e.message.find('doesnt have compatibility to')) + self.assertTrue(c1, True) + return False + + def test15(self): + """15: raise NotEmpty if host doesnt have enough resource. """ + + # Mocks for has_enough_resource() + db.instance_get = Mock(return_value = self.instance8) + + # Mocks for live_migration() + db.instance_get_by_internal_id = Mock(return_value = self.instance8) + db.instance_set_state = Mock(return_value = True) + rpc_cast = Mock(return_value = True) + + try : + self.manager.live_migration(self.ctxt, 'i-12345', 'host1') + except exception.NotEmpty, e: + c1 = ( 0 <= e.message.find('doesnt have enough resource') ) + self.assertTrue(c1, True) + return False + + + def test16(self): + """16: everything goes well. """ + + db.instance_get_by_internal_id = Mock(return_value = self.instance8) + db.instance_set_state = Mock(return_value = True) + rpc.cast = Mock(return_value = True) + + ret= self.manager.live_migration(self.ctxt, 'i-12345', 'host1') + self.assertEqual(ret, None) + + + 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) + + diff --git a/nova/livemigration_test/UT/testCase_UT.xls b/nova/livemigration_test/UT/testCase_UT.xls Binary files differnew file mode 100644 index 000000000..f73e8c5aa --- /dev/null +++ b/nova/livemigration_test/UT/testCase_UT.xls |
