Revision 37dc17e3 lib/cmdlib/__init__.py
b/lib/cmdlib/__init__.py | ||
---|---|---|
66 | 66 |
from ganeti.cmdlib.base import ResultWithJobs, LogicalUnit, NoHooksLU, \ |
67 | 67 |
Tasklet, _QueryBase |
68 | 68 |
from ganeti.cmdlib.common import _ExpandInstanceName, _ExpandItemName, \ |
69 |
_ExpandNodeName, _ShareAll |
|
69 |
_ExpandNodeName, _ShareAll, _CheckNodeGroupInstances
|
|
70 | 70 |
from ganeti.cmdlib.tags import LUTagsGet, LUTagsSearch, LUTagsSet, LUTagsDel |
71 |
from ganeti.cmdlib.network import LUNetworkAdd, LUNetworkRemove, \ |
|
72 |
LUNetworkSetParams, _NetworkQuery, LUNetworkQuery, LUNetworkConnect, \ |
|
73 |
LUNetworkDisconnect |
|
71 | 74 |
|
72 | 75 |
import ganeti.masterd.instance # pylint: disable=W0611 |
73 | 76 |
|
... | ... | |
153 | 156 |
return inst_groups |
154 | 157 |
|
155 | 158 |
|
156 |
def _CheckNodeGroupInstances(cfg, group_uuid, owned_instances): |
|
157 |
"""Checks if the instances in a node group are still correct. |
|
158 |
|
|
159 |
@type cfg: L{config.ConfigWriter} |
|
160 |
@param cfg: The cluster configuration |
|
161 |
@type group_uuid: string |
|
162 |
@param group_uuid: Node group UUID |
|
163 |
@type owned_instances: set or frozenset |
|
164 |
@param owned_instances: List of currently owned instances |
|
165 |
|
|
166 |
""" |
|
167 |
wanted_instances = cfg.GetNodeGroupInstances(group_uuid) |
|
168 |
if owned_instances != wanted_instances: |
|
169 |
raise errors.OpPrereqError("Instances in node group '%s' changed since" |
|
170 |
" locks were acquired, wanted '%s', have '%s';" |
|
171 |
" retry the operation" % |
|
172 |
(group_uuid, |
|
173 |
utils.CommaJoin(wanted_instances), |
|
174 |
utils.CommaJoin(owned_instances)), |
|
175 |
errors.ECODE_STATE) |
|
176 |
|
|
177 |
return wanted_instances |
|
178 |
|
|
179 |
|
|
180 | 159 |
def _SupportsOob(cfg, node): |
181 | 160 |
"""Tells if node supports OOB. |
182 | 161 |
|
... | ... | |
898 | 877 |
_ComputeViolatingInstances(old_ipolicy, instances, cfg)) |
899 | 878 |
|
900 | 879 |
|
901 |
def _BuildNetworkHookEnv(name, subnet, gateway, network6, gateway6, |
|
902 |
mac_prefix, tags): |
|
903 |
"""Builds network related env variables for hooks |
|
904 |
|
|
905 |
This builds the hook environment from individual variables. |
|
906 |
|
|
907 |
@type name: string |
|
908 |
@param name: the name of the network |
|
909 |
@type subnet: string |
|
910 |
@param subnet: the ipv4 subnet |
|
911 |
@type gateway: string |
|
912 |
@param gateway: the ipv4 gateway |
|
913 |
@type network6: string |
|
914 |
@param network6: the ipv6 subnet |
|
915 |
@type gateway6: string |
|
916 |
@param gateway6: the ipv6 gateway |
|
917 |
@type mac_prefix: string |
|
918 |
@param mac_prefix: the mac_prefix |
|
919 |
@type tags: list |
|
920 |
@param tags: the tags of the network |
|
921 |
|
|
922 |
""" |
|
923 |
env = {} |
|
924 |
if name: |
|
925 |
env["NETWORK_NAME"] = name |
|
926 |
if subnet: |
|
927 |
env["NETWORK_SUBNET"] = subnet |
|
928 |
if gateway: |
|
929 |
env["NETWORK_GATEWAY"] = gateway |
|
930 |
if network6: |
|
931 |
env["NETWORK_SUBNET6"] = network6 |
|
932 |
if gateway6: |
|
933 |
env["NETWORK_GATEWAY6"] = gateway6 |
|
934 |
if mac_prefix: |
|
935 |
env["NETWORK_MAC_PREFIX"] = mac_prefix |
|
936 |
if tags: |
|
937 |
env["NETWORK_TAGS"] = " ".join(tags) |
|
938 |
|
|
939 |
return env |
|
940 |
|
|
941 |
|
|
942 | 880 |
def _BuildInstanceHookEnv(name, primary_node, secondary_nodes, os_type, status, |
943 | 881 |
minmem, maxmem, vcpus, nics, disk_template, disks, |
944 | 882 |
bep, hvp, hypervisor_name, tags): |
... | ... | |
15715 | 15653 |
return result |
15716 | 15654 |
|
15717 | 15655 |
|
15718 |
class LUNetworkAdd(LogicalUnit): |
|
15719 |
"""Logical unit for creating networks. |
|
15720 |
|
|
15721 |
""" |
|
15722 |
HPATH = "network-add" |
|
15723 |
HTYPE = constants.HTYPE_NETWORK |
|
15724 |
REQ_BGL = False |
|
15725 |
|
|
15726 |
def BuildHooksNodes(self): |
|
15727 |
"""Build hooks nodes. |
|
15728 |
|
|
15729 |
""" |
|
15730 |
mn = self.cfg.GetMasterNode() |
|
15731 |
return ([mn], [mn]) |
|
15732 |
|
|
15733 |
def CheckArguments(self): |
|
15734 |
if self.op.mac_prefix: |
|
15735 |
self.op.mac_prefix = \ |
|
15736 |
utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix) |
|
15737 |
|
|
15738 |
def ExpandNames(self): |
|
15739 |
self.network_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId()) |
|
15740 |
|
|
15741 |
if self.op.conflicts_check: |
|
15742 |
self.share_locks[locking.LEVEL_NODE] = 1 |
|
15743 |
self.share_locks[locking.LEVEL_NODE_ALLOC] = 1 |
|
15744 |
self.needed_locks = { |
|
15745 |
locking.LEVEL_NODE: locking.ALL_SET, |
|
15746 |
locking.LEVEL_NODE_ALLOC: locking.ALL_SET, |
|
15747 |
} |
|
15748 |
else: |
|
15749 |
self.needed_locks = {} |
|
15750 |
|
|
15751 |
self.add_locks[locking.LEVEL_NETWORK] = self.network_uuid |
|
15752 |
|
|
15753 |
def CheckPrereq(self): |
|
15754 |
if self.op.network is None: |
|
15755 |
raise errors.OpPrereqError("Network must be given", |
|
15756 |
errors.ECODE_INVAL) |
|
15757 |
|
|
15758 |
try: |
|
15759 |
existing_uuid = self.cfg.LookupNetwork(self.op.network_name) |
|
15760 |
except errors.OpPrereqError: |
|
15761 |
pass |
|
15762 |
else: |
|
15763 |
raise errors.OpPrereqError("Desired network name '%s' already exists as a" |
|
15764 |
" network (UUID: %s)" % |
|
15765 |
(self.op.network_name, existing_uuid), |
|
15766 |
errors.ECODE_EXISTS) |
|
15767 |
|
|
15768 |
# Check tag validity |
|
15769 |
for tag in self.op.tags: |
|
15770 |
objects.TaggableObject.ValidateTag(tag) |
|
15771 |
|
|
15772 |
def BuildHooksEnv(self): |
|
15773 |
"""Build hooks env. |
|
15774 |
|
|
15775 |
""" |
|
15776 |
args = { |
|
15777 |
"name": self.op.network_name, |
|
15778 |
"subnet": self.op.network, |
|
15779 |
"gateway": self.op.gateway, |
|
15780 |
"network6": self.op.network6, |
|
15781 |
"gateway6": self.op.gateway6, |
|
15782 |
"mac_prefix": self.op.mac_prefix, |
|
15783 |
"tags": self.op.tags, |
|
15784 |
} |
|
15785 |
return _BuildNetworkHookEnv(**args) # pylint: disable=W0142 |
|
15786 |
|
|
15787 |
def Exec(self, feedback_fn): |
|
15788 |
"""Add the ip pool to the cluster. |
|
15789 |
|
|
15790 |
""" |
|
15791 |
nobj = objects.Network(name=self.op.network_name, |
|
15792 |
network=self.op.network, |
|
15793 |
gateway=self.op.gateway, |
|
15794 |
network6=self.op.network6, |
|
15795 |
gateway6=self.op.gateway6, |
|
15796 |
mac_prefix=self.op.mac_prefix, |
|
15797 |
uuid=self.network_uuid) |
|
15798 |
# Initialize the associated address pool |
|
15799 |
try: |
|
15800 |
pool = network.AddressPool.InitializeNetwork(nobj) |
|
15801 |
except errors.AddressPoolError, err: |
|
15802 |
raise errors.OpExecError("Cannot create IP address pool for network" |
|
15803 |
" '%s': %s" % (self.op.network_name, err)) |
|
15804 |
|
|
15805 |
# Check if we need to reserve the nodes and the cluster master IP |
|
15806 |
# These may not be allocated to any instances in routed mode, as |
|
15807 |
# they wouldn't function anyway. |
|
15808 |
if self.op.conflicts_check: |
|
15809 |
for node in self.cfg.GetAllNodesInfo().values(): |
|
15810 |
for ip in [node.primary_ip, node.secondary_ip]: |
|
15811 |
try: |
|
15812 |
if pool.Contains(ip): |
|
15813 |
pool.Reserve(ip) |
|
15814 |
self.LogInfo("Reserved IP address of node '%s' (%s)", |
|
15815 |
node.name, ip) |
|
15816 |
except errors.AddressPoolError, err: |
|
15817 |
self.LogWarning("Cannot reserve IP address '%s' of node '%s': %s", |
|
15818 |
ip, node.name, err) |
|
15819 |
|
|
15820 |
master_ip = self.cfg.GetClusterInfo().master_ip |
|
15821 |
try: |
|
15822 |
if pool.Contains(master_ip): |
|
15823 |
pool.Reserve(master_ip) |
|
15824 |
self.LogInfo("Reserved cluster master IP address (%s)", master_ip) |
|
15825 |
except errors.AddressPoolError, err: |
|
15826 |
self.LogWarning("Cannot reserve cluster master IP address (%s): %s", |
|
15827 |
master_ip, err) |
|
15828 |
|
|
15829 |
if self.op.add_reserved_ips: |
|
15830 |
for ip in self.op.add_reserved_ips: |
|
15831 |
try: |
|
15832 |
pool.Reserve(ip, external=True) |
|
15833 |
except errors.AddressPoolError, err: |
|
15834 |
raise errors.OpExecError("Cannot reserve IP address '%s': %s" % |
|
15835 |
(ip, err)) |
|
15836 |
|
|
15837 |
if self.op.tags: |
|
15838 |
for tag in self.op.tags: |
|
15839 |
nobj.AddTag(tag) |
|
15840 |
|
|
15841 |
self.cfg.AddNetwork(nobj, self.proc.GetECId(), check_uuid=False) |
|
15842 |
del self.remove_locks[locking.LEVEL_NETWORK] |
|
15843 |
|
|
15844 |
|
|
15845 |
class LUNetworkRemove(LogicalUnit): |
|
15846 |
HPATH = "network-remove" |
|
15847 |
HTYPE = constants.HTYPE_NETWORK |
|
15848 |
REQ_BGL = False |
|
15849 |
|
|
15850 |
def ExpandNames(self): |
|
15851 |
self.network_uuid = self.cfg.LookupNetwork(self.op.network_name) |
|
15852 |
|
|
15853 |
self.share_locks[locking.LEVEL_NODEGROUP] = 1 |
|
15854 |
self.needed_locks = { |
|
15855 |
locking.LEVEL_NETWORK: [self.network_uuid], |
|
15856 |
locking.LEVEL_NODEGROUP: locking.ALL_SET, |
|
15857 |
} |
|
15858 |
|
|
15859 |
def CheckPrereq(self): |
|
15860 |
"""Check prerequisites. |
|
15861 |
|
|
15862 |
This checks that the given network name exists as a network, that is |
|
15863 |
empty (i.e., contains no nodes), and that is not the last group of the |
|
15864 |
cluster. |
|
15865 |
|
|
15866 |
""" |
|
15867 |
# Verify that the network is not conncted. |
|
15868 |
node_groups = [group.name |
|
15869 |
for group in self.cfg.GetAllNodeGroupsInfo().values() |
|
15870 |
if self.network_uuid in group.networks] |
|
15871 |
|
|
15872 |
if node_groups: |
|
15873 |
self.LogWarning("Network '%s' is connected to the following" |
|
15874 |
" node groups: %s" % |
|
15875 |
(self.op.network_name, |
|
15876 |
utils.CommaJoin(utils.NiceSort(node_groups)))) |
|
15877 |
raise errors.OpPrereqError("Network still connected", errors.ECODE_STATE) |
|
15878 |
|
|
15879 |
def BuildHooksEnv(self): |
|
15880 |
"""Build hooks env. |
|
15881 |
|
|
15882 |
""" |
|
15883 |
return { |
|
15884 |
"NETWORK_NAME": self.op.network_name, |
|
15885 |
} |
|
15886 |
|
|
15887 |
def BuildHooksNodes(self): |
|
15888 |
"""Build hooks nodes. |
|
15889 |
|
|
15890 |
""" |
|
15891 |
mn = self.cfg.GetMasterNode() |
|
15892 |
return ([mn], [mn]) |
|
15893 |
|
|
15894 |
def Exec(self, feedback_fn): |
|
15895 |
"""Remove the network. |
|
15896 |
|
|
15897 |
""" |
|
15898 |
try: |
|
15899 |
self.cfg.RemoveNetwork(self.network_uuid) |
|
15900 |
except errors.ConfigurationError: |
|
15901 |
raise errors.OpExecError("Network '%s' with UUID %s disappeared" % |
|
15902 |
(self.op.network_name, self.network_uuid)) |
|
15903 |
|
|
15904 |
|
|
15905 |
class LUNetworkSetParams(LogicalUnit): |
|
15906 |
"""Modifies the parameters of a network. |
|
15907 |
|
|
15908 |
""" |
|
15909 |
HPATH = "network-modify" |
|
15910 |
HTYPE = constants.HTYPE_NETWORK |
|
15911 |
REQ_BGL = False |
|
15912 |
|
|
15913 |
def CheckArguments(self): |
|
15914 |
if (self.op.gateway and |
|
15915 |
(self.op.add_reserved_ips or self.op.remove_reserved_ips)): |
|
15916 |
raise errors.OpPrereqError("Cannot modify gateway and reserved ips" |
|
15917 |
" at once", errors.ECODE_INVAL) |
|
15918 |
|
|
15919 |
def ExpandNames(self): |
|
15920 |
self.network_uuid = self.cfg.LookupNetwork(self.op.network_name) |
|
15921 |
|
|
15922 |
self.needed_locks = { |
|
15923 |
locking.LEVEL_NETWORK: [self.network_uuid], |
|
15924 |
} |
|
15925 |
|
|
15926 |
def CheckPrereq(self): |
|
15927 |
"""Check prerequisites. |
|
15928 |
|
|
15929 |
""" |
|
15930 |
self.network = self.cfg.GetNetwork(self.network_uuid) |
|
15931 |
self.gateway = self.network.gateway |
|
15932 |
self.mac_prefix = self.network.mac_prefix |
|
15933 |
self.network6 = self.network.network6 |
|
15934 |
self.gateway6 = self.network.gateway6 |
|
15935 |
self.tags = self.network.tags |
|
15936 |
|
|
15937 |
self.pool = network.AddressPool(self.network) |
|
15938 |
|
|
15939 |
if self.op.gateway: |
|
15940 |
if self.op.gateway == constants.VALUE_NONE: |
|
15941 |
self.gateway = None |
|
15942 |
else: |
|
15943 |
self.gateway = self.op.gateway |
|
15944 |
if self.pool.IsReserved(self.gateway): |
|
15945 |
raise errors.OpPrereqError("Gateway IP address '%s' is already" |
|
15946 |
" reserved" % self.gateway, |
|
15947 |
errors.ECODE_STATE) |
|
15948 |
|
|
15949 |
if self.op.mac_prefix: |
|
15950 |
if self.op.mac_prefix == constants.VALUE_NONE: |
|
15951 |
self.mac_prefix = None |
|
15952 |
else: |
|
15953 |
self.mac_prefix = \ |
|
15954 |
utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix) |
|
15955 |
|
|
15956 |
if self.op.gateway6: |
|
15957 |
if self.op.gateway6 == constants.VALUE_NONE: |
|
15958 |
self.gateway6 = None |
|
15959 |
else: |
|
15960 |
self.gateway6 = self.op.gateway6 |
|
15961 |
|
|
15962 |
if self.op.network6: |
|
15963 |
if self.op.network6 == constants.VALUE_NONE: |
|
15964 |
self.network6 = None |
|
15965 |
else: |
|
15966 |
self.network6 = self.op.network6 |
|
15967 |
|
|
15968 |
def BuildHooksEnv(self): |
|
15969 |
"""Build hooks env. |
|
15970 |
|
|
15971 |
""" |
|
15972 |
args = { |
|
15973 |
"name": self.op.network_name, |
|
15974 |
"subnet": self.network.network, |
|
15975 |
"gateway": self.gateway, |
|
15976 |
"network6": self.network6, |
|
15977 |
"gateway6": self.gateway6, |
|
15978 |
"mac_prefix": self.mac_prefix, |
|
15979 |
"tags": self.tags, |
|
15980 |
} |
|
15981 |
return _BuildNetworkHookEnv(**args) # pylint: disable=W0142 |
|
15982 |
|
|
15983 |
def BuildHooksNodes(self): |
|
15984 |
"""Build hooks nodes. |
|
15985 |
|
|
15986 |
""" |
|
15987 |
mn = self.cfg.GetMasterNode() |
|
15988 |
return ([mn], [mn]) |
|
15989 |
|
|
15990 |
def Exec(self, feedback_fn): |
|
15991 |
"""Modifies the network. |
|
15992 |
|
|
15993 |
""" |
|
15994 |
#TODO: reserve/release via temporary reservation manager |
|
15995 |
# extend cfg.ReserveIp/ReleaseIp with the external flag |
|
15996 |
if self.op.gateway: |
|
15997 |
if self.gateway == self.network.gateway: |
|
15998 |
self.LogWarning("Gateway is already %s", self.gateway) |
|
15999 |
else: |
|
16000 |
if self.gateway: |
|
16001 |
self.pool.Reserve(self.gateway, external=True) |
|
16002 |
if self.network.gateway: |
|
16003 |
self.pool.Release(self.network.gateway, external=True) |
|
16004 |
self.network.gateway = self.gateway |
|
16005 |
|
|
16006 |
if self.op.add_reserved_ips: |
|
16007 |
for ip in self.op.add_reserved_ips: |
|
16008 |
try: |
|
16009 |
if self.pool.IsReserved(ip): |
|
16010 |
self.LogWarning("IP address %s is already reserved", ip) |
|
16011 |
else: |
|
16012 |
self.pool.Reserve(ip, external=True) |
|
16013 |
except errors.AddressPoolError, err: |
|
16014 |
self.LogWarning("Cannot reserve IP address %s: %s", ip, err) |
|
16015 |
|
|
16016 |
if self.op.remove_reserved_ips: |
|
16017 |
for ip in self.op.remove_reserved_ips: |
|
16018 |
if ip == self.network.gateway: |
|
16019 |
self.LogWarning("Cannot unreserve Gateway's IP") |
|
16020 |
continue |
|
16021 |
try: |
|
16022 |
if not self.pool.IsReserved(ip): |
|
16023 |
self.LogWarning("IP address %s is already unreserved", ip) |
|
16024 |
else: |
|
16025 |
self.pool.Release(ip, external=True) |
|
16026 |
except errors.AddressPoolError, err: |
|
16027 |
self.LogWarning("Cannot release IP address %s: %s", ip, err) |
|
16028 |
|
|
16029 |
if self.op.mac_prefix: |
|
16030 |
self.network.mac_prefix = self.mac_prefix |
|
16031 |
|
|
16032 |
if self.op.network6: |
|
16033 |
self.network.network6 = self.network6 |
|
16034 |
|
|
16035 |
if self.op.gateway6: |
|
16036 |
self.network.gateway6 = self.gateway6 |
|
16037 |
|
|
16038 |
self.pool.Validate() |
|
16039 |
|
|
16040 |
self.cfg.Update(self.network, feedback_fn) |
|
16041 |
|
|
16042 |
|
|
16043 |
class _NetworkQuery(_QueryBase): |
|
16044 |
FIELDS = query.NETWORK_FIELDS |
|
16045 |
|
|
16046 |
def ExpandNames(self, lu): |
|
16047 |
lu.needed_locks = {} |
|
16048 |
lu.share_locks = _ShareAll() |
|
16049 |
|
|
16050 |
self.do_locking = self.use_locking |
|
16051 |
|
|
16052 |
all_networks = lu.cfg.GetAllNetworksInfo() |
|
16053 |
name_to_uuid = dict((n.name, n.uuid) for n in all_networks.values()) |
|
16054 |
|
|
16055 |
if self.names: |
|
16056 |
missing = [] |
|
16057 |
self.wanted = [] |
|
16058 |
|
|
16059 |
for name in self.names: |
|
16060 |
if name in name_to_uuid: |
|
16061 |
self.wanted.append(name_to_uuid[name]) |
|
16062 |
else: |
|
16063 |
missing.append(name) |
|
16064 |
|
|
16065 |
if missing: |
|
16066 |
raise errors.OpPrereqError("Some networks do not exist: %s" % missing, |
|
16067 |
errors.ECODE_NOENT) |
|
16068 |
else: |
|
16069 |
self.wanted = locking.ALL_SET |
|
16070 |
|
|
16071 |
if self.do_locking: |
|
16072 |
lu.needed_locks[locking.LEVEL_NETWORK] = self.wanted |
|
16073 |
if query.NETQ_INST in self.requested_data: |
|
16074 |
lu.needed_locks[locking.LEVEL_INSTANCE] = locking.ALL_SET |
|
16075 |
if query.NETQ_GROUP in self.requested_data: |
|
16076 |
lu.needed_locks[locking.LEVEL_NODEGROUP] = locking.ALL_SET |
|
16077 |
|
|
16078 |
def DeclareLocks(self, lu, level): |
|
16079 |
pass |
|
16080 |
|
|
16081 |
def _GetQueryData(self, lu): |
|
16082 |
"""Computes the list of networks and their attributes. |
|
16083 |
|
|
16084 |
""" |
|
16085 |
all_networks = lu.cfg.GetAllNetworksInfo() |
|
16086 |
|
|
16087 |
network_uuids = self._GetNames(lu, all_networks.keys(), |
|
16088 |
locking.LEVEL_NETWORK) |
|
16089 |
|
|
16090 |
do_instances = query.NETQ_INST in self.requested_data |
|
16091 |
do_groups = query.NETQ_GROUP in self.requested_data |
|
16092 |
|
|
16093 |
network_to_instances = None |
|
16094 |
network_to_groups = None |
|
16095 |
|
|
16096 |
# For NETQ_GROUP, we need to map network->[groups] |
|
16097 |
if do_groups: |
|
16098 |
all_groups = lu.cfg.GetAllNodeGroupsInfo() |
|
16099 |
network_to_groups = dict((uuid, []) for uuid in network_uuids) |
|
16100 |
for _, group in all_groups.iteritems(): |
|
16101 |
for net_uuid in network_uuids: |
|
16102 |
netparams = group.networks.get(net_uuid, None) |
|
16103 |
if netparams: |
|
16104 |
info = (group.name, netparams[constants.NIC_MODE], |
|
16105 |
netparams[constants.NIC_LINK]) |
|
16106 |
|
|
16107 |
network_to_groups[net_uuid].append(info) |
|
16108 |
|
|
16109 |
if do_instances: |
|
16110 |
all_instances = lu.cfg.GetAllInstancesInfo() |
|
16111 |
network_to_instances = dict((uuid, []) for uuid in network_uuids) |
|
16112 |
for instance in all_instances.values(): |
|
16113 |
for nic in instance.nics: |
|
16114 |
if nic.network in network_uuids: |
|
16115 |
network_to_instances[nic.network].append(instance.name) |
|
16116 |
break |
|
16117 |
|
|
16118 |
if query.NETQ_STATS in self.requested_data: |
|
16119 |
stats = \ |
|
16120 |
dict((uuid, |
|
16121 |
self._GetStats(network.AddressPool(all_networks[uuid]))) |
|
16122 |
for uuid in network_uuids) |
|
16123 |
else: |
|
16124 |
stats = None |
|
16125 |
|
|
16126 |
return query.NetworkQueryData([all_networks[uuid] |
|
16127 |
for uuid in network_uuids], |
|
16128 |
network_to_groups, |
|
16129 |
network_to_instances, |
|
16130 |
stats) |
|
16131 |
|
|
16132 |
@staticmethod |
|
16133 |
def _GetStats(pool): |
|
16134 |
"""Returns statistics for a network address pool. |
|
16135 |
|
|
16136 |
""" |
|
16137 |
return { |
|
16138 |
"free_count": pool.GetFreeCount(), |
|
16139 |
"reserved_count": pool.GetReservedCount(), |
|
16140 |
"map": pool.GetMap(), |
|
16141 |
"external_reservations": |
|
16142 |
utils.CommaJoin(pool.GetExternalReservations()), |
|
16143 |
} |
|
16144 |
|
|
16145 |
|
|
16146 |
class LUNetworkQuery(NoHooksLU): |
|
16147 |
"""Logical unit for querying networks. |
|
16148 |
|
|
16149 |
""" |
|
16150 |
REQ_BGL = False |
|
16151 |
|
|
16152 |
def CheckArguments(self): |
|
16153 |
self.nq = _NetworkQuery(qlang.MakeSimpleFilter("name", self.op.names), |
|
16154 |
self.op.output_fields, self.op.use_locking) |
|
16155 |
|
|
16156 |
def ExpandNames(self): |
|
16157 |
self.nq.ExpandNames(self) |
|
16158 |
|
|
16159 |
def Exec(self, feedback_fn): |
|
16160 |
return self.nq.OldStyleQuery(self) |
|
16161 |
|
|
16162 |
|
|
16163 |
class LUNetworkConnect(LogicalUnit): |
|
16164 |
"""Connect a network to a nodegroup |
|
16165 |
|
|
16166 |
""" |
|
16167 |
HPATH = "network-connect" |
|
16168 |
HTYPE = constants.HTYPE_NETWORK |
|
16169 |
REQ_BGL = False |
|
16170 |
|
|
16171 |
def ExpandNames(self): |
|
16172 |
self.network_name = self.op.network_name |
|
16173 |
self.group_name = self.op.group_name |
|
16174 |
self.network_mode = self.op.network_mode |
|
16175 |
self.network_link = self.op.network_link |
|
16176 |
|
|
16177 |
self.network_uuid = self.cfg.LookupNetwork(self.network_name) |
|
16178 |
self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) |
|
16179 |
|
|
16180 |
self.needed_locks = { |
|
16181 |
locking.LEVEL_INSTANCE: [], |
|
16182 |
locking.LEVEL_NODEGROUP: [self.group_uuid], |
|
16183 |
} |
|
16184 |
self.share_locks[locking.LEVEL_INSTANCE] = 1 |
|
16185 |
|
|
16186 |
if self.op.conflicts_check: |
|
16187 |
self.needed_locks[locking.LEVEL_NETWORK] = [self.network_uuid] |
|
16188 |
self.share_locks[locking.LEVEL_NETWORK] = 1 |
|
16189 |
|
|
16190 |
def DeclareLocks(self, level): |
|
16191 |
if level == locking.LEVEL_INSTANCE: |
|
16192 |
assert not self.needed_locks[locking.LEVEL_INSTANCE] |
|
16193 |
|
|
16194 |
# Lock instances optimistically, needs verification once group lock has |
|
16195 |
# been acquired |
|
16196 |
if self.op.conflicts_check: |
|
16197 |
self.needed_locks[locking.LEVEL_INSTANCE] = \ |
|
16198 |
self.cfg.GetNodeGroupInstances(self.group_uuid) |
|
16199 |
|
|
16200 |
def BuildHooksEnv(self): |
|
16201 |
ret = { |
|
16202 |
"GROUP_NAME": self.group_name, |
|
16203 |
"GROUP_NETWORK_MODE": self.network_mode, |
|
16204 |
"GROUP_NETWORK_LINK": self.network_link, |
|
16205 |
} |
|
16206 |
return ret |
|
16207 |
|
|
16208 |
def BuildHooksNodes(self): |
|
16209 |
nodes = self.cfg.GetNodeGroup(self.group_uuid).members |
|
16210 |
return (nodes, nodes) |
|
16211 |
|
|
16212 |
def CheckPrereq(self): |
|
16213 |
owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) |
|
16214 |
|
|
16215 |
assert self.group_uuid in owned_groups |
|
16216 |
|
|
16217 |
# Check if locked instances are still correct |
|
16218 |
owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) |
|
16219 |
if self.op.conflicts_check: |
|
16220 |
_CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances) |
|
16221 |
|
|
16222 |
self.netparams = { |
|
16223 |
constants.NIC_MODE: self.network_mode, |
|
16224 |
constants.NIC_LINK: self.network_link, |
|
16225 |
} |
|
16226 |
objects.NIC.CheckParameterSyntax(self.netparams) |
|
16227 |
|
|
16228 |
self.group = self.cfg.GetNodeGroup(self.group_uuid) |
|
16229 |
#if self.network_mode == constants.NIC_MODE_BRIDGED: |
|
16230 |
# _CheckNodeGroupBridgesExist(self, self.network_link, self.group_uuid) |
|
16231 |
self.connected = False |
|
16232 |
if self.network_uuid in self.group.networks: |
|
16233 |
self.LogWarning("Network '%s' is already mapped to group '%s'" % |
|
16234 |
(self.network_name, self.group.name)) |
|
16235 |
self.connected = True |
|
16236 |
|
|
16237 |
# check only if not already connected |
|
16238 |
elif self.op.conflicts_check: |
|
16239 |
pool = network.AddressPool(self.cfg.GetNetwork(self.network_uuid)) |
|
16240 |
|
|
16241 |
_NetworkConflictCheck(self, lambda nic: pool.Contains(nic.ip), |
|
16242 |
"connect to", owned_instances) |
|
16243 |
|
|
16244 |
def Exec(self, feedback_fn): |
|
16245 |
# Connect the network and update the group only if not already connected |
|
16246 |
if not self.connected: |
|
16247 |
self.group.networks[self.network_uuid] = self.netparams |
|
16248 |
self.cfg.Update(self.group, feedback_fn) |
|
16249 |
|
|
16250 |
|
|
16251 |
def _NetworkConflictCheck(lu, check_fn, action, instances): |
|
16252 |
"""Checks for network interface conflicts with a network. |
|
16253 |
|
|
16254 |
@type lu: L{LogicalUnit} |
|
16255 |
@type check_fn: callable receiving one parameter (L{objects.NIC}) and |
|
16256 |
returning boolean |
|
16257 |
@param check_fn: Function checking for conflict |
|
16258 |
@type action: string |
|
16259 |
@param action: Part of error message (see code) |
|
16260 |
@raise errors.OpPrereqError: If conflicting IP addresses are found. |
|
16261 |
|
|
16262 |
""" |
|
16263 |
conflicts = [] |
|
16264 |
|
|
16265 |
for (_, instance) in lu.cfg.GetMultiInstanceInfo(instances): |
|
16266 |
instconflicts = [(idx, nic.ip) |
|
16267 |
for (idx, nic) in enumerate(instance.nics) |
|
16268 |
if check_fn(nic)] |
|
16269 |
|
|
16270 |
if instconflicts: |
|
16271 |
conflicts.append((instance.name, instconflicts)) |
|
16272 |
|
|
16273 |
if conflicts: |
|
16274 |
lu.LogWarning("IP addresses from network '%s', which is about to %s" |
|
16275 |
" node group '%s', are in use: %s" % |
|
16276 |
(lu.network_name, action, lu.group.name, |
|
16277 |
utils.CommaJoin(("%s: %s" % |
|
16278 |
(name, _FmtNetworkConflict(details))) |
|
16279 |
for (name, details) in conflicts))) |
|
16280 |
|
|
16281 |
raise errors.OpPrereqError("Conflicting IP addresses found; " |
|
16282 |
" remove/modify the corresponding network" |
|
16283 |
" interfaces", errors.ECODE_STATE) |
|
16284 |
|
|
16285 |
|
|
16286 |
def _FmtNetworkConflict(details): |
|
16287 |
"""Utility for L{_NetworkConflictCheck}. |
|
16288 |
|
|
16289 |
""" |
|
16290 |
return utils.CommaJoin("nic%s/%s" % (idx, ipaddr) |
|
16291 |
for (idx, ipaddr) in details) |
|
16292 |
|
|
16293 |
|
|
16294 |
class LUNetworkDisconnect(LogicalUnit): |
|
16295 |
"""Disconnect a network to a nodegroup |
|
16296 |
|
|
16297 |
""" |
|
16298 |
HPATH = "network-disconnect" |
|
16299 |
HTYPE = constants.HTYPE_NETWORK |
|
16300 |
REQ_BGL = False |
|
16301 |
|
|
16302 |
def ExpandNames(self): |
|
16303 |
self.network_name = self.op.network_name |
|
16304 |
self.group_name = self.op.group_name |
|
16305 |
|
|
16306 |
self.network_uuid = self.cfg.LookupNetwork(self.network_name) |
|
16307 |
self.group_uuid = self.cfg.LookupNodeGroup(self.group_name) |
|
16308 |
|
|
16309 |
self.needed_locks = { |
|
16310 |
locking.LEVEL_INSTANCE: [], |
|
16311 |
locking.LEVEL_NODEGROUP: [self.group_uuid], |
|
16312 |
} |
|
16313 |
self.share_locks[locking.LEVEL_INSTANCE] = 1 |
|
16314 |
|
|
16315 |
def DeclareLocks(self, level): |
|
16316 |
if level == locking.LEVEL_INSTANCE: |
|
16317 |
assert not self.needed_locks[locking.LEVEL_INSTANCE] |
|
16318 |
|
|
16319 |
# Lock instances optimistically, needs verification once group lock has |
|
16320 |
# been acquired |
|
16321 |
self.needed_locks[locking.LEVEL_INSTANCE] = \ |
|
16322 |
self.cfg.GetNodeGroupInstances(self.group_uuid) |
|
16323 |
|
|
16324 |
def BuildHooksEnv(self): |
|
16325 |
ret = { |
|
16326 |
"GROUP_NAME": self.group_name, |
|
16327 |
} |
|
16328 |
return ret |
|
16329 |
|
|
16330 |
def BuildHooksNodes(self): |
|
16331 |
nodes = self.cfg.GetNodeGroup(self.group_uuid).members |
|
16332 |
return (nodes, nodes) |
|
16333 |
|
|
16334 |
def CheckPrereq(self): |
|
16335 |
owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP)) |
|
16336 |
|
|
16337 |
assert self.group_uuid in owned_groups |
|
16338 |
|
|
16339 |
# Check if locked instances are still correct |
|
16340 |
owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE)) |
|
16341 |
_CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances) |
|
16342 |
|
|
16343 |
self.group = self.cfg.GetNodeGroup(self.group_uuid) |
|
16344 |
self.connected = True |
|
16345 |
if self.network_uuid not in self.group.networks: |
|
16346 |
self.LogWarning("Network '%s' is not mapped to group '%s'", |
|
16347 |
self.network_name, self.group.name) |
|
16348 |
self.connected = False |
|
16349 |
|
|
16350 |
# We need this check only if network is not already connected |
|
16351 |
else: |
|
16352 |
_NetworkConflictCheck(self, lambda nic: nic.network == self.network_uuid, |
|
16353 |
"disconnect from", owned_instances) |
|
16354 |
|
|
16355 |
def Exec(self, feedback_fn): |
|
16356 |
# Disconnect the network and update the group only if network is connected |
|
16357 |
if self.connected: |
|
16358 |
del self.group.networks[self.network_uuid] |
|
16359 |
self.cfg.Update(self.group, feedback_fn) |
|
16360 |
|
|
16361 |
|
|
16362 | 15656 |
#: Query type implementations |
16363 | 15657 |
_QUERY_IMPL = { |
16364 | 15658 |
constants.QR_CLUSTER: _ClusterQuery, |
Also available in: Unified diff