1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 """IP pool related commands"""
31
32
33
34
35
36 import textwrap
37 import itertools
38
39 from ganeti.cli import *
40 from ganeti import constants
41 from ganeti import opcodes
42 from ganeti import utils
43 from ganeti import errors
44 from ganeti import objects
45
46
47
48 _LIST_DEF_FIELDS = ["name", "network", "gateway",
49 "mac_prefix", "group_list", "tags"]
50
51
53 if ips is None:
54 return None
55 elif not ips:
56 return []
57 else:
58 return utils.UnescapeAndSplit(ips, sep=",")
59
60
62 """Add a network to the cluster.
63
64 @param opts: the command line options selected by the user
65 @type args: list
66 @param args: a list of length 1 with the network name to create
67 @rtype: int
68 @return: the desired exit code
69
70 """
71 (network_name, ) = args
72
73 if opts.network is None:
74 raise errors.OpPrereqError("The --network option must be given",
75 errors.ECODE_INVAL)
76
77 if opts.tags is not None:
78 tags = opts.tags.split(",")
79 else:
80 tags = []
81
82 reserved_ips = _HandleReservedIPs(opts.add_reserved_ips)
83
84 op = opcodes.OpNetworkAdd(network_name=network_name,
85 gateway=opts.gateway,
86 network=opts.network,
87 gateway6=opts.gateway6,
88 network6=opts.network6,
89 mac_prefix=opts.mac_prefix,
90 add_reserved_ips=reserved_ips,
91 conflicts_check=opts.conflicts_check,
92 tags=tags)
93 SubmitOrSend(op, opts)
94
95
97 """Gets list of groups to operate on.
98
99 If C{groups} doesn't contain groups, a list of all groups in the cluster is
100 returned.
101
102 @type cl: L{luxi.Client}
103 @type groups: list
104 @rtype: list
105
106 """
107 if groups:
108 return groups
109
110 return list(itertools.chain(*cl.QueryGroups([], ["uuid"], False)))
111
112
114 """Map a network to a node group.
115
116 @param opts: the command line options selected by the user
117 @type args: list
118 @param args: Network, mode, physlink and node groups
119 @rtype: int
120 @return: the desired exit code
121
122 """
123 cl = GetClient()
124
125 network = args[0]
126 nicparams = objects.FillDict(constants.NICC_DEFAULTS, opts.nicparams)
127
128 groups = _GetDefaultGroups(cl, args[1:])
129
130
131 for group in groups:
132 op = opcodes.OpNetworkConnect(group_name=group,
133 network_name=network,
134 network_mode=nicparams[constants.NIC_MODE],
135 network_link=nicparams[constants.NIC_LINK],
136 network_vlan=nicparams[constants.NIC_VLAN],
137 conflicts_check=opts.conflicts_check)
138 SubmitOpCode(op, opts=opts, cl=cl)
139
140
142 """Unmap a network from a node group.
143
144 @param opts: the command line options selected by the user
145 @type args: list
146 @param args: Network and node groups
147 @rtype: int
148 @return: the desired exit code
149
150 """
151 cl = GetClient()
152
153 (network, ) = args[:1]
154 groups = _GetDefaultGroups(cl, args[1:])
155
156
157 for group in groups:
158 op = opcodes.OpNetworkDisconnect(group_name=group,
159 network_name=network)
160 SubmitOpCode(op, opts=opts, cl=cl)
161
162
164 """List Ip pools and their properties.
165
166 @param opts: the command line options selected by the user
167 @type args: list
168 @param args: networks to list, or empty for all
169 @rtype: int
170 @return: the desired exit code
171
172 """
173 desired_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
174 fmtoverride = {
175 "group_list":
176 (lambda data:
177 utils.CommaJoin("%s (%s, %s, %s)" % (name, mode, link, vlan)
178 for (name, mode, link, vlan) in data),
179 False),
180 "inst_list": (",".join, False),
181 "tags": (",".join, False),
182 }
183
184 cl = GetClient()
185 return GenericList(constants.QR_NETWORK, desired_fields, args, None,
186 opts.separator, not opts.no_headers,
187 verbose=opts.verbose, format_override=fmtoverride,
188 cl=cl)
189
190
192 """List network fields.
193
194 @param opts: the command line options selected by the user
195 @type args: list
196 @param args: fields to list, or empty for all
197 @rtype: int
198 @return: the desired exit code
199
200 """
201 cl = GetClient()
202
203 return GenericListFields(constants.QR_NETWORK, args, opts.separator,
204 not opts.no_headers, cl=cl)
205
206
208 """Show network information.
209
210 @type args: list
211 @param args: should either be an empty list, in which case
212 we show information about all nodes, or should contain
213 a list of networks (names or UUIDs) to be queried for information
214 @rtype: int
215 @return: the desired exit code
216
217 """
218 cl = GetClient()
219 result = cl.QueryNetworks(fields=["name", "network", "gateway",
220 "network6", "gateway6",
221 "mac_prefix",
222 "free_count", "reserved_count",
223 "map", "group_list", "inst_list",
224 "external_reservations",
225 "serial_no", "uuid"],
226 names=args, use_locking=False)
227
228 for (name, network, gateway, network6, gateway6,
229 mac_prefix, free_count, reserved_count,
230 mapping, group_list, instances, ext_res, serial, uuid) in result:
231 size = free_count + reserved_count
232 ToStdout("Network name: %s", name)
233 ToStdout("UUID: %s", uuid)
234 ToStdout("Serial number: %d", serial)
235 ToStdout(" Subnet: %s", network)
236 ToStdout(" Gateway: %s", gateway)
237 ToStdout(" IPv6 Subnet: %s", network6)
238 ToStdout(" IPv6 Gateway: %s", gateway6)
239 ToStdout(" Mac Prefix: %s", mac_prefix)
240 ToStdout(" Size: %d", size)
241 ToStdout(" Free: %d (%.2f%%)", free_count,
242 100 * float(free_count) / float(size))
243 ToStdout(" Usage map:")
244 lenmapping = len(mapping)
245 idx = 0
246 while idx < lenmapping:
247 line = mapping[idx: idx + 64]
248 ToStdout(" %s %s %d", str(idx).rjust(4), line.ljust(64), idx + 63)
249 idx += 64
250 ToStdout(" (X) used (.) free")
251
252 if ext_res:
253 ToStdout(" externally reserved IPs:")
254 for line in textwrap.wrap(ext_res, width=64):
255 ToStdout(" %s" % line)
256
257 if group_list:
258 ToStdout(" connected to node groups:")
259 for group, nic_mode, nic_link, nic_vlan in group_list:
260 ToStdout(" %s (mode:%s link:%s vlan:%s)",
261 group, nic_mode, nic_link, nic_vlan)
262 else:
263 ToStdout(" not connected to any node group")
264
265 if instances:
266 ToStdout(" used by %d instances:", len(instances))
267 for name in instances:
268 ((ips, networks), ) = cl.QueryInstances([name],
269 ["nic.ips", "nic.networks"],
270 use_locking=False)
271
272 l = lambda value: ", ".join(str(idx) + ":" + str(ip)
273 for idx, (ip, net) in enumerate(value)
274 if net == uuid)
275
276 ToStdout(" %s: %s", name, l(zip(ips, networks)))
277 else:
278 ToStdout(" not used by any instances")
279
280
282 """Modifies an IP address pool's parameters.
283
284 @param opts: the command line options selected by the user
285 @type args: list
286 @param args: should contain only one element, the node group name
287
288 @rtype: int
289 @return: the desired exit code
290
291 """
292
293 all_changes = {
294 "gateway": opts.gateway,
295 "add_reserved_ips": _HandleReservedIPs(opts.add_reserved_ips),
296 "remove_reserved_ips": _HandleReservedIPs(opts.remove_reserved_ips),
297 "mac_prefix": opts.mac_prefix,
298 "gateway6": opts.gateway6,
299 "network6": opts.network6,
300 }
301
302 if all_changes.values().count(None) == len(all_changes):
303 ToStderr("Please give at least one of the parameters.")
304 return 1
305
306
307 op = opcodes.OpNetworkSetParams(network_name=args[0], **all_changes)
308
309
310 SubmitOrSend(op, opts)
311
312
314 """Remove an IP address pool from the cluster.
315
316 @param opts: the command line options selected by the user
317 @type args: list
318 @param args: a list of length 1 with the id of the IP address pool to remove
319 @rtype: int
320 @return: the desired exit code
321
322 """
323 (network_name,) = args
324 op = opcodes.OpNetworkRemove(network_name=network_name, force=opts.force)
325 SubmitOrSend(op, opts)
326
327
328 commands = {
329 "add": (
330 AddNetwork, ARGS_ONE_NETWORK,
331 [DRY_RUN_OPT, NETWORK_OPT, GATEWAY_OPT, ADD_RESERVED_IPS_OPT,
332 MAC_PREFIX_OPT, NETWORK6_OPT, GATEWAY6_OPT,
333 NOCONFLICTSCHECK_OPT, TAG_ADD_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
334 "<network_name>", "Add a new IP network to the cluster"),
335 "list": (
336 ListNetworks, ARGS_MANY_NETWORKS,
337 [NOHDR_OPT, SEP_OPT, FIELDS_OPT, VERBOSE_OPT],
338 "[<network_id>...]",
339 "Lists the IP networks in the cluster. The available fields can be shown"
340 " using the \"list-fields\" command (see the man page for details)."
341 " The default list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)),
342 "list-fields": (
343 ListNetworkFields, [ArgUnknown()], [NOHDR_OPT, SEP_OPT], "[fields...]",
344 "Lists all available fields for networks"),
345 "info": (
346 ShowNetworkConfig, ARGS_MANY_NETWORKS, [],
347 "[<network_name>...]", "Show information about the network(s)"),
348 "modify": (
349 SetNetworkParams, ARGS_ONE_NETWORK,
350 [DRY_RUN_OPT] + SUBMIT_OPTS +
351 [ADD_RESERVED_IPS_OPT,
352 REMOVE_RESERVED_IPS_OPT, GATEWAY_OPT, MAC_PREFIX_OPT, NETWORK6_OPT,
353 GATEWAY6_OPT, PRIORITY_OPT],
354 "<network_name>", "Alters the parameters of a network"),
355 "connect": (
356 ConnectNetwork,
357 [ArgNetwork(min=1, max=1),
358 ArgGroup()],
359 [NOCONFLICTSCHECK_OPT, PRIORITY_OPT, NIC_PARAMS_OPT],
360 "<network_name> [<node_group>...]",
361 "Map a given network to the specified node group"
362 " with given mode and link (netparams)"),
363 "disconnect": (
364 DisconnectNetwork,
365 [ArgNetwork(min=1, max=1), ArgGroup()],
366 [PRIORITY_OPT],
367 "<network_name> [<node_group>...]",
368 "Unmap a given network from a specified node group"),
369 "remove": (
370 RemoveNetwork, ARGS_ONE_NETWORK,
371 [FORCE_OPT, DRY_RUN_OPT] + SUBMIT_OPTS + [PRIORITY_OPT],
372 "[--dry-run] <network_id>",
373 "Remove an (empty) network from the cluster"),
374 "list-tags": (
375 ListTags, ARGS_ONE_NETWORK, [],
376 "<network_name>", "List the tags of the given network"),
377 "add-tags": (
378 AddTags, [ArgNetwork(min=1, max=1), ArgUnknown()],
379 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
380 "<network_name> tag...", "Add tags to the given network"),
381 "remove-tags": (
382 RemoveTags, [ArgNetwork(min=1, max=1), ArgUnknown()],
383 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
384 "<network_name> tag...", "Remove tags from given network"),
385 }
386
387
389 return GenericMain(commands, override={"tag_type": constants.TAG_NETWORK})
390