<s> """<STR_LIT>""" <EOL> import logging <EOL> import time <EOL> from ganeti import constants <EOL> from ganeti import errors <EOL> from ganeti import locking <EOL> from ganeti import hypervisor <EOL> from ganeti . masterd import iallocator <EOL> from ganeti import utils <EOL> from ganeti . cmdlib . base import LogicalUnit , Tasklet <EOL> from ganeti . cmdlib . common import ExpandInstanceUuidAndName , CheckIAllocatorOrNode , ExpandNodeUuidAndName <EOL> from ganeti . cmdlib . instance_storage import CheckDiskConsistency , ExpandCheckDisks , ShutdownInstanceDisks , AssembleInstanceDisks <EOL> from ganeti . cmdlib . instance_utils import BuildInstanceHookEnvByObject , CheckTargetNodeIPolicy , ReleaseLocks , CheckNodeNotDrained , CopyLockList , CheckNodeFreeMemory , CheckInstanceBridgesExist <EOL> import ganeti . masterd . instance <EOL> def _ExpandNamesForMigration ( lu ) : <EOL> """<STR_LIT>""" <EOL> if lu . op . target_node is not None : <EOL> ( lu . op . target_node_uuid , lu . op . target_node ) = ExpandNodeUuidAndName ( lu . cfg , lu . op . target_node_uuid , lu . op . target_node ) <EOL> lu . needed_locks [ locking . LEVEL_NODE ] = [ ] <EOL> lu . recalculate_locks [ locking . LEVEL_NODE ] = constants . LOCKS_REPLACE <EOL> lu . dont_collate_locks [ locking . LEVEL_NODE ] = True <EOL> lu . needed_locks [ locking . LEVEL_NODE_RES ] = [ ] <EOL> lu . recalculate_locks [ locking . LEVEL_NODE_RES ] = constants . LOCKS_REPLACE <EOL> lu . dont_collate_locks [ locking . LEVEL_NODE_RES ] = True <EOL> def _DeclareLocksForMigration ( lu , level ) : <EOL> """<STR_LIT>""" <EOL> if level == locking . LEVEL_NODE : <EOL> assert lu . op . instance_name in lu . owned_locks ( locking . LEVEL_INSTANCE ) <EOL> instance = lu . cfg . GetInstanceInfo ( lu . op . instance_uuid ) <EOL> disks = lu . cfg . GetInstanceDisks ( instance . uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_EXT_MIRROR ) : <EOL> if lu . op . target_node is None : <EOL> lu . needed_locks [ locking . LEVEL_NODE ] = locking . ALL_SET <EOL> else : <EOL> lu . needed_locks [ locking . LEVEL_NODE ] = [ instance . primary_node , <EOL> lu . op . target_node_uuid ] <EOL> else : <EOL> lu . _LockInstancesNodes ( ) <EOL> assert ( lu . needed_locks [ locking . LEVEL_NODE ] or <EOL> lu . needed_locks [ locking . LEVEL_NODE ] is locking . ALL_SET ) <EOL> elif level == locking . LEVEL_NODE_RES : <EOL> lu . needed_locks [ locking . LEVEL_NODE_RES ] = CopyLockList ( lu . needed_locks [ locking . LEVEL_NODE ] ) <EOL> class LUInstanceFailover ( LogicalUnit ) : <EOL> """<STR_LIT>""" <EOL> HPATH = "<STR_LIT>" <EOL> HTYPE = constants . HTYPE_INSTANCE <EOL> REQ_BGL = False <EOL> def CheckArguments ( self ) : <EOL> """<STR_LIT>""" <EOL> self . iallocator = getattr ( self . op , "<STR_LIT>" , None ) <EOL> self . target_node = getattr ( self . op , "<STR_LIT>" , None ) <EOL> def ExpandNames ( self ) : <EOL> self . _ExpandAndLockInstance ( allow_forthcoming = True ) <EOL> _ExpandNamesForMigration ( self ) <EOL> self . _migrater = TLMigrateInstance ( self , self . op . instance_uuid , self . op . instance_name , <EOL> self . op . cleanup , True , False , <EOL> self . op . ignore_consistency , True , <EOL> self . op . shutdown_timeout , self . op . ignore_ipolicy , True ) <EOL> self . tasklets = [ self . _migrater ] <EOL> def DeclareLocks ( self , level ) : <EOL> _DeclareLocksForMigration ( self , level ) <EOL> def BuildHooksEnv ( self ) : <EOL> """<STR_LIT>""" <EOL> instance = self . _migrater . instance <EOL> source_node_uuid = instance . primary_node <EOL> target_node_uuid = self . _migrater . target_node_uuid <EOL> env = { <EOL> "<STR_LIT>" : self . op . ignore_consistency , <EOL> "<STR_LIT>" : self . op . shutdown_timeout , <EOL> "<STR_LIT>" : self . cfg . GetNodeName ( source_node_uuid ) , <EOL> "<STR_LIT>" : self . cfg . GetNodeName ( target_node_uuid ) , <EOL> "<STR_LIT>" : self . op . cleanup , <EOL> } <EOL> disks = self . cfg . GetInstanceDisks ( instance . uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> secondary_nodes = self . cfg . GetInstanceSecondaryNodes ( instance . uuid ) <EOL> env [ "<STR_LIT>" ] = self . cfg . GetNodeName ( secondary_nodes [ <NUM_LIT:0> ] ) <EOL> env [ "<STR_LIT>" ] = self . cfg . GetNodeName ( source_node_uuid ) <EOL> else : <EOL> env [ "<STR_LIT>" ] = env [ "<STR_LIT>" ] = "<STR_LIT>" <EOL> env . update ( BuildInstanceHookEnvByObject ( self , instance ) ) <EOL> return env <EOL> def BuildHooksNodes ( self ) : <EOL> """<STR_LIT>""" <EOL> instance = self . _migrater . instance <EOL> secondary_nodes = self . cfg . GetInstanceSecondaryNodes ( instance . uuid ) <EOL> nl = [ self . cfg . GetMasterNode ( ) ] + list ( secondary_nodes ) <EOL> nl . append ( self . _migrater . target_node_uuid ) <EOL> return ( nl , nl + [ instance . primary_node ] ) <EOL> class LUInstanceMigrate ( LogicalUnit ) : <EOL> """<STR_LIT>""" <EOL> HPATH = "<STR_LIT>" <EOL> HTYPE = constants . HTYPE_INSTANCE <EOL> REQ_BGL = False <EOL> def ExpandNames ( self ) : <EOL> self . _ExpandAndLockInstance ( ) <EOL> _ExpandNamesForMigration ( self ) <EOL> self . _migrater = TLMigrateInstance ( self , self . op . instance_uuid , self . op . instance_name , <EOL> self . op . cleanup , False , self . op . allow_failover , False , <EOL> self . op . allow_runtime_changes , <EOL> constants . DEFAULT_SHUTDOWN_TIMEOUT , <EOL> self . op . ignore_ipolicy , self . op . ignore_hvversions ) <EOL> self . tasklets = [ self . _migrater ] <EOL> def DeclareLocks ( self , level ) : <EOL> _DeclareLocksForMigration ( self , level ) <EOL> def BuildHooksEnv ( self ) : <EOL> """<STR_LIT>""" <EOL> instance = self . _migrater . instance <EOL> source_node_uuid = instance . primary_node <EOL> target_node_uuid = self . _migrater . target_node_uuid <EOL> env = BuildInstanceHookEnvByObject ( self , instance ) <EOL> env . update ( { <EOL> "<STR_LIT>" : self . _migrater . live , <EOL> "<STR_LIT>" : self . op . cleanup , <EOL> "<STR_LIT>" : self . cfg . GetNodeName ( source_node_uuid ) , <EOL> "<STR_LIT>" : self . cfg . GetNodeName ( target_node_uuid ) , <EOL> "<STR_LIT>" : self . op . allow_runtime_changes , <EOL> } ) <EOL> disks = self . cfg . GetInstanceDisks ( instance . uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> secondary_nodes = self . cfg . GetInstanceSecondaryNodes ( instance . uuid ) <EOL> env [ "<STR_LIT>" ] = self . cfg . GetNodeName ( secondary_nodes [ <NUM_LIT:0> ] ) <EOL> env [ "<STR_LIT>" ] = self . cfg . GetNodeName ( source_node_uuid ) <EOL> else : <EOL> env [ "<STR_LIT>" ] = env [ "<STR_LIT>" ] = "<STR_LIT>" <EOL> return env <EOL> def BuildHooksNodes ( self ) : <EOL> """<STR_LIT>""" <EOL> instance = self . _migrater . instance <EOL> secondary_nodes = self . cfg . GetInstanceSecondaryNodes ( instance . uuid ) <EOL> snode_uuids = list ( secondary_nodes ) <EOL> nl = [ self . cfg . GetMasterNode ( ) , instance . primary_node ] + snode_uuids <EOL> nl . append ( self . _migrater . target_node_uuid ) <EOL> return ( nl , nl ) <EOL> class TLMigrateInstance ( Tasklet ) : <EOL> """<STR_LIT>""" <EOL> _MIGRATION_POLL_INTERVAL = <NUM_LIT:1> <EOL> _MIGRATION_FEEDBACK_INTERVAL = <NUM_LIT:10> <EOL> def __init__ ( self , lu , instance_uuid , instance_name , cleanup , failover , <EOL> fallback , ignore_consistency , allow_runtime_changes , <EOL> shutdown_timeout , ignore_ipolicy , ignore_hvversions ) : <EOL> """<STR_LIT>""" <EOL> Tasklet . __init__ ( self , lu ) <EOL> self . instance_uuid = instance_uuid <EOL> self . instance_name = instance_name <EOL> self . cleanup = cleanup <EOL> self . live = False <EOL> self . failover = failover <EOL> self . fallback = fallback <EOL> self . ignore_consistency = ignore_consistency <EOL> self . shutdown_timeout = shutdown_timeout <EOL> self . ignore_ipolicy = ignore_ipolicy <EOL> self . allow_runtime_changes = allow_runtime_changes <EOL> self . ignore_hvversions = ignore_hvversions <EOL> def CheckPrereq ( self ) : <EOL> """<STR_LIT>""" <EOL> ( self . instance_uuid , self . instance_name ) = ExpandInstanceUuidAndName ( self . lu . cfg , self . instance_uuid , <EOL> self . instance_name ) <EOL> self . instance = self . cfg . GetInstanceInfo ( self . instance_uuid ) <EOL> assert self . instance is not None <EOL> cluster = self . cfg . GetClusterInfo ( ) <EOL> if ( not self . cleanup and <EOL> not self . instance . admin_state == constants . ADMINST_UP and <EOL> not self . failover and self . fallback ) : <EOL> self . lu . LogInfo ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . failover = True <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> if not utils . AllDiskOfType ( disks , constants . DTS_MIRRORED ) : <EOL> if self . failover : <EOL> text = "<STR_LIT>" <EOL> else : <EOL> text = "<STR_LIT>" <EOL> invalid_disks = set ( d . dev_type for d in disks <EOL> if d . dev_type not in constants . DTS_MIRRORED ) <EOL> raise errors . OpPrereqError ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( utils . CommaJoin ( invalid_disks ) , text ) , <EOL> errors . ECODE_STATE ) <EOL> if utils . AllDiskOfType ( disks , constants . DTS_EXT_MIRROR ) : <EOL> CheckIAllocatorOrNode ( self . lu , "<STR_LIT>" , "<STR_LIT>" ) <EOL> if self . lu . op . iallocator : <EOL> self . _RunAllocator ( ) <EOL> else : <EOL> self . target_node_uuid = self . lu . op . target_node_uuid <EOL> nodeinfo = self . cfg . GetNodeInfo ( self . target_node_uuid ) <EOL> group_info = self . cfg . GetNodeGroup ( nodeinfo . group ) <EOL> ipolicy = ganeti . masterd . instance . CalculateGroupIPolicy ( cluster , <EOL> group_info ) <EOL> CheckTargetNodeIPolicy ( self . lu , ipolicy , self . instance , nodeinfo , <EOL> self . cfg , ignore = self . ignore_ipolicy ) <EOL> target_node_uuid = self . target_node_uuid <EOL> if self . target_node_uuid == self . instance . primary_node : <EOL> raise errors . OpPrereqError ( <EOL> "<STR_LIT>" % <EOL> ( self . instance . name , <EOL> self . cfg . GetNodeName ( self . instance . primary_node ) ) , <EOL> errors . ECODE_STATE ) <EOL> if len ( self . lu . tasklets ) == <NUM_LIT:1> : <EOL> ReleaseLocks ( self . lu , locking . LEVEL_NODE , <EOL> keep = [ self . instance . primary_node , self . target_node_uuid ] ) <EOL> elif utils . AllDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> templates = [ d . dev_type for d in disks ] <EOL> secondary_node_uuids = self . cfg . GetInstanceSecondaryNodes ( self . instance . uuid ) <EOL> if not secondary_node_uuids : <EOL> raise errors . ConfigurationError ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> utils . CommaJoin ( set ( templates ) ) ) <EOL> self . target_node_uuid = target_node_uuid = secondary_node_uuids [ <NUM_LIT:0> ] <EOL> if self . lu . op . iallocator or ( self . lu . op . target_node_uuid and <EOL> self . lu . op . target_node_uuid != target_node_uuid ) : <EOL> if self . failover : <EOL> text = "<STR_LIT>" <EOL> else : <EOL> text = "<STR_LIT>" <EOL> raise errors . OpPrereqError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( utils . CommaJoin ( set ( templates ) ) , text ) , <EOL> errors . ECODE_INVAL ) <EOL> nodeinfo = self . cfg . GetNodeInfo ( target_node_uuid ) <EOL> group_info = self . cfg . GetNodeGroup ( nodeinfo . group ) <EOL> ipolicy = ganeti . masterd . instance . CalculateGroupIPolicy ( cluster , <EOL> group_info ) <EOL> CheckTargetNodeIPolicy ( self . lu , ipolicy , self . instance , nodeinfo , <EOL> self . cfg , ignore = self . ignore_ipolicy ) <EOL> else : <EOL> raise errors . OpPrereqError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> i_be = cluster . FillBE ( self . instance ) <EOL> if ( not self . cleanup and <EOL> ( not self . failover or <EOL> self . instance . admin_state == constants . ADMINST_UP ) ) : <EOL> self . tgt_free_mem = CheckNodeFreeMemory ( <EOL> self . lu , target_node_uuid , <EOL> "<STR_LIT>" % self . instance . name , <EOL> i_be [ constants . BE_MINMEM ] , self . instance . hypervisor , <EOL> self . cfg . GetClusterInfo ( ) . hvparams [ self . instance . hypervisor ] ) <EOL> else : <EOL> self . lu . LogInfo ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> if ( not self . cleanup and not self . failover and <EOL> i_be [ constants . BE_ALWAYS_FAILOVER ] ) : <EOL> self . lu . LogInfo ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . failover = True <EOL> CheckInstanceBridgesExist ( self . lu , self . instance , <EOL> node_uuid = target_node_uuid ) <EOL> if not self . cleanup : <EOL> CheckNodeNotDrained ( self . lu , target_node_uuid ) <EOL> if not self . failover : <EOL> result = self . rpc . call_instance_migratable ( self . instance . primary_node , <EOL> self . instance ) <EOL> if result . fail_msg and self . fallback : <EOL> self . lu . LogInfo ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . failover = True <EOL> else : <EOL> result . Raise ( "<STR_LIT>" , <EOL> prereq = True , ecode = errors . ECODE_STATE ) <EOL> assert not ( self . failover and self . cleanup ) <EOL> if not self . failover : <EOL> if self . lu . op . live is not None and self . lu . op . mode is not None : <EOL> raise errors . OpPrereqError ( "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> errors . ECODE_INVAL ) <EOL> if self . lu . op . live is not None : <EOL> if self . lu . op . live : <EOL> self . lu . op . mode = constants . HT_MIGRATION_LIVE <EOL> else : <EOL> self . lu . op . mode = constants . HT_MIGRATION_NONLIVE <EOL> self . lu . op . live = None <EOL> elif self . lu . op . mode is None : <EOL> i_hv = cluster . FillHV ( self . instance , skip_globals = False ) <EOL> self . lu . op . mode = i_hv [ constants . HV_MIGRATION_MODE ] <EOL> self . live = self . lu . op . mode == constants . HT_MIGRATION_LIVE <EOL> else : <EOL> self . live = False <EOL> if not ( self . failover or self . cleanup ) : <EOL> remote_info = self . rpc . call_instance_info ( <EOL> self . instance . primary_node , self . instance . name , <EOL> self . instance . hypervisor , cluster . hvparams [ self . instance . hypervisor ] ) <EOL> remote_info . Raise ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . instance . primary_node ) , <EOL> prereq = True ) <EOL> instance_running = bool ( remote_info . payload ) <EOL> if instance_running : <EOL> self . current_mem = int ( remote_info . payload [ "<STR_LIT>" ] ) <EOL> def _RunAllocator ( self ) : <EOL> """<STR_LIT>""" <EOL> req = iallocator . IAReqRelocate ( <EOL> inst_uuid = self . instance_uuid , <EOL> relocate_from_node_uuids = [ self . instance . primary_node ] ) <EOL> ial = iallocator . IAllocator ( self . cfg , self . rpc , req ) <EOL> ial . Run ( self . lu . op . iallocator ) <EOL> if not ial . success : <EOL> raise errors . OpPrereqError ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( self . lu . op . iallocator , ial . info ) , <EOL> errors . ECODE_NORES ) <EOL> self . target_node_uuid = self . cfg . GetNodeInfoByName ( ial . result [ <NUM_LIT:0> ] ) . uuid <EOL> self . lu . LogInfo ( "<STR_LIT>" , <EOL> self . instance_name , self . lu . op . iallocator , <EOL> utils . CommaJoin ( ial . result ) ) <EOL> def _WaitUntilSync ( self ) : <EOL> """<STR_LIT>""" <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> all_done = False <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> while not all_done : <EOL> all_done = True <EOL> result = self . rpc . call_drbd_wait_sync ( self . all_node_uuids , <EOL> ( disks , self . instance ) ) <EOL> min_percent = <NUM_LIT:100> <EOL> for node_uuid , nres in result . items ( ) : <EOL> nres . Raise ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( node_uuid ) ) <EOL> node_done , node_percent = nres . payload <EOL> all_done = all_done and node_done <EOL> if node_percent is not None : <EOL> min_percent = min ( min_percent , node_percent ) <EOL> if not all_done : <EOL> if min_percent < <NUM_LIT:100> : <EOL> self . feedback_fn ( "<STR_LIT>" % min_percent ) <EOL> time . sleep ( <NUM_LIT:2> ) <EOL> def _OpenInstanceDisks ( self , node_uuid , exclusive ) : <EOL> """<STR_LIT>""" <EOL> if exclusive : <EOL> mode = "<STR_LIT>" <EOL> else : <EOL> mode = "<STR_LIT>" <EOL> node_name = self . cfg . GetNodeName ( node_uuid ) <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> ( node_name , mode ) ) <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> result = self . rpc . call_blockdev_open ( node_uuid , self . instance . name , <EOL> ( disks , self . instance ) , exclusive ) <EOL> result . Raise ( "<STR_LIT>" % node_name ) <EOL> def _CloseInstanceDisks ( self , node_uuid ) : <EOL> """<STR_LIT>""" <EOL> node_name = self . cfg . GetNodeName ( node_uuid ) <EOL> self . feedback_fn ( "<STR_LIT>" % node_name ) <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> result = self . rpc . call_blockdev_close ( node_uuid , self . instance . name , <EOL> ( disks , self . instance ) ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> if result . offline or self . ignore_consistency : <EOL> self . lu . LogWarning ( "<STR_LIT>" <EOL> "<STR_LIT>" % node_name ) <EOL> else : <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> ( node_name , msg ) ) <EOL> def _GoStandalone ( self ) : <EOL> """<STR_LIT>""" <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> result = self . rpc . call_drbd_disconnect_net ( <EOL> self . all_node_uuids , ( disks , self . instance ) ) <EOL> for node_uuid , nres in result . items ( ) : <EOL> nres . Raise ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( node_uuid ) ) <EOL> def _GoReconnect ( self , multimaster ) : <EOL> """<STR_LIT>""" <EOL> if multimaster : <EOL> msg = "<STR_LIT>" <EOL> else : <EOL> msg = "<STR_LIT>" <EOL> self . feedback_fn ( "<STR_LIT>" % msg ) <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> result = self . rpc . call_drbd_attach_net ( self . all_node_uuids , <EOL> ( disks , self . instance ) , <EOL> multimaster ) <EOL> for node_uuid , nres in result . items ( ) : <EOL> nres . Raise ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( node_uuid ) ) <EOL> def _ExecCleanup ( self ) : <EOL> """<STR_LIT>""" <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> cluster_hvparams = self . cfg . GetClusterInfo ( ) . hvparams <EOL> ins_l = self . rpc . call_instance_list ( self . all_node_uuids , <EOL> [ self . instance . hypervisor ] , <EOL> cluster_hvparams ) <EOL> for node_uuid , result in ins_l . items ( ) : <EOL> result . Raise ( "<STR_LIT>" % node_uuid ) <EOL> runningon_source = self . instance . name in ins_l [ self . source_node_uuid ] . payload <EOL> runningon_target = self . instance . name in ins_l [ self . target_node_uuid ] . payload <EOL> if runningon_source and runningon_target : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> if not ( runningon_source or runningon_target ) : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> if runningon_target : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> self . cfg . SetInstancePrimaryNode ( self . instance . uuid , <EOL> self . target_node_uuid ) <EOL> demoted_node_uuid = self . source_node_uuid <EOL> else : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . source_node_uuid ) ) <EOL> demoted_node_uuid = self . target_node_uuid <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> self . _CloseInstanceDisks ( demoted_node_uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> try : <EOL> self . _WaitUntilSync ( ) <EOL> except errors . OpExecError : <EOL> pass <EOL> self . _GoStandalone ( ) <EOL> self . _GoReconnect ( False ) <EOL> self . _WaitUntilSync ( ) <EOL> elif utils . AnyDiskOfType ( disks , constants . DTS_EXT_MIRROR ) : <EOL> self . _OpenInstanceDisks ( self . instance . primary_node , True ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> def _RevertDiskStatus ( self ) : <EOL> """<STR_LIT>""" <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> self . _CloseInstanceDisks ( self . target_node_uuid ) <EOL> if utils . AllDiskOfType ( disks , constants . DTS_EXT_MIRROR ) : <EOL> self . _OpenInstanceDisks ( self . source_node_uuid , True ) <EOL> return <EOL> try : <EOL> self . _GoStandalone ( ) <EOL> self . _GoReconnect ( False ) <EOL> self . _WaitUntilSync ( ) <EOL> except errors . OpExecError , err : <EOL> self . lu . LogWarning ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % str ( err ) ) <EOL> def _AbortMigration ( self ) : <EOL> """<STR_LIT>""" <EOL> abort_result = self . rpc . call_instance_finalize_migration_dst ( <EOL> self . target_node_uuid , self . instance , self . migration_info , <EOL> False ) <EOL> abort_msg = abort_result . fail_msg <EOL> if abort_msg : <EOL> logging . error ( "<STR_LIT>" , <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) , abort_msg ) <EOL> abort_result = self . rpc . call_instance_finalize_migration_src ( <EOL> self . source_node_uuid , self . instance , False , self . live ) <EOL> abort_msg = abort_result . fail_msg <EOL> if abort_msg : <EOL> logging . error ( "<STR_LIT>" , <EOL> self . cfg . GetNodeName ( self . source_node_uuid ) , abort_msg ) <EOL> def _ExecMigration ( self ) : <EOL> """<STR_LIT>""" <EOL> hvspecs = [ ( self . instance . hypervisor , <EOL> self . cfg . GetClusterInfo ( ) . hvparams [ self . instance . hypervisor ] ) ] <EOL> nodeinfo = self . rpc . call_node_info ( <EOL> [ self . source_node_uuid , self . target_node_uuid ] , None , hvspecs ) <EOL> for ninfo in nodeinfo . values ( ) : <EOL> ninfo . Raise ( "<STR_LIT>" % <EOL> ninfo . node ) <EOL> ( _ , _ , ( src_info , ) ) = nodeinfo [ self . source_node_uuid ] . payload <EOL> ( _ , _ , ( dst_info , ) ) = nodeinfo [ self . target_node_uuid ] . payload <EOL> if ( ( constants . HV_NODEINFO_KEY_VERSION in src_info ) and <EOL> ( constants . HV_NODEINFO_KEY_VERSION in dst_info ) ) : <EOL> src_version = src_info [ constants . HV_NODEINFO_KEY_VERSION ] <EOL> dst_version = dst_info [ constants . HV_NODEINFO_KEY_VERSION ] <EOL> if src_version != dst_version : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( src_version , dst_version ) ) <EOL> hv = hypervisor . GetHypervisor ( self . instance . hypervisor ) <EOL> if hv . VersionsSafeForMigration ( src_version , dst_version ) : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( src_version , dst_version ) ) <EOL> else : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( src_version , dst_version ) ) <EOL> if self . ignore_hvversions : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> else : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( src_version , dst_version ) ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> for ( idx , dev ) in enumerate ( self . cfg . GetInstanceDisks ( self . instance . uuid ) ) : <EOL> if not CheckDiskConsistency ( self . lu , self . instance , dev , <EOL> self . target_node_uuid , <EOL> False ) : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % idx ) <EOL> if self . current_mem > self . tgt_free_mem : <EOL> if not self . allow_runtime_changes : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( self . instance . name , <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) , <EOL> self . tgt_free_mem , self . current_mem ) ) <EOL> self . feedback_fn ( "<STR_LIT>" % self . tgt_free_mem ) <EOL> rpcres = self . rpc . call_instance_balloon_memory ( self . instance . primary_node , <EOL> self . instance , <EOL> self . tgt_free_mem ) <EOL> rpcres . Raise ( "<STR_LIT>" ) <EOL> result = self . rpc . call_migration_info ( self . source_node_uuid , self . instance ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> log_err = ( "<STR_LIT>" % <EOL> ( self . cfg . GetNodeName ( self . source_node_uuid ) , msg ) ) <EOL> logging . error ( log_err ) <EOL> raise errors . OpExecError ( log_err ) <EOL> self . migration_info = migration_info = result . payload <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> self . _CloseInstanceDisks ( self . target_node_uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> self . _GoStandalone ( ) <EOL> self . _GoReconnect ( True ) <EOL> self . _WaitUntilSync ( ) <EOL> self . _OpenInstanceDisks ( self . source_node_uuid , False ) <EOL> self . _OpenInstanceDisks ( self . target_node_uuid , False ) <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> result = self . rpc . call_accept_instance ( self . target_node_uuid , <EOL> self . instance , <EOL> migration_info , <EOL> self . nodes_ip [ self . target_node_uuid ] ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , msg ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> self . _AbortMigration ( ) <EOL> self . _RevertDiskStatus ( ) <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> ( self . instance . name , msg ) ) <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> cluster = self . cfg . GetClusterInfo ( ) <EOL> result = self . rpc . call_instance_migrate ( <EOL> self . source_node_uuid , cluster . cluster_name , self . instance , <EOL> self . nodes_ip [ self . target_node_uuid ] , self . live ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , msg ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> self . _AbortMigration ( ) <EOL> self . _RevertDiskStatus ( ) <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> ( self . instance . name , msg ) ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> last_feedback = time . time ( ) <EOL> while True : <EOL> result = self . rpc . call_instance_get_migration_status ( <EOL> self . source_node_uuid , self . instance ) <EOL> msg = result . fail_msg <EOL> ms = result . payload <EOL> if msg or ( ms . status in constants . HV_MIGRATION_FAILED_STATUSES ) : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , msg ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> self . _AbortMigration ( ) <EOL> self . _RevertDiskStatus ( ) <EOL> if not msg : <EOL> msg = "<STR_LIT>" <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> ( self . instance . name , msg ) ) <EOL> if result . payload . status != constants . HV_MIGRATION_ACTIVE : <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> break <EOL> if ( utils . TimeoutExpired ( last_feedback , <EOL> self . _MIGRATION_FEEDBACK_INTERVAL ) and <EOL> ms . transferred_ram is not None ) : <EOL> mem_progress = <NUM_LIT:100> * float ( ms . transferred_ram ) / float ( ms . total_ram ) <EOL> self . feedback_fn ( "<STR_LIT>" % mem_progress ) <EOL> last_feedback = time . time ( ) <EOL> time . sleep ( self . _MIGRATION_POLL_INTERVAL ) <EOL> result = self . rpc . call_instance_finalize_migration_src ( <EOL> self . source_node_uuid , self . instance , True , self . live ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , msg ) <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> msg ) <EOL> self . cfg . SetInstancePrimaryNode ( self . instance . uuid , self . target_node_uuid ) <EOL> self . instance = self . cfg . GetInstanceInfo ( self . instance_uuid ) <EOL> disks = self . cfg . GetInstanceDisks ( self . instance_uuid ) <EOL> result = self . rpc . call_instance_finalize_migration_dst ( <EOL> self . target_node_uuid , self . instance , migration_info , True ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , msg ) <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> msg ) <EOL> self . _CloseInstanceDisks ( self . source_node_uuid ) <EOL> if utils . AnyDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> self . _WaitUntilSync ( ) <EOL> self . _GoStandalone ( ) <EOL> self . _GoReconnect ( False ) <EOL> self . _WaitUntilSync ( ) <EOL> elif utils . AnyDiskOfType ( disks , constants . DTS_EXT_MIRROR ) : <EOL> self . _OpenInstanceDisks ( self . target_node_uuid , True ) <EOL> unmap_types = ( constants . DT_RBD , constants . DT_EXT ) <EOL> if utils . AnyDiskOfType ( disks , unmap_types ) : <EOL> unmap_disks = [ d for d in disks if d . dev_type in unmap_types ] <EOL> disks = ExpandCheckDisks ( unmap_disks , unmap_disks ) <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> ( utils . CommaJoin ( d . name for d in unmap_disks ) , <EOL> self . cfg . GetNodeName ( self . source_node_uuid ) ) ) <EOL> for disk in disks : <EOL> result = self . rpc . call_blockdev_shutdown ( self . source_node_uuid , <EOL> ( disk , self . instance ) ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> logging . error ( "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> disk . iv_name , <EOL> self . cfg . GetNodeName ( self . source_node_uuid ) , msg ) <EOL> logging . error ( "<STR_LIT>" , <EOL> disk . iv_name , <EOL> self . cfg . GetNodeName ( self . source_node_uuid ) ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> def _ExecFailover ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . instance . forthcoming : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . cfg . SetInstancePrimaryNode ( self . instance . uuid , <EOL> self . target_node_uuid ) <EOL> return <EOL> primary_node = self . cfg . GetNodeInfo ( self . instance . primary_node ) <EOL> source_node_uuid = self . instance . primary_node <EOL> if self . instance . disks_active : <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> inst_disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> for ( idx , dev ) in enumerate ( inst_disks ) : <EOL> if not CheckDiskConsistency ( self . lu , self . instance , dev , <EOL> self . target_node_uuid , False ) : <EOL> if primary_node . offline : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( primary_node . name , idx , <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) ) <EOL> elif not self . ignore_consistency : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" % idx ) <EOL> else : <EOL> self . feedback_fn ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> logging . info ( "<STR_LIT>" , <EOL> self . instance . name , self . cfg . GetNodeName ( source_node_uuid ) ) <EOL> result = self . rpc . call_instance_shutdown ( source_node_uuid , self . instance , <EOL> self . shutdown_timeout , <EOL> self . lu . op . reason ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> if self . ignore_consistency or primary_node . offline : <EOL> self . lu . LogWarning ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> self . instance . name , <EOL> self . cfg . GetNodeName ( source_node_uuid ) , <EOL> self . cfg . GetNodeName ( source_node_uuid ) , msg ) <EOL> else : <EOL> raise errors . OpExecError ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( self . instance . name , <EOL> self . cfg . GetNodeName ( source_node_uuid ) , msg ) ) <EOL> disk_template = self . cfg . GetInstanceDiskTemplate ( self . instance . uuid ) <EOL> if disk_template in constants . DTS_EXT_MIRROR : <EOL> self . _CloseInstanceDisks ( source_node_uuid ) <EOL> self . feedback_fn ( "<STR_LIT>" ) <EOL> if not ShutdownInstanceDisks ( self . lu , self . instance , ignore_primary = True ) : <EOL> raise errors . OpExecError ( "<STR_LIT>" ) <EOL> self . cfg . SetInstancePrimaryNode ( self . instance . uuid , self . target_node_uuid ) <EOL> self . instance = self . cfg . GetInstanceInfo ( self . instance_uuid ) <EOL> if self . instance . admin_state == constants . ADMINST_UP : <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> logging . info ( "<STR_LIT>" , self . instance . name , <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> disks_ok , _ , _ = AssembleInstanceDisks ( self . lu , self . instance , <EOL> ignore_secondaries = True ) <EOL> if not disks_ok : <EOL> ShutdownInstanceDisks ( self . lu , self . instance ) <EOL> raise errors . OpExecError ( "<STR_LIT>" ) <EOL> self . feedback_fn ( "<STR_LIT>" % <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) ) <EOL> result = self . rpc . call_instance_start ( self . target_node_uuid , <EOL> ( self . instance , None , None ) , False , <EOL> self . lu . op . reason ) <EOL> msg = result . fail_msg <EOL> if msg : <EOL> ShutdownInstanceDisks ( self . lu , self . instance ) <EOL> raise errors . OpExecError ( "<STR_LIT>" % <EOL> ( self . instance . name , <EOL> self . cfg . GetNodeName ( self . target_node_uuid ) , <EOL> msg ) ) <EOL> def Exec ( self , feedback_fn ) : <EOL> """<STR_LIT>""" <EOL> self . feedback_fn = feedback_fn <EOL> self . source_node_uuid = self . instance . primary_node <EOL> disks = self . cfg . GetInstanceDisks ( self . instance . uuid ) <EOL> if utils . AllDiskOfType ( disks , constants . DTS_INT_MIRROR ) : <EOL> secondary_nodes = self . cfg . GetInstanceSecondaryNodes ( self . instance . uuid ) <EOL> self . target_node_uuid = secondary_nodes [ <NUM_LIT:0> ] <EOL> self . all_node_uuids = [ self . source_node_uuid , self . target_node_uuid ] <EOL> self . nodes_ip = dict ( ( uuid , node . secondary_ip ) for ( uuid , node ) <EOL> in self . cfg . GetMultiNodeInfo ( self . all_node_uuids ) ) <EOL> if self . failover : <EOL> feedback_fn ( "<STR_LIT>" % self . instance . name ) <EOL> self . _ExecFailover ( ) <EOL> else : <EOL> feedback_fn ( "<STR_LIT>" % self . instance . name ) <EOL> if self . cleanup : <EOL> return self . _ExecCleanup ( ) <EOL> else : <EOL> return self . _ExecMigration ( ) </s>
