PageRenderTime 154ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/imagefactory-0.7.1/imgfac/ApplicationConfiguration.py

#
Python | 176 lines | 150 code | 7 blank | 19 comment | 5 complexity | 5f203196026d1ef50d9a82b61680d9a5 MD5 | raw file
Possible License(s): Apache-2.0
  1. # encoding: utf-8
  2. # Copyright 2011 Red Hat, Inc.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import sys
  16. import os
  17. import argparse
  18. import json
  19. import logging
  20. import props
  21. from Singleton import Singleton
  22. class ApplicationConfiguration(Singleton):
  23. configuration = props.prop("_configuration", "The configuration property.")
  24. def _singleton_init(self):
  25. super(ApplicationConfiguration, self)._singleton_init()
  26. self.log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__))
  27. self.configuration = self.__parse_arguments()
  28. self.jeos_images = {}
  29. self.__parse_jeos_images()
  30. def __init__(self):
  31. pass
  32. def __new_argument_parser(self):
  33. main_description = """Image Factory is an application for creating system images to run virtual machines in various public and private \
  34. clouds. The imagefactory command can be used to start a daemon providing a QMFv2 agent interface, allowing for \
  35. remote interaction. An alternate method of running imagefactory allows for one-off image building and deployment \
  36. and does not connect to a qpidd."""
  37. qmf_description = """Provide a QMFv2 agent interface. (see https://cwiki.apache.org/qpid/qmfv2-project-page.html for more information)"""
  38. cli_build_description = """Build specified system and exit."""
  39. cli_push_description = """Push an image and exit."""
  40. warehouse_description = """Options for specifying Image Warehouse (http://aeolusproject.org/imagewarehouse.html) base URL and bucket names."""
  41. rest_description = """Enable the RESTful interface."""
  42. argparser = argparse.ArgumentParser(description=main_description, prog='imagefactory')
  43. argparser.add_argument('--version', action='version', version='%(prog)s 0.1', help='Version info')
  44. argparser.add_argument('-v', '--verbose', action='store_true', default=False, help='Set verbose logging.')
  45. argparser.add_argument('--debug', action='store_true', default=False, help='Set really verbose logging for debugging.')
  46. argparser.add_argument('--image', help='UUID of iwhd image object to rebuild or push')
  47. argparser.add_argument('--foreground', action='store_true', default=False, help='Stay in the foreground and avoid launching a daemon. (default: %(default)s)')
  48. argparser.add_argument('--config', default='/etc/imagefactory/imagefactory.conf', help='Configuration file to use. (default: %(default)s)')
  49. argparser.add_argument('--imgdir', default='/tmp', help='Build image files in location specified. (default: %(default)s)')
  50. argparser.add_argument('--timeout', type=int, default=3600, help='Set the timeout period for image building in seconds. (default: %(default)s)')
  51. argparser.add_argument('--tmpdir', default='/tmp', help='Use the specified location for temporary files. (default: %(default)s)')
  52. group_rest = argparser.add_argument_group(title='RESTful Interface', description=rest_description)
  53. group_rest.add_argument('--rest', action='store_true', default=False, help='Turn on the RESTful http interface. (default: %(default)s)')
  54. group_rest.add_argument('--port', type=int, default=8075, help='Port to attach the RESTful http interface to. (defaul: %(default)s)')
  55. group_rest.add_argument('--address', default='0.0.0.0', help='Interface address to listen to. (defaul: %(default)s)')
  56. group_rest.add_argument('--no_ssl', action='store_true', default=False, help='Turn off SSL. (default: %(default)s)')
  57. group_rest.add_argument('--ssl_pem', default='*', help='PEM certificate file to use for HTTPS access to the REST interface. (default: A transient certificate is generated at runtime.)')
  58. group_rest.add_argument('--no_oauth', action='store_true', default=False, help='Use 2 legged OAuth to protect the REST interface. (default: %(default)s)')
  59. group_qmf = argparser.add_argument_group(title='QMF agent', description=qmf_description)
  60. group_qmf.add_argument('--qmf', action='store_true', default=False, help='Turn on QMF agent interface. (default: %(default)s)')
  61. group_qmf.add_argument('--qpidd', default='localhost', help='URL of qpidd to connect to. (default: %(default)s)')
  62. group_build = argparser.add_argument_group(title='Image building', description=cli_build_description)
  63. group_build.add_argument('--template', help='Template XML file to build from.')
  64. group_build.add_argument('--target', action='append', help='Cloud services to target (e.g. ec2, rhevm, vsphere, rackspace, condorcloud, etc.)')
  65. group_push = argparser.add_argument_group(title='Image pushing', description=cli_push_description)
  66. group_push.add_argument('--provider', action='append', help='Cloud service providers to push the image (e.g. ec2-us-east-1, rackspace, etc.)')
  67. group_push.add_argument('--credentials', help='Cloud provider credentials XML (i.e. <provider_credentials/> document)')
  68. group_build = argparser.add_argument_group(title='Image importing', description=cli_build_description)
  69. group_build.add_argument('--target-image', help='Target specific identifier for the image to import.')
  70. group_build.add_argument('--image-desc', help='XML document describing the imported image.')
  71. group_warehouse = argparser.add_argument_group(title='Image Warehouse', description=warehouse_description)
  72. group_warehouse.add_argument('--warehouse', default='http://localhost:9090/', help='URL of the warehouse location to store images. (default: %(default)s)')
  73. group_warehouse.add_argument('--image_bucket', help='Name of warehouse bucket to look in images. (default: %(default)s)')
  74. group_warehouse.add_argument('--build_bucket', help='Name of warehouse bucket to look in builds. (default: %(default)s)')
  75. group_warehouse.add_argument('--target_bucket', help='Name of warehouse bucket to look in for target images. (default: %(default)s)')
  76. group_warehouse.add_argument('--template_bucket', help='Name of warehouse bucket to look in for templates. (default: %(default)s)')
  77. group_warehouse.add_argument('--icicle_bucket', help='Name of warehouse bucket to look in for icicles. (default: %(default)s)')
  78. group_warehouse.add_argument('--provider_bucket', help='Name of warehouse bucket to look in for provider image instances. (default: %(default)s)')
  79. return argparser
  80. def __parse_args(self, defaults=None):
  81. if(defaults):
  82. self.argparser.set_defaults(**defaults)
  83. if(len(sys.argv) == 1):
  84. self.argparser.print_help()
  85. sys.exit()
  86. elif(sys.argv[0].endswith("imagefactory")):
  87. return self.argparser.parse_args()
  88. elif(sys.argv[0].endswith("unittest")):
  89. return self.argparser.parse_args('--image_bucket unittests_images --build_bucket unittests_builds --target_bucket unittests_target_images --template_bucket unittests_templates --icicle_bucket unittests_icicles --provider_bucket unittests_provider_images'.split())
  90. else:
  91. return self.argparser.parse_args([])
  92. def __parse_arguments(self):
  93. self.argparser = self.__new_argument_parser()
  94. configuration = self.__parse_args()
  95. if (os.path.isfile(configuration.config)):
  96. try:
  97. config_file = open(configuration.config)
  98. uconfig = json.load(config_file)
  99. # coerce this dict to ascii for python 2.6
  100. config = {}
  101. for k, v in uconfig.items():
  102. if(type(v) == str):
  103. config[k.encode('ascii')]=v.encode('ascii')
  104. else:
  105. config[k.encode('ascii')]=v
  106. configuration = self.__parse_args(defaults=config)
  107. except IOError, e:
  108. self.log.exception(e)
  109. return configuration.__dict__
  110. def __add_jeos_image(self, image_detail):
  111. # our multi-dimensional-dict has the following keys
  112. # target - provider - os - version - arch
  113. for i in range(6):
  114. image_detail[i] = image_detail[i].strip()
  115. ( target, provider, os, version, arch, provider_image_id) = image_detail
  116. if not (target in self.jeos_images):
  117. self.jeos_images[target] = {}
  118. if not (provider in self.jeos_images[target]):
  119. self.jeos_images[target][provider] = {}
  120. if not (os in self.jeos_images[target][provider]):
  121. self.jeos_images[target][provider][os] = {}
  122. if not (version in self.jeos_images[target][provider][os]):
  123. self.jeos_images[target][provider][os][version] = {}
  124. if arch in self.jeos_images[target][provider][os][version]:
  125. pass
  126. #TODO
  127. #We really should warn here but we have a bootstrap problem - loggin isn't initialized until after the singleton is created
  128. #self.log.warning("JEOS image defined more than once for %s - %s - %s - %s - %s" % (target, provider, os, version, arch))
  129. #self.log.warning("Replacing (%s) with (%s)" % (self.jeos_images[target][provider][os][version][arch], provider_image_id))
  130. self.jeos_images[target][provider][os][version][arch] = provider_image_id
  131. def __parse_jeos_images(self):
  132. # Loop through all JEOS configuration files to populate our jeos_images dictionary
  133. # TODO: Make this path itself configurable?
  134. config_path = '/etc/imagefactory/jeos_images/'
  135. listing = os.listdir(config_path)
  136. for infile in listing:
  137. fileIN = open(config_path + infile, "r")
  138. line = fileIN.readline()
  139. while line:
  140. if line[0] == "#":
  141. # Comment
  142. pass
  143. if len(line.strip()) == 0:
  144. # Whitespace
  145. pass
  146. image_detail = line.split(":")
  147. if len(image_detail) == 6:
  148. self.__add_jeos_image(image_detail)
  149. else:
  150. pass
  151. #TODO
  152. #We really should warn here but we have a bootstrap problem - loggin isn't initialized until after the singleton is created
  153. #self.log.warning("Found unparsable JEOS config line in (%s)" % (config_path + infile))
  154. line = fileIN.readline()