Revision 21e77d7f lib/cmdlib.py

b/lib/cmdlib.py
66 66

  
67 67
import ganeti.masterd.instance # pylint: disable=W0611
68 68

  
69

  
70 69
# States of instance
71 70
INSTANCE_DOWN = [constants.ADMINST_DOWN]
72 71
INSTANCE_ONLINE = [constants.ADMINST_DOWN, constants.ADMINST_UP]
......
6765 6764

  
6766 6765

  
6767 6766
def _AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False,
6768
                           ignore_size=False):
6767
                           ignore_size=False, check=True):
6769 6768
  """Prepare the block devices for an instance.
6770 6769

  
6771 6770
  This sets up the block devices on all nodes.
......
6791 6790
  device_info = []
6792 6791
  disks_ok = True
6793 6792
  iname = instance.name
6794
  disks = _ExpandCheckDisks(instance, disks)
6793
  if check:
6794
    disks = _ExpandCheckDisks(instance, disks)
6795 6795

  
6796 6796
  # With the two passes mechanism we try to reduce the window of
6797 6797
  # opportunity for the race condition of switching DRBD to primary
......
9282 9282
  return results
9283 9283

  
9284 9284

  
9285
def _GetDeviceUniqueIdx(lu, dev_type):
9286
  """Get unique idx for a device
9287

  
9288
  """
9289

  
9290
  if lu.op.OP_ID == "OP_INSTANCE_CREATE":
9291
    base = lu
9292
  elif lu.op.OP_ID == "OP_INSTANCE_SET_PARAMS":
9293
    base = lu.instance
9294

  
9295
  idx = base.dev_idxs[dev_type]
9296
  base.dev_idxs[dev_type] += 1
9297

  
9298
  if lu.op.OP_ID == "OP_INSTANCE_SET_PARAMS":
9299
    lu.cfg.UpdateDeviceUniqueIdx(lu.instance, dev_type)
9300

  
9301
  return idx
9302

  
9303

  
9304
def _DeviceHotplugable(dev):
9305

  
9306
  return dev.idx is not None
9307

  
9308

  
9285 9309
def _GenerateDRBD8Branch(lu, primary, secondary, size, vgnames, names,
9286 9310
                         iv_name, p_minor, s_minor):
9287 9311
  """Generate a drbd8 device complete with its children.
......
9298 9322
                          size=constants.DRBD_META_SIZE,
9299 9323
                          logical_id=(vgnames[1], names[1]),
9300 9324
                          params={})
9325

  
9301 9326
  drbd_dev = objects.Disk(dev_type=constants.LD_DRBD8, size=size,
9302 9327
                          logical_id=(primary, secondary, port,
9303 9328
                                      p_minor, s_minor,
9304 9329
                                      shared_secret),
9305 9330
                          children=[dev_data, dev_meta],
9306 9331
                          iv_name=iv_name, params={})
9332
  drbd_dev.idx = _GetDeviceUniqueIdx(lu, 'disks')
9333

  
9307 9334
  return drbd_dev
9308 9335

  
9309 9336

  
......
9425 9452
      size = disk[constants.IDISK_SIZE]
9426 9453
      feedback_fn("* disk %s, size %s" %
9427 9454
                  (disk_index, utils.FormatUnit(size, "h")))
9428
      disks.append(objects.Disk(dev_type=dev_type, size=size,
9429
                                logical_id=logical_id_fn(idx, disk_index, disk),
9430
                                iv_name="disk/%d" % disk_index,
9431
                                mode=disk[constants.IDISK_MODE],
9432
                                params=params))
9455
      disk_obj = objects.Disk(dev_type=dev_type, size=size,
9456
                              logical_id=logical_id_fn(idx, disk_index, disk),
9457
                              iv_name="disk/%d" % disk_index,
9458
                              mode=disk[constants.IDISK_MODE],
9459
                              params=params)
9460
      disk_obj.idx = _GetDeviceUniqueIdx(lu, 'disks')
9461

  
9462
      disks.append(disk_obj)
9433 9463

  
9434 9464
  return disks
9435 9465

  
......
9785 9815
                                       node_whitelist=node_whitelist)
9786 9816

  
9787 9817

  
9788
def _ComputeNics(op, cluster, default_ip, cfg, ec_id):
9818
def _ComputeNics(lu, op, cluster, default_ip, cfg, ec_id):
9789 9819
  """Computes the nics.
9790 9820

  
9821
  @param lu: The LU
9791 9822
  @param op: The instance opcode
9792 9823
  @param cluster: Cluster configuration object
9793 9824
  @param default_ip: The default ip to assign
......
9867 9898

  
9868 9899
    check_params = cluster.SimpleFillNIC(nicparams)
9869 9900
    objects.NIC.CheckParameterSyntax(check_params)
9870
    nics.append(objects.NIC(mac=mac, ip=nic_ip,
9871
                            network=net, nicparams=nicparams))
9901
    nic_obj = objects.NIC(mac=mac, ip=nic_ip, network=net,
9902
                          nicparams=check_params)
9903
    nic_obj.idx = _GetDeviceUniqueIdx(lu, 'nics')
9904

  
9905
    nics.append(nic_obj)
9872 9906

  
9873 9907
  return nics
9874 9908

  
......
10518 10552
    if self.op.identify_defaults:
10519 10553
      self._RevertToDefaults(cluster)
10520 10554

  
10555
    self.dev_idxs = { "disks": 0, "nics": 0 }
10556

  
10521 10557
    # NIC buildup
10522
    self.nics = _ComputeNics(self.op, cluster, self.check_ip, self.cfg,
10558
    self.nics = _ComputeNics(self, self.op, cluster, self.check_ip, self.cfg,
10523 10559
                             self.proc.GetECId())
10524 10560

  
10525 10561
    # disk checks/pre-build
......
10855 10891
                            hvparams=self.op.hvparams,
10856 10892
                            hypervisor=self.op.hypervisor,
10857 10893
                            osparams=self.op.osparams,
10894
                            dev_idxs=self.dev_idxs,
10858 10895
                            )
10859 10896

  
10860 10897
    if self.op.tags:
......
11144 11181
      node_whitelist = None
11145 11182

  
11146 11183
    insts = [_CreateInstanceAllocRequest(op, _ComputeDisks(op, default_vg),
11147
                                         _ComputeNics(op, cluster, None,
11184
                                         _ComputeNics(self, op, cluster, None,
11148 11185
                                                      self.cfg, ec_id),
11149 11186
                                         _ComputeFullBeParams(op, cluster),
11150 11187
                                         node_whitelist)
......
13016 13053
        if remove_fn is not None:
13017 13054
          remove_fn(absidx, item, private)
13018 13055

  
13056
        #TODO: include a hotplugged msg in changes
13019 13057
        changes = [("%s/%s" % (kind, absidx), "remove")]
13020 13058

  
13021 13059
        assert container[absidx] == item
13022 13060
        del container[absidx]
13023 13061
      elif op == constants.DDM_MODIFY:
13024 13062
        if modify_fn is not None:
13063
          #TODO: include a hotplugged msg in changes
13025 13064
          changes = modify_fn(absidx, item, params, private)
13065

  
13026 13066
      else:
13027 13067
        raise errors.ProgrammerError("Unhandled operation '%s'" % op)
13028 13068

  
......
13747 13787
                                 " (%d), cannot add more" % constants.MAX_NICS,
13748 13788
                                 errors.ECODE_STATE)
13749 13789

  
13790

  
13750 13791
    # Verify disk changes (operating on a copy)
13751 13792
    disks = instance.disks[:]
13752
    ApplyContainerMods("disk", disks, None, self.diskmod, None, None, None)
13793
    ApplyContainerMods("disk", disks, None, self.diskmod,
13794
                       None, None, None)
13753 13795
    if len(disks) > constants.MAX_DISKS:
13754 13796
      raise errors.OpPrereqError("Instance has too many disks (%d), cannot add"
13755 13797
                                 " more" % constants.MAX_DISKS,
......
13770 13812
      # Operate on copies as this is still in prereq
13771 13813
      nics = [nic.Copy() for nic in instance.nics]
13772 13814
      ApplyContainerMods("NIC", nics, self._nic_chgdesc, self.nicmod,
13773
                         self._CreateNewNic, self._ApplyNicMods, None)
13815
                         self._CreateNewNic, self._ApplyNicMods,
13816
                         self._RemoveNic)
13774 13817
      self._new_nics = nics
13775 13818
      ispec[constants.ISPEC_NIC_COUNT] = len(self._new_nics)
13776 13819
    else:
......
13805 13848
                utils.CommaJoin(set(res_max + res_min))))
13806 13849
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
13807 13850

  
13851

  
13808 13852
  def _ConvertPlainToDrbd(self, feedback_fn):
13809 13853
    """Converts an instance from plain to drbd.
13810 13854

  
......
13956 14000
        self.LogWarning("Failed to create volume %s (%s) on node '%s': %s",
13957 14001
                        disk.iv_name, disk, node, err)
13958 14002

  
14003
    if self.op.hotplug:
14004
      self.LogInfo("Trying to hotplug device.")
14005
      _, device_info = _AssembleInstanceDisks(self, self.instance,
14006
                                              [disk], check=False)
14007
      _, _, dev_path = device_info[0]
14008
      result = self.rpc.call_hot_add_disk(self.instance.primary_node,
14009
                                          self.instance, disk, dev_path, idx)
14010
      result.Raise("Could not hotplug device.")
14011
      self.LogInfo("Hotplug done.")
14012

  
13959 14013
    return (disk, [
13960 14014
      ("disk/%d" % idx, "add:size=%s,mode=%s" % (disk.size, disk.mode)),
13961 14015
      ])
......
13975 14029
    """Removes a disk.
13976 14030

  
13977 14031
    """
14032
    #TODO: log warning in case hotplug is not possible
14033
    if self.op.hotplug and _DeviceHotplugable(root):
14034
      self.LogInfo("Trying to hotplug device.")
14035
      result = self.rpc.call_hot_del_disk(self.instance.primary_node,
14036
                                          self.instance, root, idx)
14037
      result.Raise("Could not hotplug device.")
14038
      self.LogInfo("Hotplug done.")
14039
      _ShutdownInstanceDisks(self, self.instance, [root])
14040

  
13978 14041
    (anno_disk,) = _AnnotateDiskParams(self.instance, [root], self.cfg)
13979 14042
    for node, disk in anno_disk.ComputeNodeTree(self.instance.primary_node):
13980 14043
      self.cfg.SetDiskID(disk, node)
......
13987 14050
    if root.dev_type in constants.LDS_DRBD:
13988 14051
      self.cfg.AddTcpUdpPort(root.logical_id[2])
13989 14052

  
13990
  @staticmethod
13991
  def _CreateNewNic(idx, params, private):
14053
  def _CreateNewNic(self, idx, params, private):
13992 14054
    """Creates data structure for a new network interface.
13993 14055

  
13994 14056
    """
13995 14057
    mac = params[constants.INIC_MAC]
13996 14058
    ip = params.get(constants.INIC_IP, None)
13997 14059
    net = params.get(constants.INIC_NETWORK, None)
13998
    #TODO: not private.filled?? can a nic have no nicparams??
14060
    #TODO: not private.filled?? can a nic be saved without nicparams??
13999 14061
    nicparams = private.filled
14000 14062

  
14001
    return (objects.NIC(mac=mac, ip=ip, network=net, nicparams=nicparams), [
14063
    nic = objects.NIC(mac=mac, ip=ip, network=net, nicparams=nicparams)
14064

  
14065
    nic.idx = _GetDeviceUniqueIdx(self, 'nics')
14066
    #TODO: log warning in case hotplug is not possible
14067
    if self.op.hotplug:
14068
      result = self.rpc.call_hot_add_nic(self.instance.primary_node,
14069
                                         self.instance, nic, idx)
14070
      result.Raise("Could not hotplug device")
14071
      self.Log("Hotplug done.")
14072

  
14073
    desc =  [
14002 14074
      ("nic.%d" % idx,
14003 14075
       "add:mac=%s,ip=%s,mode=%s,link=%s,network=%s" %
14004 14076
       (mac, ip, private.filled[constants.NIC_MODE],
14005
       private.filled[constants.NIC_LINK],
14006
       net)),
14007
      ])
14077
       private.filled[constants.NIC_LINK], net)),
14078
      ]
14079
    return (nic, desc)
14008 14080

  
14009
  @staticmethod
14010
  def _ApplyNicMods(idx, nic, params, private):
14081
  def _ApplyNicMods(self, idx, nic, params, private):
14011 14082
    """Modifies a network interface.
14012 14083

  
14013 14084
    """
......
14024 14095
      for (key, val) in nic.nicparams.items():
14025 14096
        changes.append(("nic.%s/%d" % (key, idx), val))
14026 14097

  
14098
    #TODO: log warning in case hotplug is not possible
14099
    if self.op.hotplug and _DeviceHotplugable(nic):
14100
      self.LogInfo("Trying to hotplug device.")
14101
      result = self.rpc.call_hot_del_nic(self.instance.primary_node,
14102
                                         self.instance, nic, idx)
14103
      result.Raise("Could not hotplug device.")
14104
      result = self.rpc.call_hot_add_nic(self.instance.primary_node,
14105
                                         self.instance, nic, idx)
14106
      result.Raise("Could not hotplug device.")
14107
      self.Log("Hotplug done.")
14108

  
14027 14109
    return changes
14028 14110

  
14111
  def _RemoveNic(self, idx, nic, _):
14112
    #TODO: log warning in case hotplug is not possible
14113
    if self.op.hotplug and _DeviceHotplugable(nic):
14114
      self.LogInfo("Trying to hotplug device.")
14115
      result = self.rpc.call_hot_del_nic(self.instance.primary_node,
14116
                                         self.instance, nic, idx)
14117
      result.Raise("Could not hotplug device.")
14118
      self.Log("Hotplug done.")
14119

  
14120

  
14029 14121
  def Exec(self, feedback_fn):
14030 14122
    """Modifies an instance.
14031 14123

  

Also available in: Unified diff