Revision 100c6d1a

b/lib/cmdlib.py
12222 12222
    """
12223 12223
    if op in (constants.DDM_ADD, constants.DDM_MODIFY):
12224 12224
      ip = params.get(constants.INIC_IP, None)
12225
      if ip is None:
12226
        pass
12227
      elif ip.lower() == constants.VALUE_NONE:
12228
        params[constants.INIC_IP] = None
12229
      elif not netutils.IPAddress.IsValid(ip):
12230
        raise errors.OpPrereqError("Invalid IP address '%s'" % ip,
12231
                                   errors.ECODE_INVAL)
12232

  
12233
      bridge = params.get("bridge", None)
12234
      link = params.get(constants.INIC_LINK, None)
12235
      if bridge and link:
12236
        raise errors.OpPrereqError("Cannot pass 'bridge' and 'link'"
12237
                                   " at the same time", errors.ECODE_INVAL)
12238
      elif bridge and bridge.lower() == constants.VALUE_NONE:
12239
        params["bridge"] = None
12240
      elif link and link.lower() == constants.VALUE_NONE:
12241
        params[constants.INIC_LINK] = None
12225
      req_net = params.get(constants.INIC_NETWORK, None)
12226
      link = params.get(constants.NIC_LINK, None)
12227
      mode = params.get(constants.NIC_MODE, None)
12228
      if req_net is not None:
12229
        if req_net.lower() == constants.VALUE_NONE:
12230
          params[constants.INIC_NETWORK] = None
12231
          req_net = None
12232
        elif link is not None or mode is not None:
12233
          raise errors.OpPrereqError("If network is given"
12234
                                     " mode or link should not",
12235
                                     errors.ECODE_INVAL)
12242 12236

  
12243 12237
      if op == constants.DDM_ADD:
12244 12238
        macaddr = params.get(constants.INIC_MAC, None)
12245 12239
        if macaddr is None:
12246 12240
          params[constants.INIC_MAC] = constants.VALUE_AUTO
12247 12241

  
12242
      if ip is not None:
12243
        if ip.lower() == constants.VALUE_NONE:
12244
          params[constants.INIC_IP] = None
12245
        else:
12246
          if ip.lower() == constants.NIC_IP_POOL:
12247
            if op == constants.DDM_ADD and req_net is None:
12248
              raise errors.OpPrereqError("If ip=pool, parameter network"
12249
                                         " cannot be none",
12250
                                         errors.ECODE_INVAL)
12251
          else:
12252
            if not netutils.IPAddress.IsValid(ip):
12253
              raise errors.OpPrereqError("Invalid IP address '%s'" % ip,
12254
                                         errors.ECODE_INVAL)
12255

  
12248 12256
      if constants.INIC_MAC in params:
12249 12257
        macaddr = params[constants.INIC_MAC]
12250 12258
        if macaddr not in (constants.VALUE_AUTO, constants.VALUE_GENERATE):
......
12334 12342
        nicparams = self.cluster.SimpleFillNIC(nic.nicparams)
12335 12343
        mode = nicparams[constants.NIC_MODE]
12336 12344
        link = nicparams[constants.NIC_LINK]
12337
        nics.append((nic.ip, nic.mac, mode, link))
12345
        nics.append((nic.ip, nic.mac, mode, link, nic.network))
12338 12346

  
12339 12347
      args["nics"] = nics
12340 12348

  
......
12353 12361
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
12354 12362
    return (nl, nl)
12355 12363

  
12356
  def _PrepareNicModification(self, params, private, old_ip, old_params,
12357
                              cluster, pnode):
12364
  def _PrepareNicModification(self, params, private, old_ip, old_net,
12365
                              old_params, cluster, pnode):
12366

  
12358 12367
    update_params_dict = dict([(key, params[key])
12359 12368
                               for key in constants.NICS_PARAMETERS
12360 12369
                               if key in params])
12361 12370

  
12362
    if "bridge" in params:
12363
      update_params_dict[constants.NIC_LINK] = params["bridge"]
12371
    req_link = update_params_dict.get(constants.NIC_LINK, None)
12372
    req_mode = update_params_dict.get(constants.NIC_MODE, None)
12373

  
12374
    new_net = params.get(constants.INIC_NETWORK, old_net)
12375
    if new_net is not None:
12376
      netparams = self.cfg.GetGroupNetParams(new_net, pnode)
12377
      if netparams is None:
12378
        raise errors.OpPrereqError("No netparams found for the network"
12379
                                   " %s, propably not connected." % new_net,
12380
                                   errors.ECODE_INVAL)
12381
      new_params = dict(netparams)
12382
    else:
12383
      new_params = _GetUpdatedParams(old_params, update_params_dict)
12364 12384

  
12365
    new_params = _GetUpdatedParams(old_params, update_params_dict)
12366 12385
    utils.ForceDictType(new_params, constants.NICS_PARAMETER_TYPES)
12367 12386

  
12368 12387
    new_filled_params = cluster.SimpleFillNIC(new_params)
......
12402 12421
          raise errors.OpPrereqError("MAC address '%s' already in use"
12403 12422
                                     " in cluster" % mac,
12404 12423
                                     errors.ECODE_NOTUNIQUE)
12424
    elif new_net != old_net:
12425
      def get_net_prefix(net):
12426
        if net:
12427
          uuid = self.cfg.LookupNetwork(net)
12428
          if uuid:
12429
            nobj = self.cfg.GetNetwork(uuid)
12430
            return nobj.mac_prefix
12431
        return None
12432
      new_prefix = get_net_prefix(new_net)
12433
      old_prefix = get_net_prefix(old_net)
12434
      if old_prefix != new_prefix:
12435
        params[constants.INIC_MAC] = \
12436
          self.cfg.GenerateMAC(self.proc.GetECId())
12437

  
12438
    #if there is a change in nic-network configuration
12439
    new_ip = params.get(constants.INIC_IP, old_ip)
12440
    if (new_ip, new_net) != (old_ip, old_net):
12441
      if new_ip:
12442
        if new_net:
12443
          if new_ip.lower() == constants.NIC_IP_POOL:
12444
            try:
12445
              new_ip = self.cfg.GenerateIp(new_net, self.proc.GetECId())
12446
            except errors.ReservationError:
12447
              raise errors.OpPrereqError("Unable to get a free IP"
12448
                                        " from the address pool",
12449
                                         errors.ECODE_STATE)
12450
            self.LogInfo("Chose IP %s from pool %s", new_ip, new_net)
12451
            params[constants.INIC_IP] = new_ip
12452
          elif new_ip != old_ip or new_net != old_net:
12453
            try:
12454
              self.LogInfo("Reserving IP %s in pool %s", new_ip, new_net)
12455
              self.cfg.ReserveIp(new_net, new_ip, self.proc.GetECId())
12456
            except errors.ReservationError:
12457
              raise errors.OpPrereqError("IP %s not available in network %s" %
12458
                                         (new_ip, new_net),
12459
                                         errors.ECODE_NOTUNIQUE)
12460
        elif new_ip.lower() == constants.NIC_IP_POOL:
12461
          raise errors.OpPrereqError("ip=pool, but no network found",
12462
                                     ECODEE_INVAL)
12463
        else:
12464
          # new net is None
12465
          if self.op.conflicts_check:
12466
            _CheckForConflictingIp(self, new_ip, pnode)
12467

  
12468
      if old_ip:
12469
        if old_net:
12470
          try:
12471
            self.cfg.ReleaseIp(old_net, old_ip, self.proc.GetECId())
12472
          except errors.AddressPoolError:
12473
            logging.warning("Release IP %s not contained in network %s",
12474
                            old_ip, old_net)
12475

  
12476
    # there are no changes in (net, ip) tuple
12477
    elif (old_net is not None and
12478
          (req_link is not None or req_mode is not None)):
12479
      raise errors.OpPrereqError("Not allowed to change link or mode of"
12480
                                 " a NIC that is connected to a network.",
12481
                                 errors.ECODE_INVAL)
12405 12482

  
12406 12483
    private.params = new_params
12407 12484
    private.filled = new_filled_params
......
12640 12717
                                 errors.ECODE_INVAL)
12641 12718

  
12642 12719
    def _PrepareNicCreate(_, params, private):
12643
      self._PrepareNicModification(params, private, None, {}, cluster, pnode)
12720
      self._PrepareNicModification(params, private, None, None,
12721
                                   {}, cluster, pnode)
12644 12722
      return (None, None)
12645 12723

  
12646 12724
    def _PrepareNicMod(_, nic, params, private):
12647
      self._PrepareNicModification(params, private, nic.ip,
12725
      self._PrepareNicModification(params, private, nic.ip, nic.network,
12648 12726
                                   nic.nicparams, cluster, pnode)
12649 12727
      return None
12650 12728

  
12729
    def _PrepareNicRemove(_, params, private):
12730
      ip = params.ip
12731
      net = params.network
12732
      if net is not None and ip is not None:
12733
        self.cfg.ReleaseIp(net, ip, self.proc.GetECId())
12734

  
12651 12735
    # Verify NIC changes (operating on copy)
12652 12736
    nics = instance.nics[:]
12653 12737
    ApplyContainerMods("NIC", nics, None, self.nicmod,
12654
                       _PrepareNicCreate, _PrepareNicMod, None)
12738
                       _PrepareNicCreate, _PrepareNicMod, _PrepareNicRemove)
12655 12739
    if len(nics) > constants.MAX_NICS:
12656 12740
      raise errors.OpPrereqError("Instance has too many network interfaces"
12657 12741
                                 " (%d), cannot add more" % constants.MAX_NICS,
......
12868 12952
    """
12869 12953
    mac = params[constants.INIC_MAC]
12870 12954
    ip = params.get(constants.INIC_IP, None)
12871
    nicparams = private.params
12955
    network = params.get(constants.INIC_NETWORK, None)
12956
    #TODO: not private.filled?? can a nic have no nicparams??
12957
    nicparams = private.filled
12872 12958

  
12873
    return (objects.NIC(mac=mac, ip=ip, nicparams=nicparams), [
12959
    return (objects.NIC(mac=mac, ip=ip, network=network, nicparams=nicparams), [
12874 12960
      ("nic.%d" % idx,
12875
       "add:mac=%s,ip=%s,mode=%s,link=%s" %
12961
       "add:mac=%s,ip=%s,mode=%s,link=%s,network=%s" %
12876 12962
       (mac, ip, private.filled[constants.NIC_MODE],
12877
       private.filled[constants.NIC_LINK])),
12963
       private.filled[constants.NIC_LINK],
12964
       network)),
12878 12965
      ])
12879 12966

  
12880 12967
  @staticmethod
......
12884 12971
    """
12885 12972
    changes = []
12886 12973

  
12887
    for key in [constants.INIC_MAC, constants.INIC_IP]:
12974
    for key in [constants.INIC_MAC, constants.INIC_IP, constants.INIC_NETWORK]:
12888 12975
      if key in params:
12889 12976
        changes.append(("nic.%s/%d" % (key, idx), params[key]))
12890 12977
        setattr(nic, key, params[key])
12891 12978

  
12892
    if private.params:
12893
      nic.nicparams = private.params
12979
    if private.filled:
12980
      nic.nicparams = private.filled
12894 12981

  
12895
      for (key, val) in params.items():
12982
      for (key, val) in nic.nicparams.items():
12896 12983
        changes.append(("nic.%s/%d" % (key, idx), val))
12897 12984

  
12898 12985
    return changes
......
13000 13087
      self.cfg.MarkInstanceDown(instance.name)
13001 13088
      result.append(("admin_state", constants.ADMINST_DOWN))
13002 13089

  
13003
    self.cfg.Update(instance, feedback_fn)
13090
    self.cfg.Update(instance, feedback_fn, self.proc.GetECId())
13004 13091

  
13005 13092
    assert not (self.owned_locks(locking.LEVEL_NODE_RES) or
13006 13093
                self.owned_locks(locking.LEVEL_NODE)), \
b/lib/config.py
2303 2303
    return self._config_data.HasAnyDiskOfType(dev_type)
2304 2304

  
2305 2305
  @locking.ssynchronized(_config_lock)
2306
  def Update(self, target, feedback_fn):
2306
  def Update(self, target, feedback_fn, ec_id=None):
2307 2307
    """Notify function to be called after updates.
2308 2308

  
2309 2309
    This function must be called when an object (as returned by
......
2350 2350
    if isinstance(target, objects.Instance):
2351 2351
      self._UnlockedReleaseDRBDMinors(target.name)
2352 2352

  
2353
    if ec_id is not None:
2354
      # Commit all ips reserved by OpInstanceSetParams and OpGroupSetParams
2355
      self._UnlockedCommitTemporaryIps(ec_id)
2356

  
2353 2357
    self._WriteConfig(feedback_fn=feedback_fn)
2354 2358

  
2355 2359
  @locking.ssynchronized(_config_lock)

Also available in: Unified diff