registry.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/usr/bin/env python
  2. # Licensed to Cloudera, Inc. under one
  3. # or more contributor license agreements. See the NOTICE file
  4. # distributed with this work for additional information
  5. # regarding copyright ownership. Cloudera, Inc. licenses this file
  6. # to you under the Apache License, Version 2.0 (the
  7. # "License"); you may not use this file except in compliance
  8. # with the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. """
  18. Registry for the applications
  19. """
  20. import glob
  21. import logging
  22. import os
  23. import simplejson
  24. import common
  25. LOG = logging.getLogger(__name__)
  26. class AppRegistry(object):
  27. """
  28. Represents a registry.
  29. """
  30. def __init__(self):
  31. """Open the existing registry"""
  32. self._reg_path = os.path.join(common.INSTALL_ROOT, 'app.reg')
  33. self._initialized = False
  34. self._apps = { } # Map of name -> DesktopApp
  35. self._open()
  36. def _open(self):
  37. """Open the registry file. May raise OSError"""
  38. if os.path.exists(self._reg_path):
  39. reg_file = file(self._reg_path)
  40. app_list = simplejson.load(reg_file)
  41. reg_file.close()
  42. for app_json in app_list:
  43. app = DesktopApp.create(app_json)
  44. self._apps[app.name] = app
  45. self._initialized = True
  46. def _write(self, path):
  47. """Write out the registry to the given path"""
  48. outfile = file(path, 'w')
  49. simplejson.dump(self._apps.values(), outfile, cls=AppJsonEncoder, indent=2)
  50. outfile.close()
  51. def contains(self, app):
  52. """Returns whether the app (of the same version) is in the registry"""
  53. try:
  54. existing = self._apps[app.name]
  55. return existing.version == app.version
  56. except KeyError:
  57. return False
  58. def register(self, app):
  59. """register(app) -> True/False"""
  60. assert self._initialized, "Registry not yet initialized"
  61. try:
  62. existing = self._apps[app.name]
  63. version_diff = common.cmp_version(existing.version, app.version)
  64. if version_diff == 0:
  65. LOG.warn('%s is already registered' % (app,))
  66. return False
  67. elif version_diff < 0:
  68. LOG.info('Upgrading %s from version %s' % (app, existing.version))
  69. elif version_diff > 0:
  70. LOG.error('A newer version of %s is already installed' % (app,))
  71. return False
  72. except KeyError:
  73. pass
  74. LOG.info('Updating registry with %s' % (app,))
  75. self._apps[app.name] = app
  76. return True
  77. def unregister(self, app_name):
  78. """unregister(app_Name) -> DesktopApp. May raise KeyError"""
  79. assert self._initialized, "Registry not yet initialized"
  80. app = self._apps[app_name]
  81. del self._apps[app_name]
  82. return app
  83. def get_all_apps(self):
  84. """get_all_apps() -> List of DesktopApp"""
  85. return self._apps.values()
  86. def save(self):
  87. """Save and write out the registry"""
  88. assert self._initialized, "Registry not yet initialized"
  89. tmp_path = self._reg_path + '.new'
  90. self._write(tmp_path)
  91. os.rename(tmp_path, self._reg_path)
  92. LOG.info('=== Saved registry at %s' % (self._reg_path,))
  93. class DesktopApp(object):
  94. """
  95. Represents an app.
  96. """
  97. @staticmethod
  98. def create(json):
  99. return DesktopApp(json['name'], json['version'], json['path'], json['desc'])
  100. def __init__(self, name, version, path, desc):
  101. self.name = name
  102. self.version = version
  103. self.path = path
  104. self.desc = desc
  105. def __str__(self):
  106. return "%s (version %s)" % (self.name, self.version)
  107. def __cmp__(self, other):
  108. if not isinstance(other, DesktopApp):
  109. raise TypeError
  110. return cmp((self.name, self.version), (other.name, other.version))
  111. def jsonable(self):
  112. return dict(name=self.name, version=self.version, path=self.path, desc=self.desc)
  113. def find_ext_pys(self):
  114. """find_ext_pys() -> A list of paths for all ext-py packages"""
  115. return glob.glob(os.path.join(self.path, 'ext-py', '*'))
  116. class AppJsonEncoder(simplejson.JSONEncoder):
  117. def __init__(self, **kwargs):
  118. simplejson.JSONEncoder.__init__(self, **kwargs)
  119. def default(self, obj):
  120. if isinstance(obj, DesktopApp):
  121. return obj.jsonable()
  122. return simplejson.JSONEncoder.default(self, obj)