PageRenderTime 23ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/cobbler/modules/serializer_catalog.py

https://github.com/jeckersb/cobbler
Python | 204 lines | 202 code | 0 blank | 2 comment | 1 complexity | 1d81f5e2fd5cd860b43da06ae2d088d2 MD5 | raw file
  1. """
  2. Serializer code for cobbler.
  3. As of 8/2009, this is the "best" serializer option.
  4. It uses multiple files in /var/lib/cobbler/config/distros.d, profiles.d, etc
  5. And JSON, when possible, and YAML, when not.
  6. It is particularly fast, especially when using JSON. YAML, not so much.
  7. It also knows how to upgrade the old "single file" configs to .d versions.
  8. Copyright 2006-2009, Red Hat, Inc
  9. Michael DeHaan <mdehaan@redhat.com>
  10. This program is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2 of the License, or
  13. (at your option) any later version.
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. 02110-1301 USA
  22. """
  23. import distutils.sysconfig
  24. import os
  25. import sys
  26. import glob
  27. import traceback
  28. import yaml # PyYAML
  29. import simplejson
  30. import exceptions
  31. plib = distutils.sysconfig.get_python_lib()
  32. mod_path="%s/cobbler" % plib
  33. sys.path.insert(0, mod_path)
  34. from utils import _
  35. import utils
  36. from cexceptions import *
  37. import os
  38. def can_use_json():
  39. version = sys.version[:3]
  40. version = float(version)
  41. return (version > 2.3)
  42. def register():
  43. """
  44. The mandatory cobbler module registration hook.
  45. """
  46. return "serializer"
  47. def serialize_item(obj, item):
  48. if item.name is None or item.name == "":
  49. raise exceptions.RuntimeError("name unset for object!")
  50. filename = "/var/lib/cobbler/config/%ss.d/%s" % (obj.collection_type(),item.name)
  51. datastruct = item.to_datastruct()
  52. jsonable = can_use_json()
  53. if jsonable:
  54. # avoid using JSON on python 2.3 where we can encounter
  55. # unicode problems with simplejson pre 2.0
  56. if os.path.exists(filename):
  57. print "upgrading yaml file to json: %s" % filename
  58. os.remove(filename)
  59. filename = filename + ".json"
  60. datastruct = item.to_datastruct()
  61. fd = open(filename,"w+")
  62. data = simplejson.dumps(datastruct, encoding="utf-8")
  63. #data = data.encode('utf-8')
  64. fd.write(data)
  65. else:
  66. if os.path.exists(filename + ".json"):
  67. print "downgrading json file back to yaml: %s" % filename
  68. os.remove(filename + ".json")
  69. datastruct = item.to_datastruct()
  70. fd = open(filename,"w+")
  71. data = yaml.dump(datastruct)
  72. fd.write(data)
  73. fd.close()
  74. return True
  75. def serialize_delete(obj, item):
  76. filename = "/var/lib/cobbler/config/%ss.d/%s" % (obj.collection_type(),item.name)
  77. filename2 = filename + ".json"
  78. if os.path.exists(filename):
  79. os.remove(filename)
  80. if os.path.exists(filename2):
  81. os.remove(filename2)
  82. return True
  83. def deserialize_item_raw(collection_type, item_name):
  84. # this new fn is not really implemented performantly in this module.
  85. # yet.
  86. filename = "/var/lib/cobbler/config/%ss.d/%s" % (collection_type,item_name)
  87. filename2 = filename + ".json"
  88. if os.path.exists(filename):
  89. fd = open(filename)
  90. data = fd.read()
  91. return yaml.load(data)
  92. elif os.path.exists(filename2):
  93. fd = open(filename2)
  94. data = fd.read()
  95. return simplejson.loads(data, encoding="utf-8")
  96. else:
  97. return None
  98. def serialize(obj):
  99. """
  100. Save an object to disk. Object must "implement" Serializable.
  101. FIXME: Return False on access/permission errors.
  102. This should NOT be used by API if serialize_item is available.
  103. """
  104. ctype = obj.collection_type()
  105. if ctype == "settings":
  106. return True
  107. for x in obj:
  108. serialize_item(obj,x)
  109. return True
  110. def deserialize_raw(collection_type):
  111. old_filename = "/var/lib/cobbler/%ss" % collection_type
  112. if collection_type == "settings":
  113. fd = open("/etc/cobbler/settings")
  114. datastruct = yaml.load(fd.read())
  115. fd.close()
  116. return datastruct
  117. elif os.path.exists(old_filename):
  118. # for use in migration from serializer_yaml to serializer_catalog (yaml/json)
  119. fd = open(old_filename)
  120. datastruct = yaml.load(fd.read())
  121. fd.close()
  122. return datastruct
  123. else:
  124. results = []
  125. all_files = glob.glob("/var/lib/cobbler/config/%ss.d/*" % collection_type)
  126. all_files = filter_upgrade_duplicates(all_files)
  127. for f in all_files:
  128. fd = open(f)
  129. ydata = fd.read()
  130. # ydata = ydata.decode()
  131. if f.endswith(".json"):
  132. datastruct = simplejson.loads(ydata, encoding='utf-8')
  133. else:
  134. datastruct = yaml.load(ydata)
  135. results.append(datastruct)
  136. fd.close()
  137. return results
  138. def filter_upgrade_duplicates(file_list):
  139. """
  140. In a set of files, some ending with .json, some not, return
  141. the list of files with the .json ones taking priority over
  142. the ones that are not.
  143. """
  144. bases = {}
  145. for f in file_list:
  146. basekey = f.replace(".json","")
  147. if f.endswith(".json"):
  148. bases[basekey] = f
  149. else:
  150. lookup = bases.get(basekey,"")
  151. if not lookup.endswith(".json"):
  152. bases[basekey] = f
  153. return bases.values()
  154. def deserialize(obj,topological=True):
  155. """
  156. Populate an existing object with the contents of datastruct.
  157. Object must "implement" Serializable.
  158. """
  159. old_filename = "/var/lib/cobbler/%ss" % obj.collection_type()
  160. datastruct = deserialize_raw(obj.collection_type())
  161. if topological and type(datastruct) == list:
  162. datastruct.sort(__depth_cmp)
  163. obj.from_datastruct(datastruct)
  164. if os.path.exists(old_filename):
  165. # we loaded it in from the old filename, so now migrate to new fmt
  166. sys.stderr.write("auto-removing old config format: %s\n" % old_filename)
  167. serialize(obj)
  168. os.remove(old_filename)
  169. return True
  170. def __depth_cmp(item1, item2):
  171. d1 = item1.get("depth",1)
  172. d2 = item2.get("depth",1)
  173. return cmp(d1,d2)
  174. if __name__ == "__main__":
  175. print deserialize_item_raw("distro","D1")