Revision b255379d lib/hypervisor/hv_xen.py

b/lib/hypervisor/hv_xen.py
75 75
    return "cpus = [ %s ]" % ", ".join(map(_GetCPUMap, cpu_list))
76 76

  
77 77

  
78
def _RunXmList(fn, xmllist_errors):
79
  """Helper function for L{_GetXmList} to run "xm list".
80

  
81
  @type fn: callable
82
  @param fn: Function returning result of running C{xm list}
83
  @type xmllist_errors: list
84
  @param xmllist_errors: Error list
85
  @rtype: list
86

  
87
  """
88
  result = fn()
89
  if result.failed:
90
    logging.error("xm list failed (%s): %s", result.fail_reason,
91
                  result.output)
92
    xmllist_errors.append(result)
93
    raise utils.RetryAgain()
94

  
95
  # skip over the heading
96
  return result.stdout.splitlines()
97

  
98

  
99
def _ParseXmList(lines, include_node):
100
  """Parses the output of C{xm list}.
101

  
102
  @type lines: list
103
  @param lines: Output lines of C{xm list}
104
  @type include_node: boolean
105
  @param include_node: If True, return information for Dom0
106
  @return: list of tuple containing (name, id, memory, vcpus, state, time
107
    spent)
108

  
109
  """
110
  result = []
111

  
112
  # Iterate through all lines while ignoring header
113
  for line in lines[1:]:
114
    # The format of lines is:
115
    # Name      ID Mem(MiB) VCPUs State  Time(s)
116
    # Domain-0   0  3418     4 r-----    266.2
117
    data = line.split()
118
    if len(data) != 6:
119
      raise errors.HypervisorError("Can't parse output of xm list,"
120
                                   " line: %s" % line)
121
    try:
122
      data[1] = int(data[1])
123
      data[2] = int(data[2])
124
      data[3] = int(data[3])
125
      data[5] = float(data[5])
126
    except (TypeError, ValueError), err:
127
      raise errors.HypervisorError("Can't parse output of xm list,"
128
                                   " line: %s, error: %s" % (line, err))
129

  
130
    # skip the Domain-0 (optional)
131
    if include_node or data[0] != _DOM0_NAME:
132
      result.append(data)
133

  
134
  return result
135

  
136

  
137
def _GetXmList(fn, include_node, _timeout=5):
138
  """Return the list of running instances.
139

  
140
  See L{_RunXmList} and L{_ParseXmList} for parameter details.
141

  
142
  """
143
  xmllist_errors = []
144
  try:
145
    lines = utils.Retry(_RunXmList, (0.3, 1.5, 1.0), _timeout,
146
                        args=(fn, xmllist_errors))
147
  except utils.RetryTimeout:
148
    if xmllist_errors:
149
      xmlist_result = xmllist_errors.pop()
150

  
151
      errmsg = ("xm list failed, timeout exceeded (%s): %s" %
152
                (xmlist_result.fail_reason, xmlist_result.output))
153
    else:
154
      errmsg = "xm list failed"
155

  
156
    raise errors.HypervisorError(errmsg)
157

  
158
  return _ParseXmList(lines, include_node)
159

  
160

  
78 161
class XenHypervisor(hv_base.BaseHypervisor):
79 162
  """Xen generic hypervisor interface
80 163

  
......
154 237
    utils.RemoveFile(XenHypervisor._ConfigFileName(instance_name))
155 238

  
156 239
  @staticmethod
157
  def _RunXmList(xmlist_errors):
158
    """Helper function for L{_GetXMList} to run "xm list".
240
  def _GetXmList(include_node):
241
    """Wrapper around module level L{_GetXmList}.
159 242

  
160 243
    """
161
    result = utils.RunCmd([constants.XEN_CMD, "list"])
162
    if result.failed:
163
      logging.error("xm list failed (%s): %s", result.fail_reason,
164
                    result.output)
165
      xmlist_errors.append(result)
166
      raise utils.RetryAgain()
167

  
168
    # skip over the heading
169
    return result.stdout.splitlines()[1:]
170

  
171
  @classmethod
172
  def _GetXMList(cls, include_node):
173
    """Return the list of running instances.
174

  
175
    If the include_node argument is True, then we return information
176
    for dom0 also, otherwise we filter that from the return value.
177

  
178
    @return: list of (name, id, memory, vcpus, state, time spent)
179

  
180
    """
181
    xmlist_errors = []
182
    try:
183
      lines = utils.Retry(cls._RunXmList, 1, 5, args=(xmlist_errors, ))
184
    except utils.RetryTimeout:
185
      if xmlist_errors:
186
        xmlist_result = xmlist_errors.pop()
187

  
188
        errmsg = ("xm list failed, timeout exceeded (%s): %s" %
189
                  (xmlist_result.fail_reason, xmlist_result.output))
190
      else:
191
        errmsg = "xm list failed"
192

  
193
      raise errors.HypervisorError(errmsg)
194

  
195
    result = []
196
    for line in lines:
197
      # The format of lines is:
198
      # Name      ID Mem(MiB) VCPUs State  Time(s)
199
      # Domain-0   0  3418     4 r-----    266.2
200
      data = line.split()
201
      if len(data) != 6:
202
        raise errors.HypervisorError("Can't parse output of xm list,"
203
                                     " line: %s" % line)
204
      try:
205
        data[1] = int(data[1])
206
        data[2] = int(data[2])
207
        data[3] = int(data[3])
208
        data[5] = float(data[5])
209
      except (TypeError, ValueError), err:
210
        raise errors.HypervisorError("Can't parse output of xm list,"
211
                                     " line: %s, error: %s" % (line, err))
212

  
213
      # skip the Domain-0 (optional)
214
      if include_node or data[0] != _DOM0_NAME:
215
        result.append(data)
216

  
217
    return result
244
    # TODO: Abstract running Xen command for testing
245
    return _GetXmList(lambda: utils.RunCmd([constants.XEN_CMD, "list"]),
246
                      include_node)
218 247

  
219 248
  def ListInstances(self):
220 249
    """Get the list of running instances.
221 250

  
222 251
    """
223
    xm_list = self._GetXMList(False)
252
    xm_list = self._GetXmList(False)
224 253
    names = [info[0] for info in xm_list]
225 254
    return names
226 255

  
......
232 261
    @return: tuple (name, id, memory, vcpus, stat, times)
233 262

  
234 263
    """
235
    xm_list = self._GetXMList(instance_name == _DOM0_NAME)
264
    xm_list = self._GetXmList(instance_name == _DOM0_NAME)
236 265
    result = None
237 266
    for data in xm_list:
238 267
      if data[0] == instance_name:
......
246 275
    @return: list of tuples (name, id, memory, vcpus, stat, times)
247 276

  
248 277
    """
249
    xm_list = self._GetXMList(False)
278
    xm_list = self._GetXmList(False)
250 279
    return xm_list
251 280

  
252 281
  def StartInstance(self, instance, block_devices, startup_paused):
......
395 424
      result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
396 425

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

Also available in: Unified diff