"""
Cobbler's file-based object serializer.
As of 9/2014, this is Cobbler's default serializer and the most stable one.
It uses multiple JSON files in /var/lib/cobbler/collections/distros, profiles, etc
"""
from past.builtins import cmp
import os
import glob
import simplejson
import yaml
import cobbler.api as capi
from cobbler.cexceptions import CX
[docs]def register():
"""
The mandatory cobbler module registration hook.
"""
return "serializer"
[docs]def what():
"""
Module identification function
"""
return "serializer/file"
[docs]def serialize_item(collection, item):
"""
Save a collection item to file system
@param collection Collection collection
@param item Item collection item
"""
if not item.name:
raise CX("name unset for item!")
# FIXME: Need a better way to support collections/items
# appending an 's' does not work in all cases
if collection.collection_type() in ['mgmtclass']:
filename = "/var/lib/cobbler/collections/%ses/%s" % (collection.collection_type(), item.name)
else:
filename = "/var/lib/cobbler/collections/%ss/%s" % (collection.collection_type(), item.name)
_dict = item.to_dict()
if capi.CobblerAPI().settings().serializer_pretty_json:
sort_keys = True
indent = 4
else:
sort_keys = False
indent = None
filename += ".json"
_dict = item.to_dict()
fd = open(filename, "w+")
data = simplejson.dumps(_dict, encoding="utf-8", sort_keys=sort_keys, indent=indent)
fd.write(data)
fd.close()
[docs]def serialize_delete(collection, item):
"""
Delete a collection item from file system
@param collection Collection collection
@param item Item collection item
"""
# FIXME: Need a better way to support collections/items
# appending an 's' does not work in all cases
if collection.collection_type() in ['mgmtclass']:
filename = "/var/lib/cobbler/collections/%ses/%s" % (collection.collection_type(), item.name)
else:
filename = "/var/lib/cobbler/collections/%ss/%s" % (collection.collection_type(), item.name)
filename += ".json"
if os.path.exists(filename):
os.remove(filename)
[docs]def serialize(collection):
"""
Save a collection to file system
@param Collection collection collection
"""
# do not serialize settings
ctype = collection.collection_type()
if ctype != "settings":
for x in collection:
serialize_item(collection, x)
[docs]def deserialize_raw(collection_type):
# FIXME: code to load settings file should not be replicated in all
# serializer subclasses
if collection_type == "settings":
fd = open("/etc/cobbler/settings")
_dict = yaml.safe_load(fd.read())
fd.close()
# include support
for ival in _dict.get("include", []):
for ifile in glob.glob(ival):
with open(ifile, 'r') as fd:
_dict.update(yaml.safe_load(fd.read()))
return _dict
else:
results = []
# FIXME: Need a better way to support collections/items
# appending an 's' does not work in all cases
if collection_type in ['mgmtclass']:
all_files = glob.glob("/var/lib/cobbler/collections/%ses/*" % collection_type)
else:
all_files = glob.glob("/var/lib/cobbler/collections/%ss/*" % collection_type)
for f in all_files:
fd = open(f)
json_data = fd.read()
_dict = simplejson.loads(json_data, encoding='utf-8')
results.append(_dict)
fd.close()
return results
[docs]def filter_upgrade_duplicates(file_list):
"""
In a set of files, some ending with .json, some not, return
the list of files with the .json ones taking priority over
the ones that are not.
"""
bases = {}
for f in file_list:
basekey = f.replace(".json", "")
if f.endswith(".json"):
bases[basekey] = f
else:
lookup = bases.get(basekey, "")
if not lookup.endswith(".json"):
bases[basekey] = f
return list(bases.values())
[docs]def deserialize(collection, topological=True):
"""
Load a collection from file system
@param Collection collection collection
@param bool topological
"""
datastruct = deserialize_raw(collection.collection_type())
if topological and type(datastruct) == list:
# FIXME
# datastruct.sort(key=__depth_cmp)
pass
if type(datastruct) == dict:
collection.from_dict(datastruct)
elif type(datastruct) == list:
collection.from_list(datastruct)
def __depth_cmp(item1, item2):
d1 = item1.get("depth", 1)
d2 = item2.get("depth", 1)
return cmp(d1, d2)
# EOF