cloudstack/test/integration/component/test_storage_motion.py
2013-11-11 10:32:01 +05:30

305 lines
12 KiB
Python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
""" P1 tests for Storage motion
"""
#Import Local Modules
import marvin
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from nose.plugins.attrib import attr
#Import System modules
import time
_multiprocess_shared_ = True
class Services:
"""Test VM Life Cycle Services
"""
def __init__(self):
self.services = {
"disk_offering":{
"displaytext": "Small",
"name": "Small",
"disksize": 1
},
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended in create account to
# ensure unique username generated each time
"password": "password",
},
"small":
# Create a small virtual machine instance with disk offering
{
"displayname": "testserver",
"username": "root", # VM creds for SSH
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"service_offerings":
{
"small":
{
# Small service offering ID to for change VM
# service offering from medium to small
"name": "Small Instance",
"displaytext": "Small Instance",
"cpunumber": 1,
"cpuspeed": 100,
"memory": 256,
}
},
"template": {
"displaytext": "Cent OS Template",
"name": "Cent OS Template",
"passwordenabled": True,
},
"sleep": 60,
"timeout": 10,
#Migrate VM to hostid
"ostype": 'CentOS 5.3 (64-bit)',
# CentOS 5.3 (64-bit)
}
class TestStorageMotion(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.api_client = super(TestStorageMotion, cls).getClsTestClient().getApiClient()
cls.services = Services().services
# Get Zone, Domain and templates
domain = get_domain(cls.api_client, cls.services)
cls.zone = get_zone(cls.api_client, cls.services)
cls.services['mode'] = cls.zone.networktype
template = get_template(
cls.api_client,
cls.zone.id,
cls.services["ostype"]
)
# Set Zones and disk offerings
cls.services["small"]["zoneid"] = cls.zone.id
cls.services["small"]["template"] = template.id
# Create VMs, NAT Rules etc
cls.account = Account.create(
cls.api_client,
cls.services["account"],
domainid=domain.id
)
cls.small_offering = ServiceOffering.create(
cls.api_client,
cls.services["service_offerings"]["small"]
)
#create a virtual machine
cls.virtual_machine = VirtualMachine.create(
cls.api_client,
cls.services["small"],
accountid=cls.account.name,
domainid=cls.account.domainid,
serviceofferingid=cls.small_offering.id,
mode=cls.services["mode"]
)
cls._cleanup = [
cls.small_offering,
cls.account
]
@classmethod
def tearDownClass(cls):
cls.api_client = super(TestStorageMotion, cls).getClsTestClient().getApiClient()
cleanup_resources(cls.api_client, cls._cleanup)
return
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.cleanup = []
def tearDown(self):
#Clean up, terminate the created ISOs
cleanup_resources(self.apiclient, self.cleanup)
return
@attr(tags = ["advanced", "basic", "multicluster", "storagemotion", "xenserver"])
def test_01_migrate_vm_with_volume(self):
"""Test migrate virtual machine with its volumes
"""
# Validate the following
# 1. List hosts for migration of a vm. Pick a host that
# requires storage motion too.
# 2. Migrate vm to a host.
# 3. listVM command should return this VM.State of this VM
# should be "Running" and the host should be the host
# to which the VM was migrated to in a different cluster
hosts = Host.listForMigration(
self.apiclient,
virtualmachineid=self.virtual_machine.id
)
self.assertEqual(
isinstance(hosts, list),
True,
"Check the number of hosts in the zone"
)
# Migrate to a host that requires storage motion
hosts[:] = [host for host in hosts if host.requiresStorageMotion]
if hosts is None or len(hosts) == 0:
self.skipTest("No valid hosts for storage motion. Skipping")
host = hosts[0]
self.debug("Migrating VM-ID: %s to Host: %s" % (
self.virtual_machine.id,
host.id
))
cmd = migrateVirtualMachineWithVolume.migrateVirtualMachineWithVolumeCmd()
cmd.hostid = host.id
cmd.virtualmachineid = self.virtual_machine.id
self.apiclient.migrateVirtualMachineWithVolume(cmd)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vm_response, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
list_vm_response,
None,
"Check virtual machine is listVirtualMachines"
)
vm_response = list_vm_response[0]
self.assertEqual(
vm_response.id,
self.virtual_machine.id,
"Check virtual machine ID of migrated VM"
)
self.assertEqual(
vm_response.hostid,
host.id,
"Check destination hostID of migrated VM"
)
self.assertEqual(
vm_response.state,
'Running',
"Check the state of VM"
)
return
@attr(tags = ["advanced", "basic", "multipool", "storagemotion", "xenserver"])
def test_02_migrate_volume(self):
"""Test migrate volume of a running vm
"""
# Validate the following
# 1. List all the volumes of a vm. For each volume do step 2 to 4.
# 2. List storage pools for migrating volume of a vm. Multiple
# storage pools should be present in the cluster.
# 3. Migrate volume of the vm to another pool.
# 4. Check volume is present in the new pool and is in Ready state.
list_volumes_response = list_volumes(
self.apiclient,
virtualmachineid=self.virtual_machine.id,
listall=True
)
self.assertEqual(
isinstance(list_volumes_response, list),
True,
"Check list volumes response for valid list"
)
self.assertNotEqual(
list_volumes_response,
None,
"Check if volume exists in ListVolumes"
)
for volume in list_volumes_response:
pools = StoragePool.listForMigration(
self.apiclient,
id=volume.id
)
if not pools:
self.skipTest("No suitable storage pools found for volume migration. Skipping")
self.assert_(isinstance(pools, list), "invalid pool response from listStoragePoolsForMigration: %s" %pools)
self.assert_(len(pools) > 0, "no valid storage pools found for migration")
pool = pools[0]
self.debug("Migrating Volume-ID: %s to Pool: %s" % (
volume.id,
pool.id
))
Volume.migrate(
self.apiclient,
volumeid=volume.id,
storageid=pool.id,
livemigrate='true'
)
migrated_volume_response = list_volumes(
self.apiclient,
id=volume.id
)
self.assertEqual(
isinstance(migrated_volume_response, list),
True,
"Check list volumes response for valid list"
)
self.assertNotEqual(
migrated_volume_response,
None,
"Check if volume exists in ListVolumes"
)
migrated_volume = migrated_volume_response[0]
self.assertEqual(
migrated_volume.state,
'Ready',
"Check migrated volume is in Ready state"
)
self.assertEqual(
migrated_volume.storage,
pool.name,
"Check volume is on migrated pool"
)
return