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