Nova live -migration のはなし - openstack.jp · 処理概要 nova-api nova-scheduler...
Transcript of Nova live -migration のはなし - openstack.jp · 処理概要 nova-api nova-scheduler...
今回のテーマ今回のテーマ
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