Merge "Add scenarios for live migration of an instance with volumes"

This commit is contained in:
Jenkins 2015-03-06 13:59:50 +00:00 committed by Gerrit Code Review
commit 64e210db2d
6 changed files with 244 additions and 0 deletions

View File

@ -341,6 +341,94 @@ class NovaServers(utils.NovaScenario,
self._delete_server(server) self._delete_server(server)
@types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType)
@validation.image_valid_on_flavor("flavor", "image")
@validation.required_services(consts.Service.NOVA, consts.Service.CINDER)
@validation.required_openstack(admin=True, users=True)
@base.scenario(context={"cleanup": ["nova", "cinder"]})
def boot_server_from_volume_and_live_migrate(self, image, flavor,
volume_size,
block_migration=False,
disk_over_commit=False,
force_delete=False, **kwargs):
"""Boot a server from volume and then migrate it.
The scenario first creates a volume and a server booted from
the volume on a compute node available in the availability zone and
then migrates the VM to another compute node on the same availability
zone.
:param image: image to be used to boot an instance
:param flavor: flavor to be used to boot an instance
:param volume_size: volume size (in GB)
:param block_migration: Specifies the migration type
:param disk_over_commit: Specifies whether to allow overcommit
on migrated instance or not
:param force_delete: True if force_delete should be used
:param kwargs: Optional additional arguments for server creation
"""
volume = self._create_volume(volume_size, imageRef=image)
block_device_mapping = {"vda": "%s:::1" % volume.id}
server = self._boot_server(image, flavor,
block_device_mapping=block_device_mapping,
**kwargs)
new_host = self._find_host_to_migrate(server)
self._live_migrate(server, new_host,
block_migration, disk_over_commit)
self._delete_server(server, force=force_delete)
@types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType)
@validation.image_valid_on_flavor("flavor", "image")
@validation.required_services(consts.Service.NOVA, consts.Service.CINDER)
@validation.required_openstack(admin=True, users=True)
@base.scenario(context={"cleanup": ["cinder", "nova"]})
def boot_server_attach_created_volume_and_live_migrate(
self,
image,
flavor,
size,
block_migration=False,
disk_over_commit=False,
boot_server_kwargs=None,
create_volume_kwargs=None):
"""Create a VM, attach a volume to it amd live migrate.
Simple test to create a VM and attach a volume, then migrate the VM,
detach the volume and delete volume/VM.
:param image: Glance image name to use for the VM
:param flavor: VM flavor name
:param size: volume size (in GB)
:param block_migration: Specifies the migration type
:param disk_over_commit: Specifies whether to allow overcommit
on migrated instance or not
:param boot_server_kwargs: optional arguments for VM creation
:param create_volume_kwargs: optional arguments for volume creation
"""
if boot_server_kwargs is None:
boot_server_kwargs = {}
if create_volume_kwargs is None:
create_volume_kwargs = {}
server = self._boot_server(image, flavor, boot_server_kwargs)
volume = self._create_volume(size, create_volume_kwargs)
self._attach_volume(server, volume)
new_host = self._find_host_to_migrate(server)
self._live_migrate(server, new_host,
block_migration, disk_over_commit)
self._detach_volume(server, volume)
self._delete_volume(volume)
self._delete_server(server)
@types.set(image=types.ImageResourceType, @types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType) flavor=types.FlavorResourceType)
@validation.image_valid_on_flavor("flavor", "image") @validation.image_valid_on_flavor("flavor", "image")

View File

@ -0,0 +1,27 @@
{
"NovaServers.boot_server_attach_created_volume_and_live_migrate": [
{
"args": {
"size": 10,
"block_migration": false,
"image": {
"name": "^cirros.*uec$"
},
"flavor": {
"name": "m1.nano"
}
},
"runner": {
"type": "constant",
"times": 5,
"concurrency": 1
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
}
}
}
]
}

View File

@ -0,0 +1,17 @@
---
NovaServers.boot_server_attach_created_volume_and_live_migrate:
- args:
flavor:
name: m1.nano
image:
name: "^cirros.*uec$"
size: 10
block_migration: false
runner:
type: constant
times: 5
concurrency: 1
context:
users:
tenants: 2
users_per_tenant: 2

View File

@ -0,0 +1,28 @@
{
"NovaServers.boot_server_from_volume_and_live_migrate": [
{
"args": {
"flavor": {
"name": "m1.nano"
},
"image": {
"name": "^cirros.*uec$"
},
"block_migration": false,
"volume_size": 10,
"force_delete": false
},
"runner": {
"type": "constant",
"times": 10,
"concurrency": 2
},
"context": {
"users": {
"tenants": 1,
"users_per_tenant": 1
}
}
}
]
}

View File

@ -0,0 +1,18 @@
---
NovaServers.boot_server_from_volume_and_live_migrate:
- args:
flavor:
name: m1.nano
image:
name: "^cirros.*uec$"
block_migration: false
volume_size: 10
force_delete: false
runner:
type: constant
times: 10
concurrency: 2
context:
users:
tenants: 1
users_per_tenant: 1

View File

@ -351,6 +351,72 @@ class NovaServersTestCase(test.TestCase):
False, False) False, False)
scenario._delete_server.assert_called_once_with(fake_server) scenario._delete_server.assert_called_once_with(fake_server)
def test_boot_server_from_volume_and_live_migrate(self):
fake_server = mock.MagicMock()
scenario = servers.NovaServers()
scenario._generate_random_name = mock.MagicMock(return_value="name")
scenario._boot_server = mock.MagicMock(return_value=fake_server)
scenario._find_host_to_migrate = mock.MagicMock(
return_value="host_name")
scenario._live_migrate = mock.MagicMock()
scenario._delete_server = mock.MagicMock()
fake_volume = fakes.FakeVolumeManager().create()
fake_volume.id = "volume_id"
scenario._create_volume = mock.MagicMock(return_value=fake_volume)
scenario.boot_server_from_volume_and_live_migrate("img", 0, 5,
fakearg="f")
scenario._create_volume.assert_called_once_with(5, imageRef="img")
scenario._boot_server.assert_called_once_with(
"img", 0,
block_device_mapping={"vda": "volume_id:::1"},
fakearg="f")
scenario._find_host_to_migrate.assert_called_once_with(fake_server)
scenario._live_migrate.assert_called_once_with(fake_server,
"host_name",
False, False)
scenario._delete_server.assert_called_once_with(fake_server,
force=False)
def test_boot_server_attach_created_volume_and_live_migrate(self):
fake_volume = mock.MagicMock()
fake_server = mock.MagicMock()
scenario = servers.NovaServers()
scenario._attach_volume = mock.MagicMock()
scenario._detach_volume = mock.MagicMock()
scenario._find_host_to_migrate = mock.MagicMock(
return_value="host_name")
scenario._live_migrate = mock.MagicMock()
scenario._boot_server = mock.MagicMock(return_value=fake_server)
scenario._delete_server = mock.MagicMock()
scenario._create_volume = mock.MagicMock(return_value=fake_volume)
scenario._delete_volume = mock.MagicMock()
scenario.boot_server_attach_created_volume_and_live_migrate(
"img",
0,
5)
scenario._attach_volume.assert_called_once_with(fake_server,
fake_volume)
scenario._detach_volume.assert_called_once_with(fake_server,
fake_volume)
scenario._live_migrate.assert_called_once_with(fake_server,
"host_name",
False, False)
scenario._delete_volume.assert_called_once_with(fake_volume)
scenario._delete_server.assert_called_once_with(fake_server)
def _test_boot_and_migrate_server(self, confirm=False): def _test_boot_and_migrate_server(self, confirm=False):
fake_server = mock.MagicMock() fake_server = mock.MagicMock()