Revision b95d2054

b/lib/cli.py
54 54
  # Command line options
55 55
  "ABSOLUTE_OPT",
56 56
  "ADD_UIDS_OPT",
57
  "ADD_RESERVED_IPS_OPT",
57 58
  "ALLOCATABLE_OPT",
58 59
  "ALLOC_POLICY_OPT",
59 60
  "ALL_OPT",
......
87 88
  "FORCE_FILTER_OPT",
88 89
  "FORCE_OPT",
89 90
  "FORCE_VARIANT_OPT",
91
  "GATEWAY_OPT",
92
  "GATEWAY6_OPT",
90 93
  "GLOBAL_FILEDIR_OPT",
91 94
  "HID_OS_OPT",
92 95
  "GLOBAL_SHARED_FILEDIR_OPT",
......
111 114
  "MC_OPT",
112 115
  "MIGRATION_MODE_OPT",
113 116
  "NET_OPT",
117
  "NETWORK_OPT",
118
  "NETWORK6_OPT",
119
  "NETWORK_TYPE_OPT",
114 120
  "NEW_CLUSTER_CERT_OPT",
115 121
  "NEW_CLUSTER_DOMAIN_SECRET_OPT",
116 122
  "NEW_CONFD_HMAC_KEY_OPT",
......
118 124
  "NEW_SECONDARY_OPT",
119 125
  "NEW_SPICE_CERT_OPT",
120 126
  "NIC_PARAMS_OPT",
127
  "NOCONFLICTSCHECK_OPT",
121 128
  "NODE_FORCE_JOIN_OPT",
122 129
  "NODE_LIST_OPT",
123 130
  "NODE_PLACEMENT_OPT",
......
160 167
  "READD_OPT",
161 168
  "REBOOT_TYPE_OPT",
162 169
  "REMOVE_INSTANCE_OPT",
170
  "REMOVE_RESERVED_IPS_OPT",
163 171
  "REMOVE_UIDS_OPT",
164 172
  "RESERVED_LVS_OPT",
165 173
  "RUNTIME_MEM_OPT",
......
235 243
  "ARGS_MANY_INSTANCES",
236 244
  "ARGS_MANY_NODES",
237 245
  "ARGS_MANY_GROUPS",
246
  "ARGS_MANY_NETWORKS",
238 247
  "ARGS_NONE",
239 248
  "ARGS_ONE_INSTANCE",
240 249
  "ARGS_ONE_NODE",
241 250
  "ARGS_ONE_GROUP",
242 251
  "ARGS_ONE_OS",
252
  "ARGS_ONE_NETWORK",
243 253
  "ArgChoice",
244 254
  "ArgCommand",
245 255
  "ArgFile",
......
247 257
  "ArgHost",
248 258
  "ArgInstance",
249 259
  "ArgJobId",
260
  "ArgNetwork",
250 261
  "ArgNode",
251 262
  "ArgOs",
252 263
  "ArgSuggest",
......
257 268
  "OPT_COMPL_ONE_INSTANCE",
258 269
  "OPT_COMPL_ONE_NODE",
259 270
  "OPT_COMPL_ONE_NODEGROUP",
271
  "OPT_COMPL_ONE_NETWORK",
260 272
  "OPT_COMPL_ONE_OS",
261 273
  "cli_option",
262 274
  "SplitNodeOption",
......
355 367
  """
356 368

  
357 369

  
370
class ArgNetwork(_Argument):
371
  """Network argument.
372

  
373
  """
374

  
358 375
class ArgGroup(_Argument):
359 376
  """Node group argument.
360 377

  
......
393 410

  
394 411
ARGS_NONE = []
395 412
ARGS_MANY_INSTANCES = [ArgInstance()]
413
ARGS_MANY_NETWORKS = [ArgNetwork()]
396 414
ARGS_MANY_NODES = [ArgNode()]
397 415
ARGS_MANY_GROUPS = [ArgGroup()]
398 416
ARGS_ONE_INSTANCE = [ArgInstance(min=1, max=1)]
417
ARGS_ONE_NETWORK = [ArgNetwork(min=1, max=1)]
399 418
ARGS_ONE_NODE = [ArgNode(min=1, max=1)]
400 419
# TODO
401 420
ARGS_ONE_GROUP = [ArgGroup(min=1, max=1)]
......
639 658
 OPT_COMPL_ONE_INSTANCE,
640 659
 OPT_COMPL_ONE_OS,
641 660
 OPT_COMPL_ONE_IALLOCATOR,
661
 OPT_COMPL_ONE_NETWORK,
642 662
 OPT_COMPL_INST_ADD_NODES,
643
 OPT_COMPL_ONE_NODEGROUP) = range(100, 107)
663
 OPT_COMPL_ONE_NODEGROUP) = range(100, 108)
644 664

  
645 665
OPT_COMPL_ALL = frozenset([
646 666
  OPT_COMPL_MANY_NODES,
......
648 668
  OPT_COMPL_ONE_INSTANCE,
649 669
  OPT_COMPL_ONE_OS,
650 670
  OPT_COMPL_ONE_IALLOCATOR,
671
  OPT_COMPL_ONE_NETWORK,
651 672
  OPT_COMPL_INST_ADD_NODES,
652 673
  OPT_COMPL_ONE_NODEGROUP,
653 674
  ])
......
1440 1461
                          help="Marks the grow as absolute instead of the"
1441 1462
                          " (default) relative mode")
1442 1463

  
1464
NETWORK_OPT = cli_option("--network",
1465
                         action="store", default=None, dest="network",
1466
                         help="IP network in CIDR notation")
1467

  
1468
GATEWAY_OPT = cli_option("--gateway",
1469
                         action="store", default=None, dest="gateway",
1470
                         help="IP address of the router (gateway)")
1471

  
1472
ADD_RESERVED_IPS_OPT = cli_option("--add-reserved-ips",
1473
                                  action="store", default=None,
1474
                                  dest="add_reserved_ips",
1475
                                  help="Comma-separated list of"
1476
                                  " reserved IPs to add")
1477

  
1478
REMOVE_RESERVED_IPS_OPT = cli_option("--remove-reserved-ips",
1479
                                     action="store", default=None,
1480
                                     dest="remove_reserved_ips",
1481
                                     help="Comma-delimited list of"
1482
                                     " reserved IPs to remove")
1483

  
1484
NETWORK_TYPE_OPT = cli_option("--network-type",
1485
                              action="store", default=None, dest="network_type",
1486
                              help="Network type: private, public, None")
1487

  
1488
NETWORK6_OPT = cli_option("--network6",
1489
                          action="store", default=None, dest="network6",
1490
                          help="IP network in CIDR notation")
1491

  
1492
GATEWAY6_OPT = cli_option("--gateway6",
1493
                          action="store", default=None, dest="gateway6",
1494
                          help="IP6 address of the router (gateway)")
1495

  
1496
NOCONFLICTSCHECK_OPT = cli_option("--no-conflicts-check",
1497
                                  dest="conflicts_check",
1498
                                  default=True,
1499
                                  action="store_false",
1500
                                  help="Don't check for conflicting IPs")
1501

  
1443 1502
#: Options provided by all commands
1444 1503
COMMON_OPTS = [DEBUG_OPT]
1445 1504

  
......
1456 1515
  NET_OPT,
1457 1516
  NODE_PLACEMENT_OPT,
1458 1517
  NOIPCHECK_OPT,
1518
  NOCONFLICTSCHECK_OPT,
1459 1519
  NONAMECHECK_OPT,
1460 1520
  NONICS_OPT,
1461 1521
  NWSYNC_OPT,
b/lib/client/gnt_instance.py
1339 1339
                                   force=opts.force,
1340 1340
                                   wait_for_sync=opts.wait_for_sync,
1341 1341
                                   offline=offline,
1342
                                   conflicts_check=opts.conflicts_check,
1342 1343
                                   ignore_ipolicy=opts.ignore_ipolicy)
1343 1344

  
1344 1345
  # even if here we process the result, we allow submit only
......
1526 1527
    [BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
1527 1528
     DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT,
1528 1529
     OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT, NWSYNC_OPT, OFFLINE_INST_OPT,
1529
     ONLINE_INST_OPT, IGNORE_IPOLICY_OPT, RUNTIME_MEM_OPT],
1530
     ONLINE_INST_OPT, IGNORE_IPOLICY_OPT, RUNTIME_MEM_OPT,
1531
     NOCONFLICTSCHECK_OPT],
1530 1532
    "<instance>", "Alters the parameters of an instance"),
1531 1533
  "shutdown": (
1532 1534
    GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()],
b/lib/client/gnt_network.py
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)

Also available in: Unified diff