Revision e71b9ef4

b/lib/cli.py
87 87
  "MAINTAIN_NODE_HEALTH_OPT",
88 88
  "MASTER_NETDEV_OPT",
89 89
  "MC_OPT",
90
  "MIGRATION_TYPE_OPT",
90 91
  "NET_OPT",
91 92
  "NEW_CLUSTER_CERT_OPT",
92 93
  "NEW_CLUSTER_DOMAIN_SECRET_OPT",
......
698 699
                         " freeze the instance, save the state, transfer and"
699 700
                         " only then resume running on the secondary node)")
700 701

  
702
MIGRATION_TYPE_OPT = cli_option("--migration-type", dest="migration_type",
703
                                default=None,
704
                                choices=list(constants.HT_MIGRATION_TYPES),
705
                                help="Override default migration type (choose"
706
                                " either live or non-live")
707

  
701 708
NODE_PLACEMENT_OPT = cli_option("-n", "--node", dest="node",
702 709
                                help="Target node and optional secondary node",
703 710
                                metavar="<pnode>[:<snode>]",
b/lib/cmdlib.py
232 232
#: a required node name (for single-node LUs)
233 233
_PNodeName = ("node_name", _NoDefault, _TNonEmptyString)
234 234

  
235
#: the migration type (live/non-live)
236
_PMigrationLive = ("live", None, _TOr(_TNone,
237
                                      _TElemOf(constants.HT_MIGRATION_TYPES)))
238

  
235 239

  
236 240
# End types
237 241
class LogicalUnit(object):
......
5486 5490
  HTYPE = constants.HTYPE_INSTANCE
5487 5491
  _OP_PARAMS = [
5488 5492
    _PInstanceName,
5489
    ("live", True, _TBool),
5493
    _PMigrationLive,
5490 5494
    ("cleanup", False, _TBool),
5491 5495
    ]
5492 5496

  
......
5499 5503
    self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_REPLACE
5500 5504

  
5501 5505
    self._migrater = TLMigrateInstance(self, self.op.instance_name,
5502
                                       self.op.live, self.op.cleanup)
5506
                                       self.op.cleanup)
5503 5507
    self.tasklets = [self._migrater]
5504 5508

  
5505 5509
  def DeclareLocks(self, level):
......
5717 5721
  HTYPE = constants.HTYPE_NODE
5718 5722
  _OP_PARAMS = [
5719 5723
    _PNodeName,
5720
    ("live", False, _TBool),
5724
    _PMigrationLive,
5721 5725
    ]
5722 5726
  REQ_BGL = False
5723 5727

  
......
5738 5742
      logging.debug("Migrating instance %s", inst.name)
5739 5743
      names.append(inst.name)
5740 5744

  
5741
      tasklets.append(TLMigrateInstance(self, inst.name, self.op.live, False))
5745
      tasklets.append(TLMigrateInstance(self, inst.name, False))
5742 5746

  
5743 5747
    self.tasklets = tasklets
5744 5748

  
......
5765 5769

  
5766 5770

  
5767 5771
class TLMigrateInstance(Tasklet):
5768
  def __init__(self, lu, instance_name, live, cleanup):
5772
  def __init__(self, lu, instance_name, cleanup):
5769 5773
    """Initializes this class.
5770 5774

  
5771 5775
    """
......
5773 5777

  
5774 5778
    # Parameters
5775 5779
    self.instance_name = instance_name
5776
    self.live = live
5777 5780
    self.cleanup = cleanup
5781
    self.live = False # will be overridden later
5778 5782

  
5779 5783
  def CheckPrereq(self):
5780 5784
    """Check prerequisites.
......
5815 5819

  
5816 5820
    self.instance = instance
5817 5821

  
5822
    if self.lu.op.live is None:
5823
      # read the default value from the hypervisor
5824
      i_hv = self.cfg.GetClusterInfo().FillHV(instance, skip_globals=False)
5825
      self.lu.op.live = i_hv[constants.HV_MIGRATION_TYPE]
5826

  
5827
    self.live = self.lu.op.live == constants.HT_MIGRATION_LIVE
5828

  
5818 5829
  def _WaitUntilSync(self):
5819 5830
    """Poll with custom rpc for disk sync.
5820 5831

  
b/lib/constants.py
537 537
HV_MIGRATION_PORT = "migration_port"
538 538
HV_MIGRATION_BANDWIDTH = "migration_bandwidth"
539 539
HV_MIGRATION_DOWNTIME = "migration_downtime"
540
HV_MIGRATION_TYPE = "migration_type"
540 541
HV_USE_LOCALTIME = "use_localtime"
541 542
HV_DISK_CACHE = "disk_cache"
542 543
HV_SECURITY_MODEL = "security_model"
......
571 572
  HV_MIGRATION_PORT: VTYPE_INT,
572 573
  HV_MIGRATION_BANDWIDTH: VTYPE_INT,
573 574
  HV_MIGRATION_DOWNTIME: VTYPE_INT,
575
  HV_MIGRATION_TYPE: VTYPE_STRING,
574 576
  HV_USE_LOCALTIME: VTYPE_BOOL,
575 577
  HV_DISK_CACHE: VTYPE_STRING,
576 578
  HV_SECURITY_MODEL: VTYPE_STRING,
......
717 719

  
718 720
HT_KVM_FLAG_VALUES = frozenset([HT_KVM_ENABLED, HT_KVM_DISABLED])
719 721

  
722
# Migration type
723
HT_MIGRATION_LIVE = "live"
724
HT_MIGRATION_NONLIVE = "non-live"
725
HT_MIGRATION_TYPES = frozenset([HT_MIGRATION_LIVE, HT_MIGRATION_NONLIVE])
726

  
720 727
# Cluster Verify steps
721 728
VERIFY_NPLUSONE_MEM = 'nplusone_mem'
722 729
VERIFY_OPTIONAL_CHECKS = frozenset([VERIFY_NPLUSONE_MEM])
......
859 866
    HV_ROOT_PATH: '/dev/sda1',
860 867
    HV_KERNEL_ARGS: 'ro',
861 868
    HV_MIGRATION_PORT: 8002,
869
    HV_MIGRATION_TYPE: HT_MIGRATION_LIVE,
862 870
    },
863 871
  HT_XEN_HVM: {
864 872
    HV_BOOT_ORDER: "cd",
......
872 880
    HV_KERNEL_PATH: "/usr/lib/xen/boot/hvmloader",
873 881
    HV_DEVICE_MODEL: "/usr/lib/xen/bin/qemu-dm",
874 882
    HV_MIGRATION_PORT: 8002,
883
    HV_MIGRATION_TYPE: HT_MIGRATION_NONLIVE,
875 884
    HV_USE_LOCALTIME: False,
876 885
    },
877 886
  HT_KVM: {
......
894 903
    HV_MIGRATION_PORT: 8102,
895 904
    HV_MIGRATION_BANDWIDTH: 32, # MiB/s
896 905
    HV_MIGRATION_DOWNTIME: 30,  # ms
906
    HV_MIGRATION_TYPE: HT_MIGRATION_LIVE,
897 907
    HV_USE_LOCALTIME: False,
898 908
    HV_DISK_CACHE: HT_CACHE_DEFAULT,
899 909
    HV_SECURITY_MODEL: HT_SM_NONE,
......
914 924
HVC_GLOBALS = frozenset([
915 925
  HV_MIGRATION_PORT,
916 926
  HV_MIGRATION_BANDWIDTH,
927
  HV_MIGRATION_TYPE,
917 928
  ])
918 929

  
919 930
BEC_DEFAULTS = {
b/lib/hypervisor/hv_base.py
44 44

  
45 45
from ganeti import errors
46 46
from ganeti import utils
47
from ganeti import constants
47 48

  
48 49

  
49 50
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
......
71 72
# required, but no other checks
72 73
REQUIRED_CHECK = (True, None, None, None, None)
73 74

  
75
# migration type
76
MIGRATION_TYPE_CHECK = (True, lambda x: x in constants.HT_MIGRATION_TYPES,
77
                        "invalid migration type", None, None)
78

  
74 79

  
75 80
def ParamInSet(required, my_set):
76 81
  """Builds parameter checker for set membership.
b/lib/hypervisor/hv_kvm.py
194 194
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
195 195
    constants.HV_MIGRATION_BANDWIDTH: hv_base.NO_CHECK,
196 196
    constants.HV_MIGRATION_DOWNTIME: hv_base.NO_CHECK,
197
    constants.HV_MIGRATION_TYPE: hv_base.MIGRATION_TYPE_CHECK,
197 198
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
198 199
    constants.HV_DISK_CACHE:
199 200
      hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
b/lib/hypervisor/hv_xen.py
458 458
    constants.HV_ROOT_PATH: hv_base.REQUIRED_CHECK,
459 459
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
460 460
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
461
    constants.HV_MIGRATION_TYPE: hv_base.MIGRATION_TYPE_CHECK,
461 462
    }
462 463

  
463 464
  @classmethod
......
556 557
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
557 558
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
558 559
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
560
    constants.HV_MIGRATION_TYPE: hv_base.MIGRATION_TYPE_CHECK,
559 561
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
560 562
    }
561 563

  
b/man/gnt-instance.sgml
2389 2389
          <command>migrate</command>
2390 2390
          <arg>-f</arg>
2391 2391
          <arg>--non-live</arg>
2392
          <arg>--migration-type=live|non-live</arg>
2392 2393
          <arg choice="req"><replaceable>instance</replaceable></arg>
2393 2394
        </cmdsynopsis>
2394 2395

  
......
2405 2406
        </para>
2406 2407

  
2407 2408
        <para>
2408
          The <option>--non-live</option> option will switch (for the
2409
          hypervisors that support it) between a "fully live"
2410
          (i.e. the interruption is as minimal as possible) migration
2411
          and one in which the instance is frozen, its state saved and
2412
          transported to the remote node, and then resumed there. This
2413
          all depends on the hypervisor support for two different
2414
          methods. In any case, it is not an error to pass this
2415
          parameter (it will just be ignored if the hypervisor doesn't
2416
          support it).
2409
          The <option>--non-live</option>
2410
          and <option>--migration-type=non-live</option> options will
2411
          switch (for the hypervisors that support it) between a
2412
          "fully live" (i.e. the interruption is as minimal as
2413
          possible) migration and one in which the instance is frozen,
2414
          its state saved and transported to the remote node, and then
2415
          resumed there. This all depends on the hypervisor support
2416
          for two different methods. In any case, it is not an error
2417
          to pass this parameter (it will just be ignored if the
2418
          hypervisor doesn't support it). The
2419
          option <option>--migration-type=live</option> option will
2420
          request a fully-live migration. The default, when neither
2421
          option is passed, depends on the hypervisor parameters (and
2422
          can be viewed with the <command>gnt-cluster info</command>
2423
          command).
2417 2424
        </para>
2418 2425

  
2419 2426
        <para>
b/man/gnt-node.sgml
571 571
        <command>migrate</command>
572 572
        <arg>-f</arg>
573 573
        <arg>--non-live</arg>
574
        <arg>--migration-type=live|non-live</arg>
574 575
        <arg choice="req"><replaceable>node</replaceable></arg>
575 576
      </cmdsynopsis>
576 577

  
......
582 583

  
583 584
      <para>
584 585
        As for the <command>gnt-instance migrate</command> command,
585
        the <option>--no-live</option> option can be given to do a
586
        non-live migration.
586
        the options <option>--no-live</option>
587
        and <option>--migration-type</option> can be given to
588
        influence the migration type.
587 589
      </para>
588 590

  
589 591
      <para>
b/scripts/gnt-instance
897 897
    if not AskUser(usertext):
898 898
      return 1
899 899

  
900
  op = opcodes.OpMigrateInstance(instance_name=instance_name, live=opts.live,
900
  # this should be removed once --non-live is deprecated
901
  if not opts.live and opts.migration_type is not None:
902
    raise errors.OpPrereqError("Only one of the --non-live and "
903
                               "--migration-type options can be passed",
904
                               errors.ECODE_INVAL)
905
  if not opts.live: # --non-live passed
906
    live = constants.HT_MIGRATION_NONLIVE
907
  else:
908
    live = opts.migration_type
909

  
910
  op = opcodes.OpMigrateInstance(instance_name=instance_name, live=live,
901 911
                                 cleanup=opts.cleanup)
902 912
  SubmitOpCode(op, cl=cl, opts=opts)
903 913
  return 0
......
1409 1419
    " using the remote mirror (only for instances of type drbd)"),
1410 1420
  'migrate': (
1411 1421
    MigrateInstance, ARGS_ONE_INSTANCE,
1412
    [FORCE_OPT, NONLIVE_OPT, CLEANUP_OPT],
1422
    [FORCE_OPT, NONLIVE_OPT, MIGRATION_TYPE_OPT, CLEANUP_OPT],
1413 1423
    "[-f] <instance>", "Migrate instance to its secondary node"
1414 1424
    " (only for instances of type drbd)"),
1415 1425
  'move': (
b/scripts/gnt-node
360 360
                               (",".join("'%s'" % name for name in pinst))):
361 361
    return 2
362 362

  
363
  op = opcodes.OpMigrateNode(node_name=args[0], live=opts.live)
363
  # this should be removed once --non-live is deprecated
364
  if not opts.live and opts.migration_type is not None:
365
    raise errors.OpPrereqError("Only one of the --non-live and "
366
                               "--migration-type options can be passed",
367
                               errors.ECODE_INVAL)
368
  if not opts.live: # --non-live passed
369
    live = constants.HT_MIGRATION_NONLIVE
370
  else:
371
    live = opts.migration_type
372
  op = opcodes.OpMigrateNode(node_name=args[0], live=live)
364 373
  SubmitOpCode(op, cl=cl, opts=opts)
365 374

  
366 375

  
......
652 661
    "Stops the primary instances on a node and start them on their"
653 662
    " secondary node (only for instances with drbd disk template)"),
654 663
  'migrate': (
655
    MigrateNode, ARGS_ONE_NODE, [FORCE_OPT, NONLIVE_OPT],
664
    MigrateNode, ARGS_ONE_NODE, [FORCE_OPT, NONLIVE_OPT, MIGRATION_TYPE_OPT],
656 665
    "[-f] <node>",
657 666
    "Migrate all the primary instance on a node away from it"
658 667
    " (only for instances of type drbd)"),

Also available in: Unified diff