Skip to content

Instantly share code, notes, and snippets.

@rmk40
Created August 4, 2014 22:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmk40/3144c99e959ea42ead9e to your computer and use it in GitHub Desktop.
Save rmk40/3144c99e959ea42ead9e to your computer and use it in GitHub Desktop.
From 1252592b2533b0f6605f7dca309bf57e7544c18b Mon Sep 17 00:00:00 2001
From: Rafi Khardalian <rafi@metacloud.com>
Date: Fri, 1 Aug 2014 22:00:56 -0700
Subject: [PATCH] Add support for Nova live migrations
This patch adds support for live migration in a new live_migrate_server
benchmark scenario. Live migrate requires an admin context, as
does determining the host on which an instance is running. A special
is_ready function was added to check whether the instance host
record changed. This is because live migrations can fail and simply
return the instance to an active state, so the only way to know for
sure we have completed successfully is to check the host before and
after the operation is initiated.
Change-Id: I642f0ecc2b5c84202ebacd01e2b0c85ab609e597
---
doc/samples/tasks/scenarios/nova/live_migrate.json | 26 ++++++++++++++++++++
doc/samples/tasks/scenarios/nova/live_migrate.yaml | 16 ++++++++++++
rally/benchmark/scenarios/nova/servers.py | 15 +++++++++++
rally/benchmark/scenarios/nova/utils.py | 20 +++++++++++++++
tests/benchmark/scenarios/nova/test_servers.py | 17 +++++++++++++
5 files changed, 94 insertions(+)
create mode 100644 doc/samples/tasks/scenarios/nova/live_migrate.json
create mode 100644 doc/samples/tasks/scenarios/nova/live_migrate.yaml
diff --git a/doc/samples/tasks/scenarios/nova/live_migrate.json b/doc/samples/tasks/scenarios/nova/live_migrate.json
new file mode 100644
index 0000000..2bdc9c4
--- /dev/null
+++ b/doc/samples/tasks/scenarios/nova/live_migrate.json
@@ -0,0 +1,26 @@
+{
+ "NovaServers.live_migrate_server": [
+ {
+ "args": {
+ "flavor": {
+ "name": "m1.nano"
+ },
+ "image": {
+ "name": "cirros-0.3.1-x86_64-uec"
+ },
+ "block_migration": false
+ },
+ "runner": {
+ "type": "constant",
+ "times": 1,
+ "concurrency": 1
+ },
+ "context": {
+ "users": {
+ "tenants": 1,
+ "users_per_tenant": 1
+ }
+ }
+ }
+ ]
+}
diff --git a/doc/samples/tasks/scenarios/nova/live_migrate.yaml b/doc/samples/tasks/scenarios/nova/live_migrate.yaml
new file mode 100644
index 0000000..654541b
--- /dev/null
+++ b/doc/samples/tasks/scenarios/nova/live_migrate.yaml
@@ -0,0 +1,16 @@
+---
+NovaServers.live_migrate_server:
+- args:
+ flavor:
+ name: m1.nano
+ image:
+ name: cirros-0.3.1-x86_64-uec
+ block_migration: false
+ runner:
+ type: constant
+ times: 1
+ concurrency: 1
+ context:
+ users:
+ tenants: 1
+ users_per_tenant: 1
diff --git a/rally/benchmark/scenarios/nova/servers.py b/rally/benchmark/scenarios/nova/servers.py
index 759e491..e49c8f8 100644
--- a/rally/benchmark/scenarios/nova/servers.py
+++ b/rally/benchmark/scenarios/nova/servers.py
@@ -231,3 +231,18 @@ class NovaServers(utils.NovaScenario,
else:
self._resize_revert(server)
self._delete_server(server)
+
+ @types.set(image=types.ImageResourceType,
+ flavor=types.FlavorResourceType,
+ to_flavor=types.FlavorResourceType)
+ @validation.add(validation.image_valid_on_flavor("flavor", "image"))
+ @base.scenario(admin_only=True, context={"cleanup": ["nova"]})
+ @validation.required_services(consts.Service.NOVA)
+ def live_migrate_server(self, image, flavor, **kwargs):
+ """Tests live migration."""
+ server = self._boot_server(self._generate_random_name(),
+ image, flavor, **kwargs)
+
+ block_migration = kwargs.get('block_migration', False)
+ self._live_migrate(server, block_migration)
+ self._delete_server(server)
diff --git a/rally/benchmark/scenarios/nova/utils.py b/rally/benchmark/scenarios/nova/utils.py
index 14eadd3..3cb02fb 100644
--- a/rally/benchmark/scenarios/nova/utils.py
+++ b/rally/benchmark/scenarios/nova/utils.py
@@ -21,6 +21,8 @@ from rally.benchmark.scenarios import base
from rally.benchmark.scenarios import utils as scenario_utils
from rally.benchmark import utils as bench_utils
+from rally import exceptions as rally_exceptions
+
nova_benchmark_opts = []
option_names_and_defaults = [
@@ -38,6 +40,7 @@ option_names_and_defaults = [
('resize', 2, 400, 5),
('resize_confirm', 0, 200, 2),
('resize_revert', 0, 200, 2),
+ ('live_migrate', 0, 300, 2),
]
for action, prepoll, timeout, poll in option_names_and_defaults:
@@ -460,3 +463,20 @@ class NovaScenario(base.Scenario):
check_interval=(
CONF.benchmark.nova_server_resize_revert_poll_interval)
)
+
+ @scenario_utils.atomic_action_timer('nova.live_migrate')
+ def _live_migrate(self, server, block_migration=False):
+ server_admin = self.admin_clients("nova").servers.get(server.id)
+ host_pre_migrate = server_admin._info['OS-EXT-SRV-ATTR:host']
+ server_admin.live_migrate(block_migration=block_migration)
+ bench_utils.wait_for(
+ server,
+ is_ready=bench_utils.resource_is("ACTIVE"),
+ update_resource=bench_utils.get_from_manager(),
+ timeout=CONF.benchmark.nova_server_live_migrate_timeout,
+ check_interval=(
+ CONF.benchmark.nova_server_live_migrate_poll_interval)
+ )
+ if host_pre_migrate == server_admin._info['OS-EXT-SRV-ATTR:host']:
+ raise rally_exceptions.TestException(
+ "Migration complete but instance did not change hosts")
diff --git a/tests/benchmark/scenarios/nova/test_servers.py b/tests/benchmark/scenarios/nova/test_servers.py
index 74fb866..9b6f343 100644
--- a/tests/benchmark/scenarios/nova/test_servers.py
+++ b/tests/benchmark/scenarios/nova/test_servers.py
@@ -353,3 +353,20 @@ class NovaServersTestCase(test.TestCase):
def test_resize_with_revert(self):
self._test_resize(confirm=False)
+
+ def test_live_migrate_server(self):
+ fake_server = object()
+ fake_image = fakes.FakeImageManager()._create()
+ fake_image.id = "image_id"
+
+ scenario = servers.NovaServers()
+ scenario._generate_random_name = mock.MagicMock(return_value="name")
+ scenario._boot_server = mock.MagicMock(return_value=fake_server)
+ scenario._live_migrate = mock.MagicMock()
+ scenario._delete_server = mock.MagicMock()
+
+ scenario.live_migrate_server("img", 0)
+
+ scenario._boot_server.assert_called_once_with("name", "img", 0)
+ scenario._live_migrate.assert_called_once_with(fake_server, False)
+ scenario._delete_server.assert_called_once_with(fake_server)
--
1.7.9.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment