Révision b6c6a02e
kvm_net: update VM name parsing
The old parser seemed to rely on a simple "-name foo" argument format ofkvm/qemu. The changed parser also accepts the following formats:
- name,foo=bar,baz=bot
- guest=name,foo=bar
| plugins/libvirt/kvm_net | ||
|---|---|---|
| 38 | 38 |
import sys |
| 39 | 39 |
|
| 40 | 40 |
|
| 41 |
VM_NAME_REGEX = re.compile("^.*\x00-{arg_name}\x00(.+)\x00.*$")
|
|
| 42 |
|
|
| 43 |
|
|
| 41 | 44 |
def config(vm_names): |
| 42 | 45 |
""" Print the plugin's config |
| 43 | 46 |
|
| ... | ... | |
| 106 | 109 |
|
| 107 | 110 |
@return a dictionnary of {pids : cleaned vm name}
|
| 108 | 111 |
""" |
| 109 |
vm_name_regex = re.compile(r"^.*-name\x00([a-zA-Z0-9.-_-]*)\x00\-.*$") |
|
| 110 | 112 |
result = {}
|
| 111 | 113 |
for pid in pids: |
| 112 |
cmdline = open("/proc/%s/cmdline" % pid, "r")
|
|
| 113 |
result[pid] = clean_vm_name(vm_name_regex.sub(r"\1", cmdline.readline())) |
|
| 114 |
name = None |
|
| 115 |
name_arg_values = _get_kvm_process_arguments(pid, "name") |
|
| 116 |
if name_arg_values: |
|
| 117 |
name_arg_value = name_arg_values[0] |
|
| 118 |
if "," in name_arg_value: |
|
| 119 |
# the modern parameter format may look like this: |
|
| 120 |
# guest=foo,debug-threads=on |
|
| 121 |
for index, token in enumerate(name_arg_value.split(",")):
|
|
| 122 |
if (index == 0) and ("=" not in token):
|
|
| 123 |
# the first item may the plain name |
|
| 124 |
name = value |
|
| 125 |
elif "=" in token: |
|
| 126 |
key, value = token.split("=", 1)
|
|
| 127 |
if key == "guest": |
|
| 128 |
name = value |
|
| 129 |
else: |
|
| 130 |
# unknown format (no "mapping") |
|
| 131 |
pass |
|
| 132 |
else: |
|
| 133 |
name = name_arg_value |
|
| 134 |
if name is None: |
|
| 135 |
print("Failed to parse VM name from commandline of process: {}"
|
|
| 136 |
.format(name_arg_values), file=sys.stderr) |
|
| 137 |
else: |
|
| 138 |
result[pid] = clean_vm_name(name) |
|
| 114 | 139 |
return result |
| 115 | 140 |
|
| 116 | 141 |
|
| ... | ... | |
| 125 | 150 |
return mac |
| 126 | 151 |
|
| 127 | 152 |
|
| 153 |
def _get_kvm_process_arguments(pid, arg_name): |
|
| 154 |
""" parse all value with the given name from the process identified by PID |
|
| 155 |
|
|
| 156 |
The result is a list of tokens, that follow this argument name. The result |
|
| 157 |
is empty in case of problems. |
|
| 158 |
""" |
|
| 159 |
# the "cmdline" (e.g. /proc/self/cmdline) is a null-separated token list |
|
| 160 |
try: |
|
| 161 |
with open("/proc/%s/cmdline" % pid, "r") as cmdline_file:
|
|
| 162 |
cmdline = cmdline_file.read() |
|
| 163 |
except IOError: |
|
| 164 |
# the process seems to have died meanwhile |
|
| 165 |
return [] |
|
| 166 |
is_value = False |
|
| 167 |
result = [] |
|
| 168 |
for arg_token in cmdline.split("\0"):
|
|
| 169 |
if is_value: |
|
| 170 |
# the previous token was our argument name |
|
| 171 |
result.append(arg_token) |
|
| 172 |
is_value = False |
|
| 173 |
elif arg_token == "-{}".format(arg_name):
|
|
| 174 |
# this is our argument name - we want to store the next value |
|
| 175 |
is_value = True |
|
| 176 |
else: |
|
| 177 |
# any other irrelevant value |
|
| 178 |
pass |
|
| 179 |
return result |
|
| 180 |
|
|
| 181 |
|
|
| 128 | 182 |
def list_pids(): |
| 129 | 183 |
""" Find the pid of kvm processes |
| 130 | 184 |
|
Formats disponibles : Unified diff