32
Nova Nova live live - - migration migration のはなし のはなし 江口裕之 江口裕之

Nova live -migration のはなし - openstack.jp · 処理概要 nova-api nova-scheduler nova-compute (移行元) nova-compute (移行先) Thread API 権限・パラメータチェック

  • Upload
    others

  • View
    14

  • Download
    0

Embed Size (px)

Citation preview

NovaNova

livelive--migrationmigrationのはなしのはなし

江口裕之江口裕之

今回のテーマ今回のテーマ

NovaNovaののmigrationmigration機能について機能について

NovaNovaののmigrationmigration機能は以下の3つ機能は以下の3つ1.1. MigrationMigration機能機能

2.2. LiveLive--migrationmigration機能機能

3.3. BlockBlock--migrationmigration機能機能

今回は今回はLiveLive--migrationmigrationととBlockBlock--migrationmigrationにについて説明したいと思いますついて説明したいと思います

1.Migration1.Migration機能機能いわゆるコールドマイグレーションいわゆるコールドマイグレーション

停止しているVMを他のホストに移動停止しているVMを他のホストに移動rsyncrsyncによりディスクイメージ等をコピーによりディスクイメージ等をコピー�� sshssh鍵の事前設定が必要鍵の事前設定が必要

コマンドの必須パラメータはコマンドの必須パラメータはserver(VMserver(VM))のみのみ�� 移動先は指定しない移動先は指定しない

# nova migrate <server># nova migrate <server>

nova-compute nova-compute

VM

(SHUTOFF)

VM

(SHUTOFF)rsync

command

22.Live.Live--MigrationMigration機能機能稼動しているVMを他のホストに移動稼動しているVMを他のホストに移動libvirtdlibvirtdによりメモリをコピーによりメモリをコピー�� libvirtdlibvirtd設定が必要設定が必要

共有ディスク環境必須共有ディスク環境必須�� VM情報の格納場所(VM情報の格納場所(//varvar/lib/nova/instances/lib/nova/instances)を共有する)を共有する

コマンドにコマンドにserverserver((VMVM)と)とhosthost(移行先ホスト)を指定(移行先ホスト)を指定

# nova live# nova live--migration <server> <host>migration <server> <host>

nova-compute nova-compute

VM

(ACTIVE) libvirtd

command

VM

(ACTIVE)

/var/lib/nova/instances

共有共有共有共有ディスクディスクディスクディスク

33.Block.Block--MigrationMigration機能機能稼動しているVMを他のホストに移動稼動しているVMを他のホストに移動

libvirtdlibvirtdによりディスクおよびメモリをコピーによりディスクおよびメモリをコピー�� libvirtdlibvirtdの設定が必要の設定が必要

共有ディスク環境は必要なし共有ディスク環境は必要なしコマンドにコマンドにserverserver((VMVM)と)とhosthost(移行先ホスト)を指定(移行先ホスト)を指定�� コマンドとしてはコマンドとしてはlivelive--migrationmigrationコマンドコマンド�� オプションとしてオプションとして----block_migrateblock_migrateと指定することでと指定することでBlockBlock--MigrationMigrationを実施を実施

# nova live# nova live--migration migration ----block_migrateblock_migrate [[----diskdisk--overover--commit] commit] <server> <host><server> <host>

nova-compute nova-compute

command

libvirtdVM

(ACTIVE)

VM

(ACTIVE)

では実際のソース(一部抜粋)を見ながらでは実際のソース(一部抜粋)を見ながら

LiveLive--migrationmigration

((BlockBlock--migrationmigration))

についてについて

解説していきます解説していきます

処理概要処理概要novanova--apiapi novanova--schedulerscheduler novanova--computecompute

((移行元移行元))novanova--computecompute

((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

novanova--apiapi

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--apiapiの役割>の役割>

--> > 権限・パラメータチェック権限・パラメータチェック--> nova> nova--schedulerschedulerへの処理依頼への処理依頼

novanova--apiapi 権限・パラメータチェック権限・パラメータチェックnova/nova/api/openstack/compute/contrib/admin_actions.pyapi/openstack/compute/contrib/admin_actions.py

def _def _migrate_live(selfmigrate_live(self, , reqreq, id, body):, id, body):

context = context = req.environ["nova.contextreq.environ["nova.context"]"]

authorize(contextauthorize(context, ', 'migrateLivemigrateLive')')

try:try:

block_migrationblock_migration = = body["osbody["os--migrateLive"]["block_migrationmigrateLive"]["block_migration"]"]

disk_over_commitdisk_over_commit = = body["osbody["os--migrateLive"]["disk_over_commitmigrateLive"]["disk_over_commit"]"]

host = host = body["osbody["os--migrateLive"]["hostmigrateLive"]["host"]"]

except (except (TypeErrorTypeError, , KeyErrorKeyError):):

msgmsg = _("host and = _("host and block_migrationblock_migration must be specified.")must be specified.")

raise raise exc.HTTPBadRequest(explanationexc.HTTPBadRequest(explanation==msgmsg))

try:try:

instance = instance = self.compute_api.get(contextself.compute_api.get(context, id), id)

self.compute_api.live_migrate(contextself.compute_api.live_migrate(context, instance, , instance, block_migrationblock_migration,,

disk_over_commitdisk_over_commit, host), host)

except Exception:except Exception:

raise raise exc.HTTPBadRequest(explanationexc.HTTPBadRequest(explanation==msgmsg))

return return webob.Response(status_intwebob.Response(status_int=202)=202)

権限チェック権限チェック

パラメータパラメータ

チェックチェック

novanova--schedulerschedulerへのへの処理依頼処理依頼

novanova--schedulerschedulerへの処理依頼への処理依頼nova/compute/nova/compute/api.pyapi.py

@@check_instance_state(vm_statecheck_instance_state(vm_state=[=[vm_states.ACTIVEvm_states.ACTIVE])])

def def live_migrate(selflive_migrate(self, context, instance, , context, instance, block_migrationblock_migration,,

disk_over_commitdisk_over_commit, host):, host):

"""Migrate a server lively to a new host.""""""Migrate a server lively to a new host."""

LOG.debug(_("GoingLOG.debug(_("Going to try to live migrate instance to %s"),to try to live migrate instance to %s"),

host, instance=host, instance=instanceinstance))

instance = instance = self.update(contextself.update(context, instance,, instance,

task_statetask_state==task_states.MIGRATINGtask_states.MIGRATING,,

expected_task_stateexpected_task_state=None)=None)

self.scheduler_rpcapi.live_migration(contextself.scheduler_rpcapi.live_migration(context, , block_migrationblock_migration,,

disk_over_commitdisk_over_commit, instance, host), instance, host)novanova--schedulerschedulerへのへの処理依頼処理依頼

novanova--schedulerscheduler

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--schedulerschedulerの役割>の役割>--> > 各種事前チェック各種事前チェック--> > 移行先に事前チェック依頼移行先に事前チェック依頼

各種事前チェック各種事前チェック

nova/scheduler/nova/scheduler/driver.pydriver.py

def def schedule_live_migration(selfschedule_live_migration(self, context, instance, , context, instance, destdest,,

block_migrationblock_migration, , disk_over_commitdisk_over_commit):):

# Check we can do live migration# Check we can do live migration

self._live_migration_src_check(contextself._live_migration_src_check(context, instance), instance)

self._live_migration_dest_check(contextself._live_migration_dest_check(context, instance, , instance, destdest))

self._live_migration_common_check(contextself._live_migration_common_check(context, instance, , instance, destdest))

migrate_datamigrate_data = = self.compute_rpcapi.check_can_live_migrate_destinationself.compute_rpcapi.check_can_live_migrate_destination((

context, instance, context, instance, destdest, , block_migrationblock_migration, , disk_over_commitdisk_over_commit))

# Perform migration# Perform migration

srcsrc = = instance['hostinstance['host']']

self.compute_rpcapi.live_migration(contextself.compute_rpcapi.live_migration(context, host=, host=srcsrc,,

instance=instance=instanceinstance, , destdest==destdest,,

block_migrationblock_migration==block_migrationblock_migration,,

migrate_datamigrate_data==migrate_datamigrate_data))

nova/scheduler/nova/scheduler/driver.pydriver.py

def _def _live_migration_src_check(selflive_migration_src_check(self, context, , context, instance_refinstance_ref):):

# Checking instance is running.# Checking instance is running.

if if instance_ref['power_stateinstance_ref['power_state'] != '] != power_state.RUNNINGpower_state.RUNNING::

raise raise exception.InstanceNotRunningexception.InstanceNotRunning((

instance_idinstance_id==instance_ref['uuidinstance_ref['uuid'])'])

# Checking # Checking srcsrc host exists and compute nodehost exists and compute node

srcsrc = = instance_ref['hostinstance_ref['host']']

try:try:

services = services = db.service_get_all_compute_by_host(contextdb.service_get_all_compute_by_host(context, , srcsrc))

except except exception.NotFoundexception.NotFound::

raise raise exception.ComputeServiceUnavailable(hostexception.ComputeServiceUnavailable(host==srcsrc))

# Checking # Checking srcsrc host is alive.host is alive.

if not utils.service_is_up(services[0]):if not utils.service_is_up(services[0]):

raise raise exception.ComputeServiceUnavailable(hostexception.ComputeServiceUnavailable(host==srcsrc))

移行元移行元novanova--computecomputeに対しての事前チェックに対しての事前チェック

VMのステータスVMのステータスチェックチェック

ホストのチェックホストのチェック

novanova--computecompute

の死活チェックの死活チェック

nova/scheduler/nova/scheduler/driver.pydriver.py

def _def _live_migration_dest_check(selflive_migration_dest_check(self, context, , context, instance_refinstance_ref, , destdest):):

# Checking # Checking destdest exists and compute node.exists and compute node.

dservice_refsdservice_refs = = db.service_get_all_compute_by_host(contextdb.service_get_all_compute_by_host(context, , destdest))

dservice_refdservice_ref = dservice_refs[0]= dservice_refs[0]

# Checking # Checking destdest host is alive.host is alive.

if not if not utils.service_is_up(dservice_refutils.service_is_up(dservice_ref):):

raise raise exception.ComputeServiceUnavailable(hostexception.ComputeServiceUnavailable(host==destdest))

# Checking whether The host where instance is running# Checking whether The host where instance is running

# and # and destdest is not same.is not same.

srcsrc = = instance_ref['hostinstance_ref['host']']

if if destdest == == srcsrc::

raise raise exception.UnableToMigrateToSelfexception.UnableToMigrateToSelf((

instance_idinstance_id==instance_ref['uuidinstance_ref['uuid'], host='], host=destdest))

# Check memory requirements# Check memory requirements

self._assert_compute_node_has_enough_memory(contextself._assert_compute_node_has_enough_memory(context,,

instance_refinstance_ref, , destdest))

移行先移行先novanova--computecomputeに対しての事前チェックに対しての事前チェック

ホストのチェックホストのチェック

novanova--computecompute

の死活チェックの死活チェック

ホストのチェックホストのチェック

移行元=移行先移行元=移行先でないかでないか

リソースのリソースの空きチェック空きチェック

nova/scheduler/nova/scheduler/driver.pydriver.py

def _def _live_migration_common_check(selflive_migration_common_check(self, context, , context, instance_refinstance_ref, , destdest):):

dservice_refdservice_ref = = self._get_compute_info(contextself._get_compute_info(context, , destdest))

srcsrc = = instance_ref['hostinstance_ref['host']']

oservice_refoservice_ref = = self._get_compute_info(contextself._get_compute_info(context, , srcsrc))

# Checking hypervisor is same.# Checking hypervisor is same.

orig_hypervisororig_hypervisor = = oservice_ref['hypervisor_typeoservice_ref['hypervisor_type']']

dest_hypervisordest_hypervisor = = dservice_ref['hypervisor_typedservice_ref['hypervisor_type']']

if if orig_hypervisororig_hypervisor != != dest_hypervisordest_hypervisor::

raise raise exception.InvalidHypervisorTypeexception.InvalidHypervisorType()()

# Checking hypervisor version.# Checking hypervisor version.

orig_hypervisororig_hypervisor = = oservice_ref['hypervisor_versionoservice_ref['hypervisor_version']']

dest_hypervisordest_hypervisor = = dservice_ref['hypervisor_versiondservice_ref['hypervisor_version']']

if if orig_hypervisororig_hypervisor > > dest_hypervisordest_hypervisor::

raise raise exception.DestinationHypervisorTooOldexception.DestinationHypervisorTooOld()()

共通の事前チェック共通の事前チェック

ハイパーバイザハイパーバイザチェックチェック

ハイパーバイザのハイパーバイザのバージョンチェックバージョンチェック

novanova--schedulerscheduler

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--schedulerschedulerの役割>の役割>--> > 各種事前チェック各種事前チェック--> > 移行先に事前チェック依頼移行先に事前チェック依頼

novanova--computecomputeに対しての事前チェック依頼に対しての事前チェック依頼

nova/scheduler/nova/scheduler/driver.pydriver.py

def def schedule_live_migration(selfschedule_live_migration(self, context, instance, , context, instance, destdest,,

block_migrationblock_migration, , disk_over_commitdisk_over_commit):):

# Check we can do live migration# Check we can do live migration

self._live_migration_src_check(contextself._live_migration_src_check(context, instance), instance)

self._live_migration_dest_check(contextself._live_migration_dest_check(context, instance, , instance, destdest))

self._live_migration_common_check(contextself._live_migration_common_check(context, instance, , instance, destdest))

migrate_datamigrate_data = = self.compute_rpcapi.check_can_live_migrate_destinationself.compute_rpcapi.check_can_live_migrate_destination((

context, instance, context, instance, destdest, , block_migrationblock_migration, , disk_over_commitdisk_over_commit))

# Perform migration# Perform migration

srcsrc = = instance['hostinstance['host']']

self.compute_rpcapi.live_migration(contextself.compute_rpcapi.live_migration(context, host=, host=srcsrc,,

instance=instance=instanceinstance, , destdest==destdest,,

block_migrationblock_migration==block_migrationblock_migration,,

migrate_datamigrate_data==migrate_datamigrate_data))

移行先移行先novanova--computecomputeへへ事前チェック依頼事前チェック依頼

nova/compute/nova/compute/manager.pymanager.py

@@exception.wrap_exception(notifierexception.wrap_exception(notifier==notifiernotifier, , publisher_idpublisher_id==publisher_idpublisher_id())())

def def check_can_live_migrate_destination(selfcheck_can_live_migrate_destination(self, , ctxtctxt, instance,, instance,

block_migrationblock_migration=False,=False,

disk_over_commitdisk_over_commit=False):=False):

dest_check_datadest_check_data = = self.driver.check_can_live_migrate_destination(ctxtself.driver.check_can_live_migrate_destination(ctxt,,

instance, instance, block_migrationblock_migration, , disk_over_commitdisk_over_commit))

try:try:

self.compute_rpcapi.check_can_live_migrate_source(ctxtself.compute_rpcapi.check_can_live_migrate_source(ctxt,,

instance, instance, dest_check_datadest_check_data))

finally:finally:

self.driver.check_can_live_migrate_destination_cleanup(ctxtself.driver.check_can_live_migrate_destination_cleanup(ctxt,,

dest_check_datadest_check_data))

if if dest_check_datadest_check_data and 'and 'migrate_datamigrate_data' in ' in dest_check_datadest_check_data::

return return dest_check_data['migrate_datadest_check_data['migrate_data']']

移行先移行先novanova--computecompute上での事前チェック上での事前チェック

移行元移行元novanova--computecomputeへ事前チェック依頼へ事前チェック依頼作成した一時ファイルを読めるか(共有ディスク環境であるか)作成した一時ファイルを読めるか(共有ディスク環境であるか)

をチェックするをチェックする

共有ディスク環境チェック共有ディスク環境チェック//varvar/lib/nova/instance/lib/nova/instanceにに

一時ファイルを作成一時ファイルを作成

nova/compute/nova/compute/manager.pymanager.py

@@exception.wrap_exception(notifierexception.wrap_exception(notifier==notifiernotifier, , publisher_idpublisher_id==publisher_idpublisher_id())())

def def check_can_live_migrate_source(selfcheck_can_live_migrate_source(self, , ctxtctxt, instance, , instance, dest_check_datadest_check_data):):

self.driver.check_can_live_migrate_source(ctxtself.driver.check_can_live_migrate_source(ctxt, instance,, instance,

dest_check_datadest_check_data))

移行元移行元novanova--computecompute上での事前チェック上での事前チェック

本処理の中で一時ファイルを読み込めるか確認本処理の中で一時ファイルを読み込めるか確認

novanova--computecompute

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--computecomputeの役割>の役割>--> live> live--migration(blockmigration(block--migration)migration)の実施の実施--> > 前処理前処理、本処理、移行元での後処理、、本処理、移行元での後処理、

移行先での後処理の移行先での後処理の4処理4処理

nova/compute/nova/compute/manager.pymanager.py

def pre_live_migration(self, context, instance,def pre_live_migration(self, context, instance,

block_migration=False, disk=None):block_migration=False, disk=None):

# If any volume is mounted, prepare here.# If any volume is mounted, prepare here.

block_device_info = self._get_instance_volume_block_deviblock_device_info = self._get_instance_volume_block_device_info(ce_info(

context, instance['uuid'])context, instance['uuid'])

# TODO(tr3buchet): figure out how on the earth this is necessary# TODO(tr3buchet): figure out how on the earth this is necessary

fixed_ips = network_info.fixed_ips()fixed_ips = network_info.fixed_ips()

if not fixed_ips:if not fixed_ips:

raise exception.FixedIpNotFoundForInstance(raise exception.FixedIpNotFoundForInstance(

instance_uuid=instance['uinstance_uuid=instance['uuid'])uid'])

self.driver.pre_live_migration(context, instance,self.driver.pre_live_migration(context, instance,

block_device_info,block_device_info,

self._legacy_nw_info(netwself._legacy_nw_info(network_info))ork_info))

# NOTE(tr3buchet): setup networks on destination host# NOTE(tr3buchet): setup networks on destination host

self.network_api.setup_networks_on_host(context, instancself.network_api.setup_networks_on_host(context, instance,e, self.host)self.host)

# Creating filters to hypervisors and firewalls.# Creating filters to hypervisors and firewalls.

self.driver.ensure_filtering_rules_for_instance(instanceself.driver.ensure_filtering_rules_for_instance(instance,,

self._legacy_nw_infoself._legacy_nw_info(network_info))(network_info))

livelive--migrationmigration前処理前処理

volumevolume設定設定

FWFW事前設定事前設定

NWNW事前設定事前設定

novanova--computecompute

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--computecomputeの役割>の役割>--> live> live--migration(blockmigration(block--migration)migration)の実施の実施--> > 前処理、前処理、本処理本処理、移行元での後処理、、移行元での後処理、

移行先での後処理の4処理移行先での後処理の4処理

nova/nova/vir/libvirt/driver.pyvir/libvirt/driver.py

def live_migration(self, ctxt, instance_ref, dest,def live_migration(self, ctxt, instance_ref, dest,

post_method, recover_method, block_migratpost_method, recover_method, block_migration=False,ion=False,

migrate_data=None):migrate_data=None):

greenthread.spawn(self._live_migration, ctxt, instance_rgreenthread.spawn(self._live_migration, ctxt, instance_ref, dest,ef, dest,

post_method, recover_method, block_migpost_method, recover_method, block_migration)ration)

livelive--migrationmigration本処理本処理

本処理はこれだけ本処理はこれだけ

内部メソッド内部メソッド self._live_migrationself._live_migrationを別スレッドで実行を別スレッドで実行

nova/nova/vir/libvirt/driver.pyvir/libvirt/driver.py

def _live_migration(self, ctxt, instance_ref, dest, post_methoddef _live_migration(self, ctxt, instance_ref, dest, post_method,,

recover_method, block_migration=False):recover_method, block_migration=False):

try:try:

dom.migrateToURI(FLAGS.live_migration_uri % dest,dom.migrateToURI(FLAGS.live_migration_uri % dest,

logical_sum,logical_sum, None,None, FLAGS.live_migration_bandwidth)FLAGS.live_migration_bandwidth)

except Exception as e:except Exception as e:

with excutils.save_and_reraise_exception():with excutils.save_and_reraise_exception():

recover_method(ctxt, instance_ref, dest, block_migration)recover_method(ctxt, instance_ref, dest, block_migration)

def wait_for_live_migration():def wait_for_live_migration():

"""waiting for live migration completion""""""waiting for live migration completion"""

try:try:

self.get_info(instance_ref)['state']self.get_info(instance_ref)['state']

except exception.NotFound:except exception.NotFound:

timer.stop()timer.stop()

post_method(ctxt, instance_ref, dest, block_migrpost_method(ctxt, instance_ref, dest, block_migration)ation)

timer.f = wait_for_live_migrationtimer.f = wait_for_live_migration

timer.start(interval=0.5).wait()timer.start(interval=0.5).wait()

livelive--migrationmigration本処理本処理

migrationmigration実行実行

migrationmigration完了待ち完了待ち

novanova--computecompute

novanova--apiapi novanova--schedulerscheduler novanova--computecompute((移行元移行元))

novanova--computecompute((移行先移行先))

ThreadThread

APIAPI 権限・パラメータチェック権限・パラメータチェック

スケジューラに依頼スケジューラに依頼各種事前チェック各種事前チェック

移行先に事前チェック依頼移行先に事前チェック依頼

移行元に事前チェック依頼移行元に事前チェック依頼

livelive--migrationmigration依頼依頼livelive--migrationmigration前処理前処理

livelive--migrationmigration本処理本処理

LiveLive--migrationmigration後処理後処理(移行元)(移行元)

LiveLive--migrationmigration後処理後処理(移行先)(移行先)

live-migration前処理終了時点でAPIに応答

本処理は別スレッドで実施

<<novanova--computecomputeの役割>の役割>--> live> live--migration(blockmigration(block--migration)migration)の実施の実施--> > 前処理、前処理、本処理本処理、、移行元での後処理、移行元での後処理、

移行先での後処理移行先での後処理の4処理の4処理

nova/nova/vir/libvirt/driver.pyvir/libvirt/driver.py

def _post_live_migration(self, ctxt, instance_ref,def _post_live_migration(self, ctxt, instance_ref,

dest, block_migration=False):dest, block_migration=False):

# Detaching volumes.# Detaching volumes.

for bdm in self._get_instance_volume_bdms(ctxt, instancefor bdm in self._get_instance_volume_bdms(ctxt, instance_ref['uuid']):_ref['uuid']):

self.remove_volume_connection(ctxt, bdm[self.remove_volume_connection(ctxt, bdm[‘‘volume_idvolume_id’’],], instance_ref)instance_ref)

# Releasing vlan.# Releasing vlan.

network_info = self._get_instance_nw_info(ctxt, instancenetwork_info = self._get_instance_nw_info(ctxt, instance_ref)_ref)

# Releasing security group ingress rule.# Releasing security group ingress rule.

self.driver.unfilter_instance(instance_ref,self.driver.unfilter_instance(instance_ref,

self._legacy_nw_info(netwoself._legacy_nw_info(network_info))rk_info))

# Define domain at destination host, without doing it,# Define domain at destination host, without doing it,

self.compute_rpcapi.post_live_migration_at_destination(ctxt,self.compute_rpcapi.post_live_migration_at_destination(ctxt,

instance_ref, block_migration, dest)instance_ref, block_migration, dest)

if block_migration:if block_migration:

self.driver.destroy(instance_ref,self.driver.destroy(instance_ref, self._legacy_nw_info(network_info))self._legacy_nw_info(network_info))

else:else:

self.driver.unplug_vifs(instance_ref,self.driver.unplug_vifs(instance_ref, self._legacy_nw_info(network_info))self._legacy_nw_info(network_info))

livelive--migrationmigration移行元での後処理移行元での後処理

VolumeVolumeデタッチデタッチ

VLANVLAN開放開放

FWFW設定設定

解除解除

VMVM削除削除

nova/compute/nova/compute/manager.pymanager.py

def post_live_migration_at_destination(self, context, instance,def post_live_migration_at_destination(self, context, instance,

block_migration=Falseblock_migration=False):):

self.network_api.setup_networks_on_host(context, instance,self.network_api.setup_networks_on_host(context, instance,

self.hoself.host)st)

network_info = self._get_instance_nw_info(context, instanetwork_info = self._get_instance_nw_info(context, instance)nce)

self.driver.post_live_migration_at_destination(context, self.driver.post_live_migration_at_destination(context, instance,instance,

self._legacy_nw_infoself._legacy_nw_info(network_info),(network_info),

block_migration)block_migration)

# Restore instance state# Restore instance state

current_power_state = self._get_power_state(context, inscurrent_power_state = self._get_power_state(context, instance)tance)

self._instance_update(context,self._instance_update(context,

instance['uuid'],instance['uuid'],

host=self.host,host=self.host,

power_state=current_power_state,power_state=current_power_state,

vm_state=vm_states.ACTIVE,vm_state=vm_states.ACTIVE,

task_state=None,task_state=None,

expected_task_state=task_states.MIexpected_task_state=task_states.MIGRATING)GRATING)

livelive--migrationmigration移行先での後処理移行先での後処理

DBDB

更新更新

GrizzlyGrizzlyリリースでのリリースでのlivelive--migrationmigration機能機能

以下の2機能が追加される予定以下の2機能が追加される予定

�� BootFromVolumeBootFromVolume VMのVMのlivelive--migrationmigration機能機能

�� BootFromVolumeBootFromVolume VMのVMのvolumevolume--migrationmigration機能機能

cinder-volumecinder-volume

BootFromVolumeBootFromVolumeとはとはEssexEssexリリースにて実装された機能リリースにて実装された機能

VolumeVolumeからVMを起動可能からVMを起動可能�� それまではそれまではVolumeVolumeは追加ディスクとしてアタッチする用途が主は追加ディスクとしてアタッチする用途が主

�� 事前に事前にVolumeVolumeに起動可能なシステム領域を格納しておきVMを稼動に起動可能なシステム領域を格納しておきVMを稼動

# nova boot # nova boot ----block_device_mappingblock_device_mappingvdavda=<=<volume_idvolume_id>:<type>:<size>:<>:<type>:<size>:<delete_on_terminationdelete_on_termination>><<server_nameserver_name>>

command

nova-compute

VM

(ACTIVE)

仮想ディスク仮想ディスク

volumevolume

nova-compute

VM

(ACTIVE) volumevolume

主な主なvolumevolumeの使い方の使い方 BootFromVolumeBootFromVolume

cinder-volume

BootFromVolumeBootFromVolume VMのVMのlivelive--migrationmigration

共有ディスク環境なしで共有ディスク環境なしでlivelive--migrationmigrationが可能が可能

nova-compute

VM

(ACTIVE)

volumevolume

nova-compute

VM

(ACTIVE)live-migration

cinder-volume

BootFromVolumeBootFromVolume VMのVMのvolumevolume--migrationmigration

volumevolumeののmigrationmigrationが可能が可能

nova-compute

VM

(ACTIVE)

volumevolume

cinder-volume

volumevolumevolume-migration

おわりおわり

ご静聴ありがとうございましたご静聴ありがとうございました