Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_network.py @ f58ecd88

History | View | Annotate | Download (10.4 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-msg=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", "group_cnt", "group_list"]
36

    
37

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

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

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

55
  """
56
  (network_name, ) = args
57

    
58
  op = opcodes.OpNetworkAdd(network_name=network_name,
59
                            gateway=opts.gateway,
60
                            network=opts.network,
61
                            gateway6=opts.gateway6,
62
                            network6=opts.network6,
63
                            mac_prefix=opts.mac_prefix,
64
                            network_type=opts.network_type,
65
                            add_reserved_ips=_HandleReservedIPs(opts.add_reserved_ips))
66
  SubmitOpCode(op, opts=opts)
67

    
68

    
69
def MapNetwork(opts, args):
70
  """Map a network to a node group.
71

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

78
  """
79
  network = args[0]
80
  groups = args[1]
81
  mode = args[2]
82
  link = args[3]
83

    
84
  #TODO: allow comma separated group names
85
  if groups == 'all':
86
    cl = GetClient()
87
    (groups, ) = cl.QueryGroups([], ['name'], False)
88
  else:
89
    groups = [groups]
90

    
91
  for group in groups:
92
    op = opcodes.OpNetworkConnect(group_name=group,
93
                                  network_name=network,
94
                                  network_mode=mode,
95
                                  network_link=link,
96
                                  conflicts_check=opts.conflicts_check)
97
    SubmitOpCode(op, opts=opts)
98

    
99

    
100
def UnmapNetwork(opts, args):
101
  """Unmap a network from a node group.
102

103
  @param opts: the command line options selected by the user
104
  @type args: list
105
  @param args: a list of length 3 with network, nodegorup
106
  @rtype: int
107
  @return: the desired exit code
108

109
  """
110
  network = args[0]
111
  groups = args[1]
112

    
113
  #TODO: allow comma separated group names
114
  if groups == 'all':
115
    cl = GetClient()
116
    (groups, ) = cl.QueryGroups([], ['name'], False)
117
  else:
118
    groups = [groups]
119

    
120
  for group in groups:
121
    op = opcodes.OpNetworkDisconnect(group_name=group,
122
                                     network_name=network,
123
                                     conflicts_check=opts.conflicts_check)
124
    SubmitOpCode(op, opts=opts)
125

    
126

    
127
def ListNetworks(opts, args):
128
  """List Ip pools and their properties.
129

130
  @param opts: the command line options selected by the user
131
  @type args: list
132
  @param args: networks to list, or empty for all
133
  @rtype: int
134
  @return: the desired exit code
135

136
  """
137
  desired_fields = ParseFields(opts.output, _LIST_DEF_FIELDS)
138
  fmtoverride = {
139
    "group_list": (",".join, False),
140
    "inst_list": (",".join, False),
141
  }
142

    
143
  return GenericList(constants.QR_NETWORK, desired_fields, args, None,
144
                     opts.separator, not opts.no_headers,
145
                     verbose=opts.verbose, format_override=fmtoverride)
146

    
147

    
148
def ListNetworkFields(opts, args):
149
  """List network fields.
150

151
  @param opts: the command line options selected by the user
152
  @type args: list
153
  @param args: fields to list, or empty for all
154
  @rtype: int
155
  @return: the desired exit code
156

157
  """
158
  return GenericListFields(constants.QR_NETWORK, args, opts.separator,
159
                           not opts.no_headers)
160

    
161

    
162
def ShowNetworkConfig(opts, args):
163
  """Show network information.
164

165
  @param opts: the command line options selected by the user
166
  @type args: list
167
  @param args: should either be an empty list, in which case
168
      we show information about all nodes, or should contain
169
      a list of networks (names or UUIDs) to be queried for information
170
  @rtype: int
171
  @return: the desired exit code
172

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

    
183
  for (name, network, gateway, network6, gateway6,
184
       mac_prefix, network_type, free_count, reserved_count,
185
       map, group_list, instances, ext_res) in result:
186
    size = free_count + reserved_count
187
    ToStdout("Network name: %s", name)
188
    ToStdout("  subnet: %s", network)
189
    ToStdout("  gateway: %s", gateway)
190
    ToStdout("  subnet6: %s", network6)
191
    ToStdout("  gateway6: %s", gateway6)
192
    ToStdout("  mac prefix: %s", mac_prefix)
193
    ToStdout("  type: %s", network_type)
194
    ToStdout("  size: %d", size)
195
    ToStdout("  free: %d (%.2f%%)", free_count,
196
             100 * float(free_count)/float(size))
197
    ToStdout("  usage map:")
198
    idx = 0
199
    for line in wrap(map, width=64):
200
      ToStdout("     %s %s %d", str(idx).rjust(3), line.ljust(64), idx + 63)
201
      idx += 64
202
    ToStdout("         (X) used    (.) free")
203

    
204
    if ext_res:
205
      ToStdout("  externally reserved IPs:")
206
      for line in wrap(ext_res, width=64):
207
        ToStdout("    %s" % line)
208

    
209
    if group_list:
210
      ToStdout("  connected to node groups:")
211
      for group in group_list:
212
        ToStdout("    %s", group)
213
    else:
214
      ToStdout("  not connected to any node group")
215

    
216
    if instances:
217
      ToStdout("  used by %d instances:", len(instances))
218
      for inst in instances:
219
        ((ips, networks), ) = cl.QueryInstances([inst],
220
                                                ["nic.ips", "nic.networks"],
221
                                                use_locking=False)
222

    
223
        l = lambda value: ", ".join(`idx`+":"+str(ip)
224
                                    for idx, (ip, net) in enumerate(value)
225
                                      if net == name)
226

    
227
        ToStdout("    %s : %s", inst, l(zip(ips,networks)))
228
    else:
229
      ToStdout("  not used by any instances")
230

    
231

    
232
def SetNetworkParams(opts, args):
233
  """Modifies an IP address pool's parameters.
234

235
  @param opts: the command line options selected by the user
236
  @type args: list
237
  @param args: should contain only one element, the node group name
238

239
  @rtype: int
240
  @return: the desired exit code
241

242
  """
243

    
244
  # TODO: add "network": opts.network,
245
  all_changes = {
246
    "gateway": opts.gateway,
247
    "add_reserved_ips": _HandleReservedIPs(opts.add_reserved_ips),
248
    "remove_reserved_ips": _HandleReservedIPs(opts.remove_reserved_ips),
249
    "mac_prefix": opts.mac_prefix,
250
    "network_type": opts.network_type,
251
    "gateway6": opts.gateway6,
252
    "network6": opts.network6,
253
  }
254

    
255
  if all_changes.values().count(None) == len(all_changes):
256
    ToStderr("Please give at least one of the parameters.")
257
    return 1
258

    
259
  op = opcodes.OpNetworkSetParams(network_name=args[0],
260
                                  # pylint: disable-msg=W0142
261
                                  **all_changes)
262

    
263
  # TODO: add feedback to user, e.g. list the modifications
264
  SubmitOrSend(op, opts)
265

    
266

    
267
def RemoveNetwork(opts, args):
268
  """Remove an IP address pool from the cluster.
269

270
  @param opts: the command line options selected by the user
271
  @type args: list
272
  @param args: a list of length 1 with the id of the IP address pool to remove
273
  @rtype: int
274
  @return: the desired exit code
275

276
  """
277
  (network_name,) = args
278
  op = opcodes.OpNetworkRemove(network_name=network_name, force=opts.force)
279
  SubmitOpCode(op, opts=opts)
280

    
281

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

    
326

    
327
def Main():
328
  return GenericMain(commands)