Skip to content

Commit

Permalink
nixvirt-module-helper: only redefine the config when the settings is new
Browse files Browse the repository at this point in the history
  • Loading branch information
pharra committed May 31, 2024
1 parent 62d34f7 commit c450ad6
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 11 deletions.
2 changes: 1 addition & 1 deletion modules.nix
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ let
jsonFile = packages.writeText "nixvirt module script" (builtins.toJSON opts);
verboseFlag = if cfg.verbose then "-v" else "";
in
"${moduleHelperFile} ${verboseFlag} --connect ${connection} ${jsonFile}\n";
"${moduleHelperFile} ${verboseFlag} --statedir /var/lib/nixvirt --connect ${connection} ${jsonFile}\n";

extraPackages = [ packages.qemu-utils ] ++ (if cfg.swtpm.enable then [ packages.swtpm ] else [ ]);
extraPaths = concatStrMap (p: "${p}/bin:") extraPackages;
Expand Down
42 changes: 37 additions & 5 deletions tool/nixvirt-module-helper
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
#!/usr/bin/python3
import sys, argparse, uuid, lxml.etree, json, libvirt, nixvirt
import sys, argparse, uuid, lxml.etree, json, libvirt, nixvirt, os

parser = argparse.ArgumentParser(prog='nixvirt-module-helper',description='Define and control a collection of libvirt objects idempotently.')
parser.add_argument('-v', '--verbose', action='store_true', help='report actions to stderr')
parser.add_argument('--connect', action='store', required=True, metavar='URI', help='connection URI (e.g. qemu:///session)')
parser.add_argument('--statedir', action='store', required=True, metavar='PATH', help='state dir (e.g. /var/lib/nixvirt)')
parser.add_argument('settingspath', action='store', metavar='PATH', help='path to JSON file of settings')
args = parser.parse_args()
types = [("network","networks"),("pool","pools"),("domain","domains")]

if not os.path.exists(args.statedir):
os.makedirs(args.statedir)

with open(args.settingspath,"r") as f:
settings = json.load(f)
newSettings = json.load(f)

# save newSettings as json since we will edit it
newSettingsStr = json.dumps(newSettings)

oldSettingsPath = os.path.join(args.statedir, "oldsettings.json")
if os.path.isfile(oldSettingsPath):
with open(oldSettingsPath, "r") as f:
oldSettings = json.load(f)
else:
oldSettings = {}

settings = {}

for (type,key) in types:
newItemlist = newSettings.get(key)
oldItemlist = oldSettings.get(key)
if newItemlist is None or oldItemlist is None:
continue
else:
for newItem in newItemlist:
# tag it with "unchanged"
if oldItemlist.__contains__(newItem):
newItem["unchanged"] = True
settings[key] = newItemlist


class TypeSpec:
def __init__(self,session,type,itemlist):
self.oc = nixvirt.getObjectConnection(session,type)
self.specList = [nixvirt.ObjectSpec.fromDefinitionFile(self.oc,item["definition"],item.get("active"),item) for item in itemlist]
self.specList = [nixvirt.ObjectSpec.fromDefinitionFile(self.oc,item["definition"],item.get("active"),item.get("unchanged"),item) for item in itemlist]

def deleteOld(self):
allObjects = self.oc.getAll()
Expand All @@ -39,8 +69,6 @@ class TypeSpec:
try:
session = nixvirt.Session(args.connect,args.verbose)

types = [("network","networks"),("pool","pools"),("domain","domains")]

session.vreport("Examining settings")
typeSpecs = []
for (type,key) in types:
Expand Down Expand Up @@ -68,6 +96,10 @@ try:
for typeSpec in typeSpecs:
typeSpec.setActive()

# save the new Settings
with open(oldSettingsPath, "w") as f:
f.write(newSettingsStr)

session.vreport("Done")

except nixvirt.NixVirtError as err:
Expand Down
17 changes: 12 additions & 5 deletions tool/nixvirt.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def defineExtra(self,extra):
# what we want for an object
class ObjectSpec:

def __init__(self,oc,specUUID = None,specName = None,specDefXML = None,active = None,extra = None):
def __init__(self,oc,specUUID = None,specName = None,specDefXML = None,active = None, unchanged = None, extra = None):
if specUUID is not None:
self.subject = oc.fromUUIDOrNone(specUUID)
elif specName is not None:
Expand All @@ -327,6 +327,7 @@ def __init__(self,oc,specUUID = None,specName = None,specDefXML = None,active =
self.specName = specName
self.specUUID = specUUID
self.active = active
self.unchanged = unchanged
self.extra = extra

def vreport(self,msg):
Expand All @@ -338,20 +339,22 @@ def fromUUID(oc,specUUID,active):
def fromName(oc,specName,active):
return ObjectSpec(oc,specName = specName,active = active)

def fromDefinition(oc,specDefXML,active,extra = None):
def fromDefinition(oc,specDefXML,active,unchanged,extra = None):
specDefETree = xmlToETree(specDefXML)
specUUID = uuid.UUID(specDefETree.find("uuid").text).bytes
specName = specDefETree.find("name").text
fixedDefETree = oc._fixDefinitionETree(specUUID,specDefETree)
if fixedDefETree is not None:
specDefXML = eTreeToXML(fixedDefETree)
return ObjectSpec(oc,specUUID = specUUID,specName = specName,specDefXML = specDefXML,active = active, extra = extra)
return ObjectSpec(oc,specUUID = specUUID,specName = specName,specDefXML = specDefXML,active = active, unchanged = unchanged, extra = extra)

def fromDefinitionFile(oc,path,active,extra = None):
def fromDefinitionFile(oc,path,active,unchanged,extra = None):
specDefXML = oc.getFile(path)
return ObjectSpec.fromDefinition(oc,specDefXML,active, extra = extra)
return ObjectSpec.fromDefinition(oc,specDefXML,active,unchanged,extra = extra)

def define(self):
if self.unchanged:
return
if self.specDefXML is not None:
if self.subject is not None:
oldDefETree = self.subject.descriptionETree()
Expand All @@ -377,8 +380,12 @@ def define(self):
self.subject = self.oc._fromXML(self.specDefXML)

def defineExtra(self):
if self.unchanged:
return
if self.subject is not None:
self.subject.defineExtra(self.extra)

def setActive(self):
if self.unchanged:
return
self.subject.setActive(self.active)

0 comments on commit c450ad6

Please sign in to comment.