Package ganeti :: Package cmdlib :: Module network
[hide private]
[frames] | no frames]

Source Code for Module ganeti.cmdlib.network

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30   
 31  """Logical units dealing with networks.""" 
 32   
 33  from ganeti import constants 
 34  from ganeti import errors 
 35  from ganeti import locking 
 36  from ganeti import network 
 37  from ganeti import objects 
 38  from ganeti import qlang 
 39  from ganeti import query 
 40  from ganeti import utils 
 41  from ganeti.cmdlib.base import LogicalUnit, NoHooksLU, QueryBase 
 42  from ganeti.cmdlib.common import ShareAll, CheckNodeGroupInstances 
43 44 45 -def _BuildNetworkHookEnv(name, subnet, gateway, network6, gateway6, 46 mac_prefix, tags):
47 """Builds network related env variables for hooks 48 49 This builds the hook environment from individual variables. 50 51 @type name: string 52 @param name: the name of the network 53 @type subnet: string 54 @param subnet: the ipv4 subnet 55 @type gateway: string 56 @param gateway: the ipv4 gateway 57 @type network6: string 58 @param network6: the ipv6 subnet 59 @type gateway6: string 60 @param gateway6: the ipv6 gateway 61 @type mac_prefix: string 62 @param mac_prefix: the mac_prefix 63 @type tags: list 64 @param tags: the tags of the network 65 66 """ 67 env = {} 68 if name: 69 env["NETWORK_NAME"] = name 70 if subnet: 71 env["NETWORK_SUBNET"] = subnet 72 if gateway: 73 env["NETWORK_GATEWAY"] = gateway 74 if network6: 75 env["NETWORK_SUBNET6"] = network6 76 if gateway6: 77 env["NETWORK_GATEWAY6"] = gateway6 78 if mac_prefix: 79 env["NETWORK_MAC_PREFIX"] = mac_prefix 80 if tags: 81 env["NETWORK_TAGS"] = " ".join(tags) 82 83 return env
84
85 86 -class LUNetworkAdd(LogicalUnit):
87 """Logical unit for creating networks. 88 89 """ 90 HPATH = "network-add" 91 HTYPE = constants.HTYPE_NETWORK 92 REQ_BGL = False 93
94 - def BuildHooksNodes(self):
95 """Build hooks nodes. 96 97 """ 98 mn = self.cfg.GetMasterNode() 99 return ([mn], [mn])
100
101 - def CheckArguments(self):
102 if self.op.mac_prefix: 103 self.op.mac_prefix = \ 104 utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix)
105
106 - def ExpandNames(self):
107 self.network_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId()) 108 109 if self.op.conflicts_check: 110 self.share_locks[locking.LEVEL_NODE] = 1 111 self.share_locks[locking.LEVEL_NODE_ALLOC] = 1 112 self.needed_locks = { 113 locking.LEVEL_NODE: locking.ALL_SET, 114 locking.LEVEL_NODE_ALLOC: locking.ALL_SET, 115 } 116 else: 117 self.needed_locks = {} 118 119 self.add_locks[locking.LEVEL_NETWORK] = self.network_uuid
120
121 - def CheckPrereq(self):
122 if self.op.network is None: 123 raise errors.OpPrereqError("Network must be given", 124 errors.ECODE_INVAL) 125 126 try: 127 existing_uuid = self.cfg.LookupNetwork(self.op.network_name) 128 except errors.OpPrereqError: 129 pass 130 else: 131 raise errors.OpPrereqError("Desired network name '%s' already exists as a" 132 " network (UUID: %s)" % 133 (self.op.network_name, existing_uuid), 134 errors.ECODE_EXISTS) 135 136 # Check tag validity 137 for tag in self.op.tags: 138 objects.TaggableObject.ValidateTag(tag)
139
140 - def BuildHooksEnv(self):
141 """Build hooks env. 142 143 """ 144 args = { 145 "name": self.op.network_name, 146 "subnet": self.op.network, 147 "gateway": self.op.gateway, 148 "network6": self.op.network6, 149 "gateway6": self.op.gateway6, 150 "mac_prefix": self.op.mac_prefix, 151 "tags": self.op.tags, 152 } 153 return _BuildNetworkHookEnv(**args) # pylint: disable=W0142
154
155 - def Exec(self, feedback_fn):
156 """Add the ip pool to the cluster. 157 158 """ 159 nobj = objects.Network(name=self.op.network_name, 160 network=self.op.network, 161 gateway=self.op.gateway, 162 network6=self.op.network6, 163 gateway6=self.op.gateway6, 164 mac_prefix=self.op.mac_prefix, 165 uuid=self.network_uuid) 166 # Initialize the associated address pool 167 try: 168 pool = network.AddressPool.InitializeNetwork(nobj) 169 except errors.AddressPoolError, err: 170 raise errors.OpExecError("Cannot create IP address pool for network" 171 " '%s': %s" % (self.op.network_name, err)) 172 173 # Check if we need to reserve the nodes and the cluster master IP 174 # These may not be allocated to any instances in routed mode, as 175 # they wouldn't function anyway. 176 if self.op.conflicts_check: 177 for node in self.cfg.GetAllNodesInfo().values(): 178 for ip in [node.primary_ip, node.secondary_ip]: 179 try: 180 if pool.Contains(ip): 181 pool.Reserve(ip, external=True) 182 self.LogInfo("Reserved IP address of node '%s' (%s)", 183 node.name, ip) 184 except errors.AddressPoolError, err: 185 self.LogWarning("Cannot reserve IP address '%s' of node '%s': %s", 186 ip, node.name, err) 187 188 master_ip = self.cfg.GetClusterInfo().master_ip 189 try: 190 if pool.Contains(master_ip): 191 pool.Reserve(master_ip, external=True) 192 self.LogInfo("Reserved cluster master IP address (%s)", master_ip) 193 except errors.AddressPoolError, err: 194 self.LogWarning("Cannot reserve cluster master IP address (%s): %s", 195 master_ip, err) 196 197 if self.op.add_reserved_ips: 198 for ip in self.op.add_reserved_ips: 199 try: 200 pool.Reserve(ip, external=True) 201 except errors.AddressPoolError, err: 202 raise errors.OpExecError("Cannot reserve IP address '%s': %s" % 203 (ip, err)) 204 205 if self.op.tags: 206 for tag in self.op.tags: 207 nobj.AddTag(tag) 208 209 self.cfg.AddNetwork(nobj, self.proc.GetECId(), check_uuid=False) 210 del self.remove_locks[locking.LEVEL_NETWORK]
211
212 213 -class LUNetworkRemove(LogicalUnit):
214 HPATH = "network-remove" 215 HTYPE = constants.HTYPE_NETWORK 216 REQ_BGL = False 217
218 - def ExpandNames(self):
219 self.network_uuid = self.cfg.LookupNetwork(self.op.network_name) 220 221 self.share_locks[locking.LEVEL_NODEGROUP] = 1 222 self.needed_locks = { 223 locking.LEVEL_NETWORK: [self.network_uuid], 224 locking.LEVEL_NODEGROUP: locking.ALL_SET, 225 }
226
227 - def CheckPrereq(self):
228 """Check prerequisites. 229 230 This checks that the given network name exists as a network, that is 231 empty (i.e., contains no nodes), and that is not the last group of the 232 cluster. 233 234 """ 235 # Verify that the network is not conncted. 236 node_groups = [group.name 237 for group in self.cfg.GetAllNodeGroupsInfo().values() 238 if self.network_uuid in group.networks] 239 240 if node_groups: 241 self.LogWarning("Network '%s' is connected to the following" 242 " node groups: %s" % 243 (self.op.network_name, 244 utils.CommaJoin(utils.NiceSort(node_groups)))) 245 raise errors.OpPrereqError("Network still connected", errors.ECODE_STATE)
246
247 - def BuildHooksEnv(self):
248 """Build hooks env. 249 250 """ 251 return { 252 "NETWORK_NAME": self.op.network_name, 253 }
254
255 - def BuildHooksNodes(self):
256 """Build hooks nodes. 257 258 """ 259 mn = self.cfg.GetMasterNode() 260 return ([mn], [mn])
261
262 - def Exec(self, feedback_fn):
263 """Remove the network. 264 265 """ 266 try: 267 self.cfg.RemoveNetwork(self.network_uuid) 268 except errors.ConfigurationError: 269 raise errors.OpExecError("Network '%s' with UUID %s disappeared" % 270 (self.op.network_name, self.network_uuid))
271
272 273 -class LUNetworkSetParams(LogicalUnit):
274 """Modifies the parameters of a network. 275 276 """ 277 HPATH = "network-modify" 278 HTYPE = constants.HTYPE_NETWORK 279 REQ_BGL = False 280
281 - def CheckArguments(self):
282 if (self.op.gateway and 283 (self.op.add_reserved_ips or self.op.remove_reserved_ips)): 284 raise errors.OpPrereqError("Cannot modify gateway and reserved ips" 285 " at once", errors.ECODE_INVAL)
286
287 - def ExpandNames(self):
288 self.network_uuid = self.cfg.LookupNetwork(self.op.network_name) 289 290 self.needed_locks = { 291 locking.LEVEL_NETWORK: [self.network_uuid], 292 }
293
294 - def CheckPrereq(self):
295 """Check prerequisites. 296 297 """ 298 self.network = self.cfg.GetNetwork(self.network_uuid) 299 self.gateway = self.network.gateway 300 self.mac_prefix = self.network.mac_prefix 301 self.network6 = self.network.network6 302 self.gateway6 = self.network.gateway6 303 self.tags = self.network.tags 304 305 self.pool = network.AddressPool(self.network) 306 307 if self.op.gateway: 308 if self.op.gateway == constants.VALUE_NONE: 309 self.gateway = None 310 else: 311 self.gateway = self.op.gateway 312 if self.pool.IsReserved(self.gateway): 313 raise errors.OpPrereqError("Gateway IP address '%s' is already" 314 " reserved" % self.gateway, 315 errors.ECODE_STATE) 316 317 if self.op.mac_prefix: 318 if self.op.mac_prefix == constants.VALUE_NONE: 319 self.mac_prefix = None 320 else: 321 self.mac_prefix = \ 322 utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix) 323 324 if self.op.gateway6: 325 if self.op.gateway6 == constants.VALUE_NONE: 326 self.gateway6 = None 327 else: 328 self.gateway6 = self.op.gateway6 329 330 if self.op.network6: 331 if self.op.network6 == constants.VALUE_NONE: 332 self.network6 = None 333 else: 334 self.network6 = self.op.network6
335
336 - def BuildHooksEnv(self):
337 """Build hooks env. 338 339 """ 340 args = { 341 "name": self.op.network_name, 342 "subnet": self.network.network, 343 "gateway": self.gateway, 344 "network6": self.network6, 345 "gateway6": self.gateway6, 346 "mac_prefix": self.mac_prefix, 347 "tags": self.tags, 348 } 349 return _BuildNetworkHookEnv(**args) # pylint: disable=W0142
350
351 - def BuildHooksNodes(self):
352 """Build hooks nodes. 353 354 """ 355 mn = self.cfg.GetMasterNode() 356 return ([mn], [mn])
357
358 - def Exec(self, feedback_fn):
359 """Modifies the network. 360 361 """ 362 #TODO: reserve/release via temporary reservation manager 363 # extend cfg.ReserveIp/ReleaseIp with the external flag 364 if self.op.gateway: 365 if self.gateway == self.network.gateway: 366 self.LogWarning("Gateway is already %s", self.gateway) 367 else: 368 if self.gateway: 369 self.pool.Reserve(self.gateway, external=True) 370 if self.network.gateway: 371 self.pool.Release(self.network.gateway, external=True) 372 self.network.gateway = self.gateway 373 374 if self.op.add_reserved_ips: 375 for ip in self.op.add_reserved_ips: 376 try: 377 self.pool.Reserve(ip, external=True) 378 except errors.AddressPoolError, err: 379 self.LogWarning("Cannot reserve IP address %s: %s", ip, err) 380 381 if self.op.remove_reserved_ips: 382 for ip in self.op.remove_reserved_ips: 383 if ip == self.network.gateway: 384 self.LogWarning("Cannot unreserve Gateway's IP") 385 continue 386 try: 387 self.pool.Release(ip, external=True) 388 except errors.AddressPoolError, err: 389 self.LogWarning("Cannot release IP address %s: %s", ip, err) 390 391 if self.op.mac_prefix: 392 self.network.mac_prefix = self.mac_prefix 393 394 if self.op.network6: 395 self.network.network6 = self.network6 396 397 if self.op.gateway6: 398 self.network.gateway6 = self.gateway6 399 400 self.pool.Validate() 401 402 self.cfg.Update(self.network, feedback_fn)
403
404 405 -class NetworkQuery(QueryBase):
406 FIELDS = query.NETWORK_FIELDS 407
408 - def ExpandNames(self, lu):
409 lu.needed_locks = {} 410 lu.share_locks = ShareAll() 411 412 self.do_locking = self.use_locking 413 414 all_networks = lu.cfg.GetAllNetworksInfo() 415 name_to_uuid = dict((n.name, n.uuid) for n in all_networks.values()) 416 417 if self.names: 418 missing = [] 419 self.wanted = [] 420 421 for name in self.names: 422 if name in name_to_uuid: 423 self.wanted.append(name_to_uuid[name]) 424 else: 425 missing.append(name) 426 427 if missing: 428 raise errors.OpPrereqError("Some networks do not exist: %s" % missing, 429 errors.ECODE_NOENT) 430 else: 431 self.wanted = locking.ALL_SET 432 433 if self.do_locking: 434 lu.needed_locks[locking.LEVEL_NETWORK] = self.wanted 435 if query.NETQ_INST in self.requested_data: 436 lu.needed_locks[locking.LEVEL_INSTANCE] = locking.ALL_SET 437 if query.NETQ_GROUP in self.requested_data: 438 lu.needed_locks[locking.LEVEL_NODEGROUP] = locking.ALL_SET
439
440 - def DeclareLocks(self, lu, level):
441 pass
442
443 - def _GetQueryData(self, lu):
444 """Computes the list of networks and their attributes. 445 446 """ 447 all_networks = lu.cfg.GetAllNetworksInfo() 448 449 network_uuids = self._GetNames(lu, all_networks.keys(), 450 locking.LEVEL_NETWORK) 451 452 do_instances = query.NETQ_INST in self.requested_data 453 do_groups = query.NETQ_GROUP in self.requested_data 454 455 network_to_instances = None 456 network_to_groups = None 457 458 # For NETQ_GROUP, we need to map network->[groups] 459 if do_groups: 460 all_groups = lu.cfg.GetAllNodeGroupsInfo() 461 network_to_groups = dict((uuid, []) for uuid in network_uuids) 462 for _, group in all_groups.iteritems(): 463 for net_uuid in network_uuids: 464 netparams = group.networks.get(net_uuid, None) 465 if netparams: 466 info = (group.name, netparams[constants.NIC_MODE], 467 netparams[constants.NIC_LINK], 468 netparams[constants.NIC_VLAN]) 469 470 network_to_groups[net_uuid].append(info) 471 472 if do_instances: 473 all_instances = lu.cfg.GetAllInstancesInfo() 474 network_to_instances = dict((uuid, []) for uuid in network_uuids) 475 for instance in all_instances.values(): 476 for nic in instance.nics: 477 if nic.network in network_uuids: 478 if instance.name not in network_to_instances[nic.network]: 479 network_to_instances[nic.network].append(instance.name) 480 481 if query.NETQ_STATS in self.requested_data: 482 stats = \ 483 dict((uuid, 484 self._GetStats(network.AddressPool(all_networks[uuid]))) 485 for uuid in network_uuids) 486 else: 487 stats = None 488 489 return query.NetworkQueryData([all_networks[uuid] 490 for uuid in network_uuids], 491 network_to_groups, 492 network_to_instances, 493 stats)
494 495 @staticmethod
496 - def _GetStats(pool):
497 """Returns statistics for a network address pool. 498 499 """ 500 return { 501 "free_count": pool.GetFreeCount(), 502 "reserved_count": pool.GetReservedCount(), 503 "map": pool.GetMap(), 504 "external_reservations": 505 utils.CommaJoin(pool.GetExternalReservations()), 506 }
507
508 509 -class LUNetworkQuery(NoHooksLU):
510 """Logical unit for querying networks. 511 512 """ 513 REQ_BGL = False 514
515 - def CheckArguments(self):
516 self.nq = NetworkQuery(qlang.MakeSimpleFilter("name", self.op.names), 517 self.op.output_fields, self.op.use_locking)
518
519 - def ExpandNames(self):
520 self.nq.ExpandNames(self)
521
522 - def Exec(self, feedback_fn):
523 return self.nq.OldStyleQuery(self)
524
525 526 -def _FmtNetworkConflict(details):
527 """Utility for L{_NetworkConflictCheck}. 528 529 """ 530 return utils.CommaJoin("nic%s/%s" % (idx, ipaddr) 531 for (idx, ipaddr) in details)
532
533 534 -def _NetworkConflictCheck(lu, check_fn, action, instances):
535 """Checks for network interface conflicts with a network. 536 537 @type lu: L{LogicalUnit} 538 @type check_fn: callable receiving one parameter (L{objects.NIC}) and 539 returning boolean 540 @param check_fn: Function checking for conflict 541 @type action: string 542 @param action: Part of error message (see code) 543 @param instances: the instances to check 544 @type instances: list of instance objects 545 @raise errors.OpPrereqError: If conflicting IP addresses are found. 546 547 """ 548 conflicts = [] 549 550 for instance in instances: 551 instconflicts = [(idx, nic.ip) 552 for (idx, nic) in enumerate(instance.nics) 553 if check_fn(nic)] 554 555 if instconflicts: 556 conflicts.append((instance.name, instconflicts)) 557 558 if conflicts: 559 lu.LogWarning("IP addresses from network '%s', which is about to %s" 560 " node group '%s', are in use: %s" % 561 (lu.network_name, action, lu.group.name, 562 utils.CommaJoin(("%s: %s" % 563 (name, _FmtNetworkConflict(details))) 564 for (name, details) in conflicts))) 565 566 raise errors.OpPrereqError("Conflicting IP addresses found; " 567 " remove/modify the corresponding network" 568 " interfaces", errors.ECODE_STATE)
569
570 571 -class LUNetworkConnect(LogicalUnit):
572 """Connect a network to a nodegroup 573 574 """ 575 HPATH = "network-connect" 576 HTYPE = constants.HTYPE_NETWORK 577 REQ_BGL = False 578
579 - def ExpandNames(self):
580 self.network_name = self.op.network_name 581 self.group_name = self.op.group_name 582 self.network_mode = self.op.network_mode 583 self.network_link = self.op.network_link 584 self.network_vlan = self.op.network_vlan 585 586 self.network_uuid = self.cfg.LookupNetwork(self.network_name) 587 self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) 588 589 self.needed_locks = { 590 locking.LEVEL_INSTANCE: [], 591 locking.LEVEL_NODEGROUP: [self.group_uuid], 592 } 593 self.share_locks[locking.LEVEL_INSTANCE] = 1 594 595 if self.op.conflicts_check: 596 self.needed_locks[locking.LEVEL_NETWORK] = [self.network_uuid] 597 self.share_locks[locking.LEVEL_NETWORK] = 1
598
599 - def DeclareLocks(self, level):
600 if level == locking.LEVEL_INSTANCE: 601 assert not self.needed_locks[locking.LEVEL_INSTANCE] 602 603 # Lock instances optimistically, needs verification once group lock has 604 # been acquired 605 if self.op.conflicts_check: 606 self.needed_locks[locking.LEVEL_INSTANCE] = \ 607 self.cfg.GetInstanceNames( 608 self.cfg.GetNodeGroupInstances(self.group_uuid))
609
610 - def BuildHooksEnv(self):
611 ret = { 612 "GROUP_NAME": self.group_name, 613 "GROUP_NETWORK_MODE": self.network_mode, 614 "GROUP_NETWORK_LINK": self.network_link, 615 "GROUP_NETWORK_VLAN": self.network_vlan, 616 } 617 return ret
618
619 - def BuildHooksNodes(self):
620 node_uuids = self.cfg.GetNodeGroup(self.group_uuid).members 621 return (node_uuids, node_uuids)
622
623 - def CheckPrereq(self):
624 owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) 625 626 assert self.group_uuid in owned_groups 627 628 # Check if locked instances are still correct 629 owned_instance_names = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) 630 if self.op.conflicts_check: 631 CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instance_names) 632 633 self.netparams = { 634 constants.NIC_MODE: self.network_mode, 635 constants.NIC_LINK: self.network_link, 636 constants.NIC_VLAN: self.network_vlan, 637 } 638 639 objects.NIC.CheckParameterSyntax(self.netparams) 640 641 self.group = self.cfg.GetNodeGroup(self.group_uuid) 642 #if self.network_mode == constants.NIC_MODE_BRIDGED: 643 # _CheckNodeGroupBridgesExist(self, self.network_link, self.group_uuid) 644 self.connected = False 645 if self.network_uuid in self.group.networks: 646 self.LogWarning("Network '%s' is already mapped to group '%s'" % 647 (self.network_name, self.group.name)) 648 self.connected = True 649 650 # check only if not already connected 651 elif self.op.conflicts_check: 652 pool = network.AddressPool(self.cfg.GetNetwork(self.network_uuid)) 653 654 _NetworkConflictCheck( 655 self, lambda nic: pool.Contains(nic.ip), "connect to", 656 [instance_info for (_, instance_info) in 657 self.cfg.GetMultiInstanceInfoByName(owned_instance_names)])
658
659 - def Exec(self, feedback_fn):
660 # Connect the network and update the group only if not already connected 661 if not self.connected: 662 self.group.networks[self.network_uuid] = self.netparams 663 self.cfg.Update(self.group, feedback_fn)
664
665 666 -class LUNetworkDisconnect(LogicalUnit):
667 """Disconnect a network to a nodegroup 668 669 """ 670 HPATH = "network-disconnect" 671 HTYPE = constants.HTYPE_NETWORK 672 REQ_BGL = False 673
674 - def ExpandNames(self):
675 self.network_name = self.op.network_name 676 self.group_name = self.op.group_name 677 678 self.network_uuid = self.cfg.LookupNetwork(self.network_name) 679 self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) 680 681 self.needed_locks = { 682 locking.LEVEL_INSTANCE: [], 683 locking.LEVEL_NODEGROUP: [self.group_uuid], 684 } 685 self.share_locks[locking.LEVEL_INSTANCE] = 1
686
687 - def DeclareLocks(self, level):
688 if level == locking.LEVEL_INSTANCE: 689 assert not self.needed_locks[locking.LEVEL_INSTANCE] 690 691 # Lock instances optimistically, needs verification once group lock has 692 # been acquired 693 self.needed_locks[locking.LEVEL_INSTANCE] = \ 694 self.cfg.GetInstanceNames( 695 self.cfg.GetNodeGroupInstances(self.group_uuid))
696
697 - def BuildHooksEnv(self):
698 ret = { 699 "GROUP_NAME": self.group_name, 700 } 701 702 if self.connected: 703 ret.update({ 704 "GROUP_NETWORK_MODE": self.netparams[constants.NIC_MODE], 705 "GROUP_NETWORK_LINK": self.netparams[constants.NIC_LINK], 706 "GROUP_NETWORK_VLAN": self.netparams[constants.NIC_VLAN], 707 }) 708 return ret
709
710 - def BuildHooksNodes(self):
711 nodes = self.cfg.GetNodeGroup(self.group_uuid).members 712 return (nodes, nodes)
713
714 - def CheckPrereq(self):
715 owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) 716 717 assert self.group_uuid in owned_groups 718 719 # Check if locked instances are still correct 720 owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) 721 CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances) 722 723 self.group = self.cfg.GetNodeGroup(self.group_uuid) 724 self.connected = True 725 if self.network_uuid not in self.group.networks: 726 self.LogWarning("Network '%s' is not mapped to group '%s'", 727 self.network_name, self.group.name) 728 self.connected = False 729 730 # We need this check only if network is not already connected 731 else: 732 _NetworkConflictCheck( 733 self, lambda nic: nic.network == self.network_uuid, "disconnect from", 734 [instance_info for (_, instance_info) in 735 self.cfg.GetMultiInstanceInfoByName(owned_instances)]) 736 self.netparams = self.group.networks.get(self.network_uuid)
737
738 - def Exec(self, feedback_fn):
739 # Disconnect the network and update the group only if network is connected 740 if self.connected: 741 del self.group.networks[self.network_uuid] 742 self.cfg.Update(self.group, feedback_fn)
743