Skip to content

Commit

Permalink
Made patcher only use libvirt api, and skip changes if guest is running.
Browse files Browse the repository at this point in the history
  • Loading branch information
xlevus committed Feb 3, 2018
1 parent 1961cfa commit c6020c9
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 31 deletions.
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
sudo: false

language: python
python:
- '2.7'
- '3.4'
- '3.5'
- '3.6'
virtualenv:
system_site_packages: true

addons:
apt:
packages:
- python-libvirt
- python3-libvirt

install: pip install tox-travis

script: tox
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Virsh Patcher ![](https://travis-ci.org/PassthroughPOST/virsh-patcher.svg?branch=master)
===================

Simple utility to apply common changes to libvirtd domain xml files.
Simple utility to apply common changes to libvirtd guests.

Can either edit the xml file directly, or apply the patch via a hack around `virsh edit`.
Changes will not be applied if the guest is running.


Supported Fixes
Expand Down Expand Up @@ -36,16 +36,19 @@ $ virshpatcher --error43 --hugepages --host-passthrough win10-guest

```
$ virshpatcher --help
usage: virshpatcher [--error43] [--hugepages] [--host-passthrough]
[--patch PATCH] [--help]
[FILE]
usage: virshpatcher [--connect URI] [--error43] [--hugepages]
[--host-passthrough] [--patch PATCH] [--help]
[--vendor-id ab1234567890] [--random-vendor-id]
[DOMAIN [DOMAIN ...]]
libvirtd xml patcher
positional arguments:
FILE XML file to edit, or libvirtd domain.
DOMAIN
optional arguments:
--connect URI, -c URI
hypervisor connection URI
--error43 Add fixes for 'error43' with nvidia devices.
--hugepages Make guest use hugepages.
--host-passthrough Make guest CPU model `host_passthrough`.
Expand All @@ -61,7 +64,6 @@ optional arguments:
Future Improvements
-----------------------

* Use libvirt API instead of `virsh edit` hack.
* Add ability to connect PCI devices to guest (By name/pattern/id?)
* Interactive (?)
* More tests.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
setup_requires=['pytest-runner'],
tests_require=['pytest'],
classifiers=[],
install_requires=[],
install_requires=['libvirt-python'],
entry_points={
'console_scripts': [
'virshpatcher=virshpatcher.main:main',
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ envlist = py27,py34,py35,py36
[testenv]
deps=
pytest
libvirt-python
commands=py.test
71 changes: 49 additions & 22 deletions virshpatcher/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@
import subprocess
from xml.etree import ElementTree as ET

import libvirt

RUNNING = {
libvirt.VIR_DOMAIN_RUNNING,
libvirt.VIR_DOMAIN_PAUSED,
libvirt.VIR_DOMAIN_PMSUSPENDED,
}

parser = argparse.ArgumentParser(
add_help=False,
description='libvirtd xml patcher')

parser.add_argument(
'--connect', '-c',
metavar='URI',
help='hypervisor connection URI',
default='qemu:///system')

parser.add_argument(
'--error43',
help='Add fixes for \'error43\' with nvidia devices.',
Expand Down Expand Up @@ -66,35 +79,49 @@ def main():
patchers.append(inst)

parser.add_argument(
'file',
help='XML file to edit, or libvirtd domain.',
nargs='?',
metavar='FILE')
'domains',
metavar='DOMAIN',
nargs='*')

args, remainder = parser.parse_known_args(sys.argv[1:])


if args.help:
parser.print_help()
exit(1)

if not args.file:
err("No filename or libvirtd domain specified.")
if not args.domains:
err("No domains provided.")
exit(1)

if not patchers:
err("No patches provided.")
exit(1)

if os.path.exists(args.file):
tree = ET.parse(args.file)
warning = False

connection = libvirt.open(args.connect)

for domain in args.domains:

dom = connection.lookupByName(domain)
state = dom.info()

if state[0] in RUNNING:
warning = True
err("Warning: Domain '{}' is running. Not applying changes. ".format(
domain))
continue

print("Patching: {}".format(domain))
tree = ET.fromstring(dom.XMLDesc(0))

for p in patchers:
print("> Applying: {}".format(p.__class__.__name__))
p.patch(tree, args)
tree.write(args.file)

else:
if args.file != sys.argv[-1]:
err("Libvirt domain must be the last argument provided.")

os.environ['EDITOR'] = " ".join(sys.argv[:-1])
cmd = ['virsh', 'edit', args.file]
try:
ret = subprocess.run(cmd, check=True)
except Exception as e:
err("Unable to edit domain {!r}".format(args.file))
err(e)
exit(1)

xml_str = ET.tostring(tree).decode()
connection.defineXML(xml_str)

if warning:
exit(1)
4 changes: 3 additions & 1 deletion virshpatcher/patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def add_arguments(self, parser):

def patch(self, tree, args):
for patch_set in self.nodes:
node = tree.getroot()
node = tree

for tag in patch_set:
creator = getattr(
Expand All @@ -28,6 +28,8 @@ def patch(self, tree, args):
new = node.find(tag)

if new is None:
if isinstance(node, ET.ElementTree):
node = node.getroot()
new = ET.SubElement(node, *creator(args))

patcher(args, new)
Expand Down

0 comments on commit c6020c9

Please sign in to comment.