Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_network.py @ eba5b011

History | View | Annotate | Download (10.6 kB)

1
#
2
#
3

    
4
# Copyright (C) 2011 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
"""IP pool related commands"""
22

    
23
# pylint: disable=W0401,W0614
24
# W0401: Wildcard import ganeti.cli
25
# W0614: Unused import %s from wildcard import (since we need cli)
26

    
27
from ganeti.cli import *
28
from ganeti import constants
29
from ganeti import opcodes
30
from ganeti import utils
31
from textwrap import wrap
32

    
33

    
34
#: default list of fields for L{ListNetworks}
35
_LIST_DEF_FIELDS = ["name", "network", "gateway",
36
                    "network_type", "mac_prefix", "group_list"]
37

    
38

    
39
def _HandleReservedIPs(ips):
40
  if ips is not None:
41
    if ips == "":
42
      return []
43
    else:
44
      return utils.UnescapeAndSplit(ips, sep=",")
45
  return None
46

    
47

    
48
def AddNetwork(opts, args):
49
  """Add a network to the cluster.
50

51
  @param opts: the command line options selected by the user
52
  @type args: list
53
  @param args: a list of length 1 with the network name to create
54
  @rtype: int
55
  @return: the desired exit code
56

57
  """
58
  (network_name, ) = args
59

    
60
  op = opcodes.OpNetworkAdd(
61
                    network_name=network_name,
62
                    gateway=opts.gateway,
63
                    network=opts.network,
64
                    gateway6=opts.gateway6,
65
                    network6=opts.network6,
66
                    mac_prefix=opts.mac_prefix,
67
                    network_type=opts.network_type,
68
                    add_reserved_ips=_HandleReservedIPs(opts.add_reserved_ips),
69
                    conflicts_check=opts.conflicts_check)
70
  SubmitOpCode(op, opts=opts)
71

    
72

    
73
def MapNetwork(opts, args):
74
  """Map a network to a node group.
75

76
  @param opts: the command line options selected by the user
77
  @type args: list
78
  @param args: a list of length 3 with network, nodegroup, mode, physlink
79
  @rtype: int
80
  @return: the desired exit code
81

82
  """
83
  network = args[0]
84
  groups = args[1]
85
  mode = args[2]
86
  link = args[3]
87

    
88
  #TODO: allow comma separated group names
89
  if groups == 'all':
90
    cl = GetClient()
91
    (groups, ) = cl.QueryGroups([], ['name'], False)
92
  else:
93
    groups = [groups]
94

    
95
  for group in groups:
96
    op = opcodes.OpNetworkConnect(group_name=group,
97
                                  network_name=network,
98
                                  network_mode=mode,
99
                                  network_link=link,
100
                                  conflicts_check=opts.conflicts_check)
101
    SubmitOpCode(op, opts=opts)
102

    
103

    
104
def UnmapNetwork(opts, args):
105
  """Unmap a network from a node group.
106

107
  @param opts: the command line options selected by the user
108
  @type args: list
109
  @param args: a list of length 3 with network, nodegorup
110
  @rtype: int
111
  @return: the desired exit code
112

113
  """
114
  network = args[0]
115
  groups = args[1]
116

    
117
  #TODO: allow comma separated group names
118
  if groups == 'all':
119
    cl = GetClient()
120
    (groups, ) = cl.QueryGroups([], ['name'], False)
121
  else:
122
    groups = [groups]
123

    
124
  for group in groups:
125
    op = opcodes.OpNetworkDisconnect(group_name=group,
126
                                     network_name=network,
127
                                     conflicts_check=opts.conflicts_check)
128
    SubmitOpCode(op, opts=opts)
129

    
130

    
131
def ListNetworks(opts, args):
132
  """List Ip pools and their properties.
133

134
  @param opts: the command line options selected by the user
135
  @type args: list
136
  @param args: networks to list, or empty for all
137
  @rtype: int
138
  @return: the desired exit code
139

140
  """
141
  desired_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
142
  fmtoverride = {
143
    "group_list": (",".join, False),
144
    "inst_list": (",".join, False),
145
  }
146

    
147
  return GenericList(constants.QR_NETWORK, desired_fields, args, None,
148
                     opts.separator, not opts.no_headers,
149
                     verbose=opts.verbose, format_override=fmtoverride)
150

    
151

    
152
def ListNetworkFields(opts, args):
153
  """List network fields.
154

155
  @param opts: the command line options selected by the user
156
  @type args: list
157
  @param args: fields to list, or empty for all
158
  @rtype: int
159
  @return: the desired exit code
160

161
  """
162
  return GenericListFields(constants.QR_NETWORK, args, opts.separator,
163
                           not opts.no_headers)
164

    
165

    
166
def ShowNetworkConfig(_, args):
167
  """Show network information.
168

169
  @type args: list
170
  @param args: should either be an empty list, in which case
171
      we show information about all nodes, or should contain
172
      a list of networks (names or UUIDs) to be queried for information
173
  @rtype: int
174
  @return: the desired exit code
175

176
  """
177
  cl = GetClient()
178
  result = cl.QueryNetworks(fields=["name", "network", "gateway",
179
                                    "network6", "gateway6",
180
                                    "mac_prefix", "network_type",
181
                                    "free_count", "reserved_count",
182
                                    "map", "group_list", "inst_list",
183
                                    "external_reservations",
184
                                    "serial_no", "uuid"],
185
                            names=args, use_locking=False)
186

    
187
  for (name, network, gateway, network6, gateway6,
188
       mac_prefix, network_type, free_count, reserved_count,
189
       mapping, group_list, instances, ext_res, serial, uuid) in result:
190
    size = free_count + reserved_count
191
    ToStdout("Network name: %s", name)
192
    ToStdout("UUID: %s", uuid)
193
    ToStdout("Serial number: %d", serial)
194
    ToStdout("  Subnet: %s", network)
195
    ToStdout("  Gateway: %s", gateway)
196
    ToStdout("  IPv6 Subnet: %s", network6)
197
    ToStdout("  IPv6 Gateway: %s", gateway6)
198
    ToStdout("  Mac Prefix: %s", mac_prefix)
199
    ToStdout("  Type: %s", network_type)
200
    ToStdout("  Size: %d", size)
201
    ToStdout("  Free: %d (%.2f%%)", free_count,
202
             100 * float(free_count)/float(size))
203
    ToStdout("  Usage map:")
204
    idx = 0
205
    for line in wrap(mapping, width=64):
206
      ToStdout("     %s %s %d", str(idx).rjust(3), line.ljust(64), idx + 63)
207
      idx += 64
208
    ToStdout("         (X) used    (.) free")
209

    
210
    if ext_res:
211
      ToStdout("  externally reserved IPs:")
212
      for line in wrap(ext_res, width=64):
213
        ToStdout("    %s" % line)
214

    
215
    if group_list:
216
      ToStdout("  connected to node groups:")
217
      for group in group_list:
218
        ToStdout("    %s", group)
219
    else:
220
      ToStdout("  not connected to any node group")
221

    
222
    if instances:
223
      ToStdout("  used by %d instances:", len(instances))
224
      for inst in instances:
225
        ((ips, networks), ) = cl.QueryInstances([inst],
226
                                                ["nic.ips", "nic.networks"],
227
                                                use_locking=False)
228

    
229
        l = lambda value: ", ".join(str(idx) + ":" + str(ip)
230
                                    for idx, (ip, net) in enumerate(value)
231
                                      if net == name)
232

    
233
        ToStdout("    %s : %s", inst, l(zip(ips, networks)))
234
    else:
235
      ToStdout("  not used by any instances")
236

    
237

    
238
def SetNetworkParams(opts, args):
239
  """Modifies an IP address pool's parameters.
240

241
  @param opts: the command line options selected by the user
242
  @type args: list
243
  @param args: should contain only one element, the node group name
244

245
  @rtype: int
246
  @return: the desired exit code
247

248
  """
249

    
250
  # TODO: add "network": opts.network,
251
  all_changes = {
252
    "gateway": opts.gateway,
253
    "add_reserved_ips": _HandleReservedIPs(opts.add_reserved_ips),
254
    "remove_reserved_ips": _HandleReservedIPs(opts.remove_reserved_ips),
255
    "mac_prefix": opts.mac_prefix,
256
    "network_type": opts.network_type,
257
    "gateway6": opts.gateway6,
258
    "network6": opts.network6,
259
  }
260

    
261
  if all_changes.values().count(None) == len(all_changes):
262
    ToStderr("Please give at least one of the parameters.")
263
    return 1
264

    
265
  # pylint: disable=W0142
266
  op = opcodes.OpNetworkSetParams(network_name=args[0], **all_changes)
267

    
268
  # TODO: add feedback to user, e.g. list the modifications
269
  SubmitOrSend(op, opts)
270

    
271

    
272
def RemoveNetwork(opts, args):
273
  """Remove an IP address pool from the cluster.
274

275
  @param opts: the command line options selected by the user
276
  @type args: list
277
  @param args: a list of length 1 with the id of the IP address pool to remove
278
  @rtype: int
279
  @return: the desired exit code
280

281
  """
282
  (network_name,) = args
283
  op = opcodes.OpNetworkRemove(network_name=network_name, force=opts.force)
284
  SubmitOpCode(op, opts=opts)
285

    
286

    
287
commands = {
288
  "add": (
289
    AddNetwork, ARGS_ONE_NETWORK,
290
    [DRY_RUN_OPT, NETWORK_OPT, GATEWAY_OPT, ADD_RESERVED_IPS_OPT,
291
     MAC_PREFIX_OPT, NETWORK_TYPE_OPT, NETWORK6_OPT, GATEWAY6_OPT,
292
     NOCONFLICTSCHECK_OPT],
293
    "<network_name>", "Add a new IP network to the cluster"),
294
  "list": (
295
    ListNetworks, ARGS_MANY_NETWORKS,
296
    [NOHDR_OPT, SEP_OPT, FIELDS_OPT, VERBOSE_OPT],
297
    "[<network_id>...]",
298
    "Lists the IP networks in the cluster. The available fields can be shown"
299
    " using the \"list-fields\" command (see the man page for details)."
300
    " The default list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)),
301
  "list-fields": (
302
    ListNetworkFields, [ArgUnknown()], [NOHDR_OPT, SEP_OPT], "[fields...]",
303
    "Lists all available fields for networks"),
304
  "info": (
305
    ShowNetworkConfig, ARGS_MANY_NETWORKS, [],
306
    "[<network_name>...]", "Show information about the network(s)"),
307
  "modify": (
308
    SetNetworkParams, ARGS_ONE_NETWORK,
309
    [DRY_RUN_OPT, SUBMIT_OPT, ADD_RESERVED_IPS_OPT, REMOVE_RESERVED_IPS_OPT,
310
     GATEWAY_OPT, MAC_PREFIX_OPT, NETWORK_TYPE_OPT, NETWORK6_OPT, GATEWAY6_OPT],
311
    "<network_name>", "Alters the parameters of a network"),
312
  "connect": (
313
    MapNetwork,
314
    [ArgNetwork(min=1, max=1), ArgGroup(min=1, max=1),
315
     ArgUnknown(min=1, max=1), ArgUnknown(min=1, max=1)],
316
    [NOCONFLICTSCHECK_OPT],
317
    "<network_name> <node_group> <mode> <link>",
318
    "Map a given network to the specified node group"
319
    " with given mode and link (netparams)"),
320
  "disconnect": (
321
    UnmapNetwork,
322
    [ArgNetwork(min=1, max=1), ArgGroup(min=1, max=1)],
323
    [NOCONFLICTSCHECK_OPT],
324
    "<network_name> <node_group>",
325
    "Unmap a given network from a specified node group"),
326
  "remove": (
327
    RemoveNetwork, ARGS_ONE_NETWORK, [FORCE_OPT, DRY_RUN_OPT],
328
    "[--dry-run] <network_id>",
329
    "Remove an (empty) network from the cluster"),
330
}
331

    
332

    
333
def Main():
334
  return GenericMain(commands)