Revision ec79568d

b/daemons/ganeti-masterd
234 234
      return queue.QueryJobs(job_ids, fields)
235 235

  
236 236
    elif method == luxi.REQ_QUERY_INSTANCES:
237
      (names, fields) = args
238
      op = opcodes.OpQueryInstances(names=names, output_fields=fields)
237
      (names, fields, use_locking) = args
238
      op = opcodes.OpQueryInstances(names=names, output_fields=fields,
239
                                    use_locking=use_locking)
239 240
      return self._Query(op)
240 241

  
241 242
    elif method == luxi.REQ_QUERY_NODES:
242
      (names, fields) = args
243
      op = opcodes.OpQueryNodes(names=names, output_fields=fields)
243
      (names, fields, use_locking) = args
244
      op = opcodes.OpQueryNodes(names=names, output_fields=fields,
245
                                use_locking=use_locking)
244 246
      return self._Query(op)
245 247

  
246 248
    elif method == luxi.REQ_QUERY_EXPORTS:
247
      nodes = args
248
      op = opcodes.OpQueryExports(nodes=nodes)
249
      nodes, use_locking = args
250
      op = opcodes.OpQueryExports(nodes=nodes, use_locking=use_locking)
249 251
      return self._Query(op)
250 252

  
251 253
    elif method == luxi.REQ_QUERY_CONFIG_VALUES:
b/daemons/ganeti-watcher
236 236
  if with_secondaries is not None:
237 237
    fields.append("snodes")
238 238

  
239
  result = client.QueryInstances([], fields)
239
  result = client.QueryInstances([], fields, True)
240 240

  
241 241
  instances = []
242 242
  for fields in result:
......
264 264
  """Get a dict mapping nodes to boot IDs.
265 265

  
266 266
  """
267
  result = client.QueryNodes([], ["name", "bootid", "offline"])
267
  result = client.QueryNodes([], ["name", "bootid", "offline"], True)
268 268
  return dict([(name, (bootid, offline)) for name, bootid, offline in result])
269 269

  
270 270

  
b/lib/cli.py
51 51
           "FormatError", "SplitNodeOption", "SubmitOrSend",
52 52
           "JobSubmittedException", "FormatTimestamp", "ParseTimespec",
53 53
           "ValidateBeParams", "ToStderr", "ToStdout", "UsesRPC",
54
           "GetOnlineNodes", "JobExecutor",
54
           "GetOnlineNodes", "JobExecutor", "SYNC_OPT",
55 55
           ]
56 56

  
57 57

  
......
190 190
                         help="Submit the job and return the job ID, but"
191 191
                         " don't wait for the job to finish")
192 192

  
193
SYNC_OPT = make_option("--sync", dest="do_locking",
194
                       default=False, action="store_true",
195
                       help="Grab locks while doing the queries"
196
                       " in order to ensure more consistent results")
197

  
193 198

  
194 199
def ARGS_FIXED(val):
195 200
  """Macro-like function denoting a fixed number of arguments"""
b/lib/cmdlib.py
3074 3074
  """Logical unit for querying instances.
3075 3075

  
3076 3076
  """
3077
  _OP_REQP = ["output_fields", "names"]
3077
  _OP_REQP = ["output_fields", "names", "use_locking"]
3078 3078
  REQ_BGL = False
3079 3079
  _FIELDS_STATIC = utils.FieldSet(*["name", "os", "pnode", "snodes",
3080 3080
                                    "admin_state", "admin_ram",
......
3108 3108
    else:
3109 3109
      self.wanted = locking.ALL_SET
3110 3110

  
3111
    self.do_locking = self._FIELDS_STATIC.NonMatching(self.op.output_fields)
3111
    self.do_node_query = self._FIELDS_STATIC.NonMatching(self.op.output_fields)
3112
    self.do_locking = self.do_node_query and self.op.use_locking
3112 3113
    if self.do_locking:
3113 3114
      self.needed_locks[locking.LEVEL_INSTANCE] = self.wanted
3114 3115
      self.needed_locks[locking.LEVEL_NODE] = []
......
3157 3158

  
3158 3159
    bad_nodes = []
3159 3160
    off_nodes = []
3160
    if self.do_locking:
3161
    if self.do_node_query:
3161 3162
      live_data = {}
3162 3163
      node_data = self.rpc.call_all_instances_info(nodes, hv_list)
3163 3164
      for name in nodes:
b/lib/luxi.py
357 357
  def QueryJobs(self, job_ids, fields):
358 358
    return self.CallMethod(REQ_QUERY_JOBS, (job_ids, fields))
359 359

  
360
  def QueryInstances(self, names, fields):
361
    return self.CallMethod(REQ_QUERY_INSTANCES, (names, fields))
360
  def QueryInstances(self, names, fields, use_locking):
361
    return self.CallMethod(REQ_QUERY_INSTANCES, (names, fields, use_locking))
362 362

  
363
  def QueryNodes(self, names, fields):
364
    return self.CallMethod(REQ_QUERY_NODES, (names, fields))
363
  def QueryNodes(self, names, fields, use_locking):
364
    return self.CallMethod(REQ_QUERY_NODES, (names, fields, use_locking))
365 365

  
366
  def QueryExports(self, nodes):
367
    return self.CallMethod(REQ_QUERY_EXPORTS, nodes)
366
  def QueryExports(self, nodes, use_locking):
367
    return self.CallMethod(REQ_QUERY_EXPORTS, (nodes, use_locking))
368 368

  
369 369
  def QueryConfigValues(self, fields):
370 370
    return self.CallMethod(REQ_QUERY_CONFIG_VALUES, fields)
b/lib/opcodes.py
319 319
class OpQueryNodes(OpCode):
320 320
  """Compute the list of nodes."""
321 321
  OP_ID = "OP_NODE_QUERY"
322
  __slots__ = ["output_fields", "names"]
322
  __slots__ = ["output_fields", "names", "use_locking"]
323 323

  
324 324

  
325 325
class OpQueryNodeVolumes(OpCode):
......
450 450
class OpQueryInstances(OpCode):
451 451
  """Compute the list of instances."""
452 452
  OP_ID = "OP_INSTANCE_QUERY"
453
  __slots__ = ["output_fields", "names"]
453
  __slots__ = ["output_fields", "names", "use_locking"]
454 454

  
455 455

  
456 456
class OpQueryInstanceData(OpCode):
......
488 488
class OpQueryExports(OpCode):
489 489
  """Compute the list of exported images."""
490 490
  OP_ID = "OP_BACKUP_QUERY"
491
  __slots__ = ["nodes"]
491
  __slots__ = ["nodes", "use_locking"]
492 492

  
493 493

  
494 494
class OpExportInstance(OpCode):
b/lib/rapi/rlib2.py
208 208

  
209 209
    """
210 210
    client = luxi.Client()
211
    nodesdata = client.QueryNodes([], ["name"])
211
    nodesdata = client.QueryNodes([], ["name"], True)
212 212
    nodeslist = [row[0] for row in nodesdata]
213 213

  
214 214
    if 'bulk' in self.queryargs:
215
      bulkdata = client.QueryNodes(nodeslist, N_FIELDS)
215
      bulkdata = client.QueryNodes(nodeslist, N_FIELDS, True)
216 216
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
217 217

  
218 218
    return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
......
292 292

  
293 293
    """
294 294
    client = luxi.Client()
295
    instancesdata = client.QueryInstances([], ["name"])
295
    instancesdata = client.QueryInstances([], ["name"], True)
296 296
    instanceslist = [row[0] for row in instancesdata]
297 297

  
298 298

  
299 299
    if 'bulk' in self.queryargs:
300
      bulkdata = client.QueryInstances(instanceslist, I_FIELDS)
300
      bulkdata = client.QueryInstances(instanceslist, I_FIELDS, True)
301 301
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
302 302

  
303 303
    else:
b/scripts/gnt-backup
45 45
  @return: the desired exit code
46 46

  
47 47
  """
48
  exports = GetClient().QueryExports(opts.nodes)
48
  exports = GetClient().QueryExports(opts.nodes, True)
49 49
  retcode = 0
50 50
  for node in exports:
51 51
    ToStdout("Node: %s", node)
b/scripts/gnt-instance
81 81
  if mode == _SHUTDOWN_CLUSTER:
82 82
    if names:
83 83
      raise errors.OpPrereqError("Cluster filter mode takes no arguments")
84
    idata = client.QueryInstances([], ["name"])
84
    idata = client.QueryInstances([], ["name"], False)
85 85
    inames = [row[0] for row in idata]
86 86

  
87 87
  elif mode in (_SHUTDOWN_NODES_BOTH,
......
89 89
                _SHUTDOWN_NODES_SEC):
90 90
    if not names:
91 91
      raise errors.OpPrereqError("No node names passed")
92
    ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"])
92
    ndata = client.QueryNodes(names, ["name", "pinst_list", "sinst_list"],
93
                              True)
93 94
    ipri = [row[1] for row in ndata]
94 95
    pri_names = list(itertools.chain(*ipri))
95 96
    isec = [row[2] for row in ndata]
......
106 107
  elif mode == _SHUTDOWN_INSTANCES:
107 108
    if not names:
108 109
      raise errors.OpPrereqError("No instance names passed")
109
    idata = client.QueryInstances(names, ["name"])
110
    idata = client.QueryInstances(names, ["name"], False)
110 111
    inames = [row[0] for row in idata]
111 112

  
112 113
  else:
......
191 192
  """
192 193
  # TODO: change LUQueryInstances to that it actually returns None
193 194
  # instead of raising an exception, or devise a better mechanism
194
  result = client.QueryInstances(names, ["name"])
195
  result = client.QueryInstances(names, ["name"], False)
195 196
  for orig_name, row in zip(names, result):
196 197
    if row[0] is None:
197 198
      raise errors.OpPrereqError("Instance '%s' does not exist" % orig_name)
......
214 215
  else:
215 216
    selected_fields = opts.output.split(",")
216 217

  
217
  output = GetClient().QueryInstances(args, selected_fields)
218
  output = GetClient().QueryInstances(args, selected_fields, opts.do_locking)
218 219

  
219 220
  if not opts.no_headers:
220 221
    headers = {
......
1370 1371
            ], "[-s] [<instance>...]",
1371 1372
           "Show information on the specified instance(s)"),
1372 1373
  'list': (ListInstances, ARGS_ANY,
1373
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
1374
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT, SYNC_OPT],
1374 1375
           "[<instance>...]",
1375 1376
           "Lists the instances and their status. The available fields are"
1376 1377
           " (see the man page for details): status, oper_state, oper_ram,"
b/scripts/gnt-node
76 76

  
77 77
  if not opts.readd:
78 78
    try:
79
      output = cl.QueryNodes(names=[node], fields=['name'])
79
      output = cl.QueryNodes(names=[node], fields=['name'], use_locking=True)
80 80
    except (errors.OpPrereqError, errors.OpExecError):
81 81
      pass
82 82
    else:
......
119 119
  else:
120 120
    selected_fields = opts.output.split(",")
121 121

  
122
  output = GetClient().QueryNodes([], selected_fields)
122
  output = GetClient().QueryNodes([], selected_fields, True)
123 123

  
124 124
  if not opts.no_headers:
125 125
    headers = _LIST_HEADERS
......
183 183
  src_node = args[0]
184 184

  
185 185
  op = opcodes.OpQueryNodes(output_fields=selected_fields, names=[src_node])
186
  result = cl.QueryNodes(names=[src_node], fields=selected_fields)
186
  result = cl.QueryNodes(names=[src_node], fields=selected_fields,
187
                         use_locking=True)
187 188
  src_node, sinst = result[0]
188 189

  
189 190
  if not sinst:
......
191 192
    return constants.EXIT_SUCCESS
192 193

  
193 194
  if dst_node is not None:
194
    result = cl.QueryNodes(names=[dst_node], fields=["name"])
195
    result = cl.QueryNodes(names=[dst_node], fields=["name"], use_locking=True)
195 196
    dst_node = result[0][0]
196 197

  
197 198
    if src_node == dst_node:
......
276 277
  force = opts.force
277 278
  selected_fields = ["name", "pinst_list"]
278 279

  
279
  result = cl.QueryNodes(names=args, fields=selected_fields)
280
  result = cl.QueryNodes(names=args, fields=selected_fields, use_locking=True)
280 281
  node, pinst = result[0]
281 282

  
282 283
  if not pinst:
b/tools/burnin
323 323
    else:
324 324
      names = []
325 325
    try:
326
      op = opcodes.OpQueryNodes(output_fields=["name", "offline"], names=names)
326
      op = opcodes.OpQueryNodes(output_fields=["name", "offline"],
327
                                names=names, use_locking=True)
327 328
      result = self.ExecOp(op)
328 329
    except errors.GenericError, err:
329 330
      err_code, msg = cli.FormatError(err)
......
484 485
      Log("instance %s" % instance, indent=1)
485 486
      # read the full name of the instance
486 487
      nam_op = opcodes.OpQueryInstances(output_fields=["name"],
487
                                           names=[instance])
488
                                        names=[instance], use_locking=True)
488 489
      full_name = self.ExecOp(nam_op)[0][0]
489 490

  
490 491
      if self.opts.iallocator:

Also available in: Unified diff