Revision 31b836b8 lib/cmdlib/common.py

b/lib/cmdlib/common.py
37 37
from ganeti import utils
38 38

  
39 39

  
40
# States of instance
41
INSTANCE_DOWN = [constants.ADMINST_DOWN]
42
INSTANCE_ONLINE = [constants.ADMINST_DOWN, constants.ADMINST_UP]
43
INSTANCE_NOT_RUNNING = [constants.ADMINST_DOWN, constants.ADMINST_OFFLINE]
44

  
45
#: Instance status in which an instance can be marked as offline/online
46
CAN_CHANGE_INSTANCE_OFFLINE = (frozenset(INSTANCE_DOWN) | frozenset([
47
  constants.ADMINST_OFFLINE,
48
  ]))
49

  
50

  
40 51
def _ExpandItemName(fn, name, kind):
41 52
  """Expand an item name.
42 53

  
......
873 884
              for inst in instances
874 885
              for (node, vols) in inst.MapLVsByNode().items()
875 886
              for vol in vols)
887

  
888

  
889
def _CheckParamsNotGlobal(params, glob_pars, kind, bad_levels, good_levels):
890
  """Make sure that none of the given paramters is global.
891

  
892
  If a global parameter is found, an L{errors.OpPrereqError} exception is
893
  raised. This is used to avoid setting global parameters for individual nodes.
894

  
895
  @type params: dictionary
896
  @param params: Parameters to check
897
  @type glob_pars: dictionary
898
  @param glob_pars: Forbidden parameters
899
  @type kind: string
900
  @param kind: Kind of parameters (e.g. "node")
901
  @type bad_levels: string
902
  @param bad_levels: Level(s) at which the parameters are forbidden (e.g.
903
      "instance")
904
  @type good_levels: strings
905
  @param good_levels: Level(s) at which the parameters are allowed (e.g.
906
      "cluster or group")
907

  
908
  """
909
  used_globals = glob_pars.intersection(params)
910
  if used_globals:
911
    msg = ("The following %s parameters are global and cannot"
912
           " be customized at %s level, please modify them at"
913
           " %s level: %s" %
914
           (kind, bad_levels, good_levels, utils.CommaJoin(used_globals)))
915
    raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
916

  
917

  
918
def _IsExclusiveStorageEnabledNode(cfg, node):
919
  """Whether exclusive_storage is in effect for the given node.
920

  
921
  @type cfg: L{config.ConfigWriter}
922
  @param cfg: The cluster configuration
923
  @type node: L{objects.Node}
924
  @param node: The node
925
  @rtype: bool
926
  @return: The effective value of exclusive_storage
927

  
928
  """
929
  return cfg.GetNdParams(node)[constants.ND_EXCLUSIVE_STORAGE]
930

  
931

  
932
def _CheckInstanceState(lu, instance, req_states, msg=None):
933
  """Ensure that an instance is in one of the required states.
934

  
935
  @param lu: the LU on behalf of which we make the check
936
  @param instance: the instance to check
937
  @param msg: if passed, should be a message to replace the default one
938
  @raise errors.OpPrereqError: if the instance is not in the required state
939

  
940
  """
941
  if msg is None:
942
    msg = ("can't use instance from outside %s states" %
943
           utils.CommaJoin(req_states))
944
  if instance.admin_state not in req_states:
945
    raise errors.OpPrereqError("Instance '%s' is marked to be %s, %s" %
946
                               (instance.name, instance.admin_state, msg),
947
                               errors.ECODE_STATE)
948

  
949
  if constants.ADMINST_UP not in req_states:
950
    pnode = instance.primary_node
951
    if not lu.cfg.GetNodeInfo(pnode).offline:
952
      ins_l = lu.rpc.call_instance_list([pnode], [instance.hypervisor])[pnode]
953
      ins_l.Raise("Can't contact node %s for instance information" % pnode,
954
                  prereq=True, ecode=errors.ECODE_ENVIRON)
955
      if instance.name in ins_l.payload:
956
        raise errors.OpPrereqError("Instance %s is running, %s" %
957
                                   (instance.name, msg), errors.ECODE_STATE)
958
    else:
959
      lu.LogWarning("Primary node offline, ignoring check that instance"
960
                     " is down")
961

  
962

  
963
def _CheckIAllocatorOrNode(lu, iallocator_slot, node_slot):
964
  """Check the sanity of iallocator and node arguments and use the
965
  cluster-wide iallocator if appropriate.
966

  
967
  Check that at most one of (iallocator, node) is specified. If none is
968
  specified, or the iallocator is L{constants.DEFAULT_IALLOCATOR_SHORTCUT},
969
  then the LU's opcode's iallocator slot is filled with the cluster-wide
970
  default iallocator.
971

  
972
  @type iallocator_slot: string
973
  @param iallocator_slot: the name of the opcode iallocator slot
974
  @type node_slot: string
975
  @param node_slot: the name of the opcode target node slot
976

  
977
  """
978
  node = getattr(lu.op, node_slot, None)
979
  ialloc = getattr(lu.op, iallocator_slot, None)
980
  if node == []:
981
    node = None
982

  
983
  if node is not None and ialloc is not None:
984
    raise errors.OpPrereqError("Do not specify both, iallocator and node",
985
                               errors.ECODE_INVAL)
986
  elif ((node is None and ialloc is None) or
987
        ialloc == constants.DEFAULT_IALLOCATOR_SHORTCUT):
988
    default_iallocator = lu.cfg.GetDefaultIAllocator()
989
    if default_iallocator:
990
      setattr(lu.op, iallocator_slot, default_iallocator)
991
    else:
992
      raise errors.OpPrereqError("No iallocator or node given and no"
993
                                 " cluster-wide default iallocator found;"
994
                                 " please specify either an iallocator or a"
995
                                 " node, or set a cluster-wide default"
996
                                 " iallocator", errors.ECODE_INVAL)
997

  
998

  
999
def _FindFaultyInstanceDisks(cfg, rpc_runner, instance, node_name, prereq):
1000
  faulty = []
1001

  
1002
  for dev in instance.disks:
1003
    cfg.SetDiskID(dev, node_name)
1004

  
1005
  result = rpc_runner.call_blockdev_getmirrorstatus(node_name, (instance.disks,
1006
                                                                instance))
1007
  result.Raise("Failed to get disk status from node %s" % node_name,
1008
               prereq=prereq, ecode=errors.ECODE_ENVIRON)
1009

  
1010
  for idx, bdev_status in enumerate(result.payload):
1011
    if bdev_status and bdev_status.ldisk_status == constants.LDS_FAULTY:
1012
      faulty.append(idx)
1013

  
1014
  return faulty

Also available in: Unified diff