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.name) 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 @raise errors.OpPrereqError: If conflicting IP addresses are found. 540 541 """ 542 conflicts = [] 543 544 for (_, instance) in lu.cfg.GetMultiInstanceInfo(instances): 545 instconflicts = [(idx, nic.ip) 546 for (idx, nic) in enumerate(instance.nics) 547 if check_fn(nic)] 548 549 if instconflicts: 550 conflicts.append((instance.name, instconflicts)) 551 552 if conflicts: 553 lu.LogWarning("IP addresses from network '%s', which is about to %s" 554 " node group '%s', are in use: %s" % 555 (lu.network_name, action, lu.group.name, 556 utils.CommaJoin(("%s: %s" % 557 (name, _FmtNetworkConflict(details))) 558 for (name, details) in conflicts))) 559 560 raise errors.OpPrereqError("Conflicting IP addresses found; " 561 " remove/modify the corresponding network" 562 " interfaces", errors.ECODE_STATE)
563
564 565 -class LUNetworkConnect(LogicalUnit):
566 """Connect a network to a nodegroup 567 568 """ 569 HPATH = "network-connect" 570 HTYPE = constants.HTYPE_NETWORK 571 REQ_BGL = False 572
573 - def ExpandNames(self):
574 self.network_name = self.op.network_name 575 self.group_name = self.op.group_name 576 self.network_mode = self.op.network_mode 577 self.network_link = self.op.network_link 578 579 self.network_uuid = self.cfg.LookupNetwork(self.network_name) 580 self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) 581 582 self.needed_locks = { 583 locking.LEVEL_INSTANCE: [], 584 locking.LEVEL_NODEGROUP: [self.group_uuid], 585 } 586 self.share_locks[locking.LEVEL_INSTANCE] = 1 587 588 if self.op.conflicts_check: 589 self.needed_locks[locking.LEVEL_NETWORK] = [self.network_uuid] 590 self.share_locks[locking.LEVEL_NETWORK] = 1
591
592 - def DeclareLocks(self, level):
593 if level == locking.LEVEL_INSTANCE: 594 assert not self.needed_locks[locking.LEVEL_INSTANCE] 595 596 # Lock instances optimistically, needs verification once group lock has 597 # been acquired 598 if self.op.conflicts_check: 599 self.needed_locks[locking.LEVEL_INSTANCE] = \ 600 self.cfg.GetNodeGroupInstances(self.group_uuid)
601
602 - def BuildHooksEnv(self):
603 ret = { 604 "GROUP_NAME": self.group_name, 605 "GROUP_NETWORK_MODE": self.network_mode, 606 "GROUP_NETWORK_LINK": self.network_link, 607 } 608 return ret
609
610 - def BuildHooksNodes(self):
611 nodes = self.cfg.GetNodeGroup(self.group_uuid).members 612 return (nodes, nodes)
613
614 - def CheckPrereq(self):
615 owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) 616 617 assert self.group_uuid in owned_groups 618 619 # Check if locked instances are still correct 620 owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) 621 if self.op.conflicts_check: 622 CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances) 623 624 self.netparams = { 625 constants.NIC_MODE: self.network_mode, 626 constants.NIC_LINK: self.network_link, 627 } 628 objects.NIC.CheckParameterSyntax(self.netparams) 629 630 self.group = self.cfg.GetNodeGroup(self.group_uuid) 631 #if self.network_mode == constants.NIC_MODE_BRIDGED: 632 # _CheckNodeGroupBridgesExist(self, self.network_link, self.group_uuid) 633 self.connected = False 634 if self.network_uuid in self.group.networks: 635 self.LogWarning("Network '%s' is already mapped to group '%s'" % 636 (self.network_name, self.group.name)) 637 self.connected = True 638 639 # check only if not already connected 640 elif self.op.conflicts_check: 641 pool = network.AddressPool(self.cfg.GetNetwork(self.network_uuid)) 642 643 _NetworkConflictCheck(self, lambda nic: pool.Contains(nic.ip), 644 "connect to", owned_instances)
645
646 - def Exec(self, feedback_fn):
647 # Connect the network and update the group only if not already connected 648 if not self.connected: 649 self.group.networks[self.network_uuid] = self.netparams 650 self.cfg.Update(self.group, feedback_fn)
651
652 653 -class LUNetworkDisconnect(LogicalUnit):
654 """Disconnect a network to a nodegroup 655 656 """ 657 HPATH = "network-disconnect" 658 HTYPE = constants.HTYPE_NETWORK 659 REQ_BGL = False 660
661 - def ExpandNames(self):
662 self.network_name = self.op.network_name 663 self.group_name = self.op.group_name 664 665 self.network_uuid = self.cfg.LookupNetwork(self.network_name) 666 self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) 667 668 self.needed_locks = { 669 locking.LEVEL_INSTANCE: [], 670 locking.LEVEL_NODEGROUP: [self.group_uuid], 671 } 672 self.share_locks[locking.LEVEL_INSTANCE] = 1
673
674 - def DeclareLocks(self, level):
675 if level == locking.LEVEL_INSTANCE: 676 assert not self.needed_locks[locking.LEVEL_INSTANCE] 677 678 # Lock instances optimistically, needs verification once group lock has 679 # been acquired 680 self.needed_locks[locking.LEVEL_INSTANCE] = \ 681 self.cfg.GetNodeGroupInstances(self.group_uuid)
682
683 - def BuildHooksEnv(self):
684 ret = { 685 "GROUP_NAME": self.group_name, 686 } 687 return ret
688
689 - def BuildHooksNodes(self):
690 nodes = self.cfg.GetNodeGroup(self.group_uuid).members 691 return (nodes, nodes)
692
693 - def CheckPrereq(self):
694 owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) 695 696 assert self.group_uuid in owned_groups 697 698 # Check if locked instances are still correct 699 owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) 700 CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances) 701 702 self.group = self.cfg.GetNodeGroup(self.group_uuid) 703 self.connected = True 704 if self.network_uuid not in self.group.networks: 705 self.LogWarning("Network '%s' is not mapped to group '%s'", 706 self.network_name, self.group.name) 707 self.connected = False 708 709 # We need this check only if network is not already connected 710 else: 711 _NetworkConflictCheck(self, lambda nic: nic.network == self.network_uuid, 712 "disconnect from", owned_instances)
713
714 - def Exec(self, feedback_fn):
715 # Disconnect the network and update the group only if network is connected 716 if self.connected: 717 del self.group.networks[self.network_uuid] 718 self.cfg.Update(self.group, feedback_fn)
719