Revision 06c9a520 lib/hypervisor/hv_xen.py

b/lib/hypervisor/hv_xen.py
158 158
  return _ParseXmList(lines, include_node)
159 159

  
160 160

  
161
def _ParseNodeInfo(info):
162
  """Return information about the node.
163

  
164
  @return: a dict with the following keys (memory values in MiB):
165
        - memory_total: the total memory size on the node
166
        - memory_free: the available memory on the node for instances
167
        - nr_cpus: total number of CPUs
168
        - nr_nodes: in a NUMA system, the number of domains
169
        - nr_sockets: the number of physical CPU sockets in the node
170
        - hv_version: the hypervisor version in the form (major, minor)
171

  
172
  """
173
  result = {}
174
  cores_per_socket = threads_per_core = nr_cpus = None
175
  xen_major, xen_minor = None, None
176
  memory_total = None
177
  memory_free = None
178

  
179
  for line in info.splitlines():
180
    fields = line.split(":", 1)
181

  
182
    if len(fields) < 2:
183
      continue
184

  
185
    (key, val) = map(lambda s: s.strip(), fields)
186

  
187
    # Note: in Xen 3, memory has changed to total_memory
188
    if key in ("memory", "total_memory"):
189
      memory_total = int(val)
190
    elif key == "free_memory":
191
      memory_free = int(val)
192
    elif key == "nr_cpus":
193
      nr_cpus = result["cpu_total"] = int(val)
194
    elif key == "nr_nodes":
195
      result["cpu_nodes"] = int(val)
196
    elif key == "cores_per_socket":
197
      cores_per_socket = int(val)
198
    elif key == "threads_per_core":
199
      threads_per_core = int(val)
200
    elif key == "xen_major":
201
      xen_major = int(val)
202
    elif key == "xen_minor":
203
      xen_minor = int(val)
204

  
205
  if None not in [cores_per_socket, threads_per_core, nr_cpus]:
206
    result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
207

  
208
  if memory_free is not None:
209
    result["memory_free"] = memory_free
210

  
211
  if memory_total is not None:
212
    result["memory_total"] = memory_total
213

  
214
  if not (xen_major is None or xen_minor is None):
215
    result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)
216

  
217
  return result
218

  
219

  
220
def _MergeInstanceInfo(info, fn):
221
  """Updates node information from L{_ParseNodeInfo} with instance info.
222

  
223
  @type info: dict
224
  @param info: Result from L{_ParseNodeInfo}
225
  @type fn: callable
226
  @param fn: Function returning result of running C{xm list}
227
  @rtype: dict
228

  
229
  """
230
  total_instmem = 0
231

  
232
  for (name, _, mem, vcpus, _, _) in fn(True):
233
    if name == _DOM0_NAME:
234
      info["memory_dom0"] = mem
235
      info["dom0_cpus"] = vcpus
236

  
237
    # Include Dom0 in total memory usage
238
    total_instmem += mem
239

  
240
  memory_free = info.get("memory_free")
241
  memory_total = info.get("memory_total")
242

  
243
  # Calculate memory used by hypervisor
244
  if None not in [memory_total, memory_free, total_instmem]:
245
    info["memory_hv"] = memory_total - memory_free - total_instmem
246

  
247
  return info
248

  
249

  
250
def _GetNodeInfo(info, fn):
251
  """Combines L{_MergeInstanceInfo} and L{_ParseNodeInfo}.
252

  
253
  """
254
  return _MergeInstanceInfo(_ParseNodeInfo(info), fn)
255

  
256

  
161 257
class XenHypervisor(hv_base.BaseHypervisor):
162 258
  """Xen generic hypervisor interface
163 259

  
......
372 468
  def GetNodeInfo(self):
373 469
    """Return information about the node.
374 470

  
375
    @return: a dict with the following keys (memory values in MiB):
376
          - memory_total: the total memory size on the node
377
          - memory_free: the available memory on the node for instances
378
          - memory_dom0: the memory used by the node itself, if available
379
          - nr_cpus: total number of CPUs
380
          - nr_nodes: in a NUMA system, the number of domains
381
          - nr_sockets: the number of physical CPU sockets in the node
382
          - hv_version: the hypervisor version in the form (major, minor)
471
    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}
383 472

  
384 473
    """
474
    # TODO: Abstract running Xen command for testing
385 475
    result = utils.RunCmd([constants.XEN_CMD, "info"])
386 476
    if result.failed:
387 477
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
388 478
                    result.output)
389 479
      return None
390 480

  
391
    xmoutput = result.stdout.splitlines()
392
    result = {}
393
    cores_per_socket = threads_per_core = nr_cpus = None
394
    xen_major, xen_minor = None, None
395
    memory_total = None
396
    memory_free = None
397

  
398
    for line in xmoutput:
399
      splitfields = line.split(":", 1)
400

  
401
      if len(splitfields) > 1:
402
        key = splitfields[0].strip()
403
        val = splitfields[1].strip()
404

  
405
        # note: in xen 3, memory has changed to total_memory
406
        if key == "memory" or key == "total_memory":
407
          memory_total = int(val)
408
        elif key == "free_memory":
409
          memory_free = int(val)
410
        elif key == "nr_cpus":
411
          nr_cpus = result["cpu_total"] = int(val)
412
        elif key == "nr_nodes":
413
          result["cpu_nodes"] = int(val)
414
        elif key == "cores_per_socket":
415
          cores_per_socket = int(val)
416
        elif key == "threads_per_core":
417
          threads_per_core = int(val)
418
        elif key == "xen_major":
419
          xen_major = int(val)
420
        elif key == "xen_minor":
421
          xen_minor = int(val)
422

  
423
    if None not in [cores_per_socket, threads_per_core, nr_cpus]:
424
      result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
425

  
426
    total_instmem = 0
427
    for (name, _, mem, vcpus, _, _) in self._GetXmList(True):
428
      if name == _DOM0_NAME:
429
        result["memory_dom0"] = mem
430
        result["dom0_cpus"] = vcpus
431

  
432
      # Include Dom0 in total memory usage
433
      total_instmem += mem
434

  
435
    if memory_free is not None:
436
      result["memory_free"] = memory_free
437

  
438
    if memory_total is not None:
439
      result["memory_total"] = memory_total
440

  
441
    # Calculate memory used by hypervisor
442
    if None not in [memory_total, memory_free, total_instmem]:
443
      result["memory_hv"] = memory_total - memory_free - total_instmem
444

  
445
    if not (xen_major is None or xen_minor is None):
446
      result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)
447

  
448
    return result
481
    return _GetNodeInfo(result.stdout, self._GetXmList)
449 482

  
450 483
  @classmethod
451 484
  def GetInstanceConsole(cls, instance, hvparams, beparams):

Also available in: Unified diff