Taskotron - hotfix imgfac to enable /raw_image route
This commit is contained in:
parent
a7f87fb817
commit
656ac70857
3 changed files with 394 additions and 1 deletions
|
@ -69,7 +69,7 @@ buildmaster_pubkey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYzVmGYh6EHH8UAlgX6FI
|
|||
############################################################
|
||||
|
||||
imagefactory_user: imgfac_user
|
||||
imagefactory_user_home: /home/fedora/imgfac_user
|
||||
imagefactory_user_home: '/home/{{imagefactory_user}}'
|
||||
imagefactory_shared_dir: '{{imagefactory_user_home}}/images'
|
||||
|
||||
|
||||
|
|
390
roles/taskotron/imagefactory/files/hotfix_imgfac_RESTv2.py
Normal file
390
roles/taskotron/imagefactory/files/hotfix_imgfac_RESTv2.py
Normal file
|
@ -0,0 +1,390 @@
|
|||
#
|
||||
# Copyright 2012 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http:/www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
sys.path.insert(1, '%s/imgfac/rest' % sys.path[0])
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
from bottle import *
|
||||
from imgfac.rest.RESTtools import *
|
||||
from imgfac.rest.OAuthTools import oauth_protect
|
||||
from imgfac.BuildDispatcher import BuildDispatcher
|
||||
from imgfac.PluginManager import PluginManager
|
||||
from imgfac.PersistentImageManager import PersistentImageManager
|
||||
from imgfac.Version import VERSION as VERSION
|
||||
from imgfac.picklingtools.xmldumper import *
|
||||
from imgfac.Builder import Builder
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
rest_api = Bottle(catchall=True)
|
||||
|
||||
IMAGE_TYPES = {'BaseImage': 'base_image', 'TargetImage': 'target_image', 'ProviderImage': 'provider_image',
|
||||
'base_images': 'BaseImage', 'target_images': 'TargetImage', 'provider_images': 'ProviderImage'}
|
||||
|
||||
def converted_response(resp_dict):
|
||||
if('xml' in request.get_header('Accept', '')):
|
||||
response.set_header('Content-Type', request.get_header('Accept', None))
|
||||
xml_options = XML_DUMP_STRINGS_AS_STRINGS | XML_DUMP_PRETTY | XML_DUMP_POD_LIST_AS_XML_LIST
|
||||
string_stream = cStringIO.StringIO()
|
||||
WriteToXMLStream(resp_dict, string_stream, options=xml_options)
|
||||
converted_response = string_stream.getvalue()
|
||||
return converted_response
|
||||
else:
|
||||
return resp_dict
|
||||
|
||||
@rest_api.get('/imagefactory')
|
||||
@log_request
|
||||
@check_accept_header
|
||||
def api_info():
|
||||
return converted_response({'name':'imagefactory', 'version':VERSION, 'api_version':'2.0'})
|
||||
|
||||
@rest_api.get('/imagefactory/base_images/<image_id>/raw_image')
|
||||
@rest_api.get('/imagefactory/target_images/<image_id>/raw_image')
|
||||
@rest_api.get('/imagefactory/provider_images/<image_id>/raw_image')
|
||||
@rest_api.get('/imagefactory/base_images/<base_image_id>/target_images/<image_id>/raw_image')
|
||||
@rest_api.get('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>/provider_images/<image_id>/raw_image')
|
||||
@rest_api.get('/imagefactory/target_images/<target_image_id>/provider_images/<image_id>/raw_image')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def get_image_file(image_id, base_image_id=None, target_image_id=None, provider_image_id=None):
|
||||
try:
|
||||
image = PersistentImageManager.default_manager().image_with_id(image_id)
|
||||
if(not image):
|
||||
raise HTTPResponse(status=404, output='No image found with id: %s' % image_id)
|
||||
path, filename = os.path.split(image.data)
|
||||
return static_file(filename, path, download=True)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
|
||||
|
||||
@rest_api.get('/imagefactory/<image_collection>')
|
||||
@rest_api.get('/imagefactory/base_images/<base_image_id>/<image_collection>')
|
||||
@rest_api.get('/imagefactory/target_images/<target_image_id>/<image_collection>')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def list_images(image_collection, base_image_id=None, target_image_id=None, list_url=None):
|
||||
try:
|
||||
_type = IMAGE_TYPES[image_collection]
|
||||
if _type:
|
||||
fetch_spec = {'type': _type}
|
||||
if base_image_id:
|
||||
fetch_spec['base_image_id'] = base_image_id
|
||||
if target_image_id:
|
||||
fetch_spec['target_image_id'] = target_image_id
|
||||
else:
|
||||
raise HTTPResponse(status=404, output='%s not found' % image_collection)
|
||||
|
||||
fetched_images = PersistentImageManager.default_manager().images_from_query(fetch_spec)
|
||||
images = list()
|
||||
_url = list_url if list_url else request.url
|
||||
for image in fetched_images:
|
||||
resp_item = {image_collection[0:-1]:
|
||||
{'_type':type(image).__name__,
|
||||
'id':image.identifier,
|
||||
'href':'%s/%s' % (_url, image.identifier)}
|
||||
}
|
||||
images.append(resp_item)
|
||||
|
||||
return converted_response({image_collection:images})
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
|
||||
@rest_api.post('/imagefactory/<image_collection>')
|
||||
@rest_api.post('/imagefactory/base_images/<base_image_id>/<image_collection>')
|
||||
@rest_api.post('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>/<image_collection>')
|
||||
@rest_api.post('/imagefactory/target_images/<target_image_id>/<image_collection>')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def create_image(image_collection, base_image_id=None, target_image_id=None):
|
||||
try:
|
||||
image_type = image_collection[0:-1]
|
||||
content_type = request.headers.get('Content-Type')
|
||||
form_data = form_data_for_content_type(content_type)
|
||||
if(('application/x-www-form-urlencoded' in content_type) or ('multipart/form-data' in content_type)):
|
||||
request_data = form_data
|
||||
else:
|
||||
request_data = form_data.get(image_type)
|
||||
if(not request_data):
|
||||
raise HTTPResponse(status=400, output='%s not found in request.' % image_type)
|
||||
|
||||
req_base_img_id = request_data.get('base_image_id')
|
||||
req_target_img_id = request_data.get('target_image_id')
|
||||
base_img_id = req_base_img_id if req_base_img_id else base_image_id
|
||||
target_img_id = req_target_img_id if req_target_img_id else target_image_id
|
||||
|
||||
if(image_collection == 'base_images'):
|
||||
builder = BuildDispatcher().builder_for_base_image(template=request_data.get('template'),
|
||||
parameters=request_data.get('parameters'))
|
||||
image = builder.base_image
|
||||
elif(image_collection == 'target_images'):
|
||||
builder = BuildDispatcher().builder_for_target_image(target=request_data.get('target'),
|
||||
image_id=base_img_id,
|
||||
template=request_data.get('template'),
|
||||
parameters=request_data.get('parameters'))
|
||||
image = builder.target_image
|
||||
elif(image_collection == 'provider_images'):
|
||||
_provider = request_data.get('provider')
|
||||
_credentials = request_data.get('credentials')
|
||||
_target = request_data.get('target')
|
||||
if(_provider and _credentials and _target):
|
||||
builder = BuildDispatcher().builder_for_provider_image(provider=_provider,
|
||||
credentials=_credentials,
|
||||
target=_target,
|
||||
image_id=target_img_id,
|
||||
template=request_data.get('template'),
|
||||
parameters=request_data.get('parameters'))
|
||||
image = builder.provider_image
|
||||
else:
|
||||
_credentials = 'REDACTED' if _credentials else None
|
||||
raise HTTPResponse(status=400, output="Missing key/value pair: provider(%s), credentials(%s), target(%s)" % (_provider, _credentials, _target))
|
||||
else:
|
||||
raise HTTPResponse(status=404, output="%s not found" % image_collection)
|
||||
|
||||
_response = {'_type':type(image).__name__,
|
||||
'id':image.identifier,
|
||||
'href':'%s/%s' % (request.url, image.identifier)}
|
||||
for key in image.metadata():
|
||||
if key not in ('identifier', 'data'):
|
||||
_response[key] = getattr(image, key, None)
|
||||
|
||||
response.status = 202
|
||||
return converted_response({image_collection[0:-1]:_response})
|
||||
except KeyError as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=400, output='Missing value for key: %s' % e)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
|
||||
@rest_api.get('/imagefactory/<collection_type>/<image_id>')
|
||||
@rest_api.get('/imagefactory/base_images/<base_image_id>/<collection_type>/<image_id>')
|
||||
@rest_api.get('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>/<collection_type>/<image_id>')
|
||||
@rest_api.get('/imagefactory/target_images/<target_image_id>/<collection_type>/<image_id>')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def image_with_id(collection_type, image_id, base_image_id=None, target_image_id=None, provider_image_id=None):
|
||||
try:
|
||||
img_class = IMAGE_TYPES[collection_type]
|
||||
if img_class:
|
||||
fetch_spec = {'type': img_class, 'identifier': image_id}
|
||||
try:
|
||||
image = PersistentImageManager.default_manager().images_from_query(fetch_spec)[0]
|
||||
_type = type(image).__name__
|
||||
_response = {'_type': _type,
|
||||
'id': image.identifier,
|
||||
'href': request.url}
|
||||
for key in image.metadata():
|
||||
if key not in ('identifier', 'data', 'base_image_id', 'target_image_id'):
|
||||
_response[key] = getattr(image, key, None)
|
||||
|
||||
api_url = '%s://%s/imagefactory' % (request.urlparts[0], request.urlparts[1])
|
||||
|
||||
if (_type == "BaseImage"):
|
||||
_objtype = 'base_image'
|
||||
_response['target_images'] = list_images('target_images',
|
||||
base_image_id=image.identifier,
|
||||
list_url='%s/target_images' % api_url)
|
||||
elif (_type == "TargetImage"):
|
||||
_objtype = 'target_image'
|
||||
base_image_id = image.base_image_id
|
||||
if (base_image_id):
|
||||
base_image_href = '%s/base_images/%s' % (api_url, base_image_id)
|
||||
base_image_dict = {'_type': 'BaseImage', 'id': base_image_id, 'href': base_image_href}
|
||||
_response['base_image'] = base_image_dict
|
||||
else:
|
||||
_response['base_image'] = None
|
||||
_response['provider_images'] = list_images('provider_images',
|
||||
target_image_id=image.identifier,
|
||||
list_url='%s/provider_images' % api_url)
|
||||
elif (_type == "ProviderImage"):
|
||||
_objtype = 'provider_image'
|
||||
target_image_id = image.target_image_id
|
||||
if (target_image_id):
|
||||
target_image_href = '%s/target_images/%s' % (api_url, target_image_id)
|
||||
target_image_dict = {'_type': 'TargetImage', 'id': target_image_id, 'href': target_image_href}
|
||||
_response['target_image'] = target_image_dict
|
||||
else:
|
||||
_response['target_image'] = None
|
||||
else:
|
||||
log.error("Returning HTTP status 500 due to unknown image type: %s" % _type)
|
||||
raise HTTPResponse(status=500, output='Bad type for found object: %s' % _type)
|
||||
|
||||
response.status = 200
|
||||
return converted_response({_objtype: _response})
|
||||
|
||||
except IndexError as e:
|
||||
log.warning(e)
|
||||
raise HTTPResponse(status=404, output='No %s found with id: %s' % (img_class, image_id))
|
||||
else:
|
||||
raise HTTPResponse(status=404, output='Unknown resource type: %s' % collection_type)
|
||||
except KeyError as e:
|
||||
if collection_type == 'plugins':
|
||||
return get_plugins(plugin_id=image_id)
|
||||
else:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
|
||||
@rest_api.delete('/imagefactory/<collection_type>/<image_id>')
|
||||
@rest_api.delete('/imagefactory/base_images/<base_image_id>/<collection_type>/<image_id>')
|
||||
@rest_api.delete('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>/<collection_type>/<image_id>')
|
||||
@rest_api.delete('/imagefactory/target_images/<target_image_id>/<collection_type>/<image_id>')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def delete_image_with_id(image_id, collection_type=None, base_image_id=None, target_image_id=None, provider_image_id=None):
|
||||
try:
|
||||
response.status = 204
|
||||
image = PersistentImageManager.default_manager().image_with_id(image_id)
|
||||
if(not image):
|
||||
raise HTTPResponse(status=404, output='No image found with id: %s' % image_id)
|
||||
image_class = type(image).__name__
|
||||
builder = Builder()
|
||||
content_type = request.headers.get('Content-Type')
|
||||
form_data = form_data_for_content_type(content_type)
|
||||
required_values = set(['provider', 'credentials', 'target'])
|
||||
|
||||
if form_data:
|
||||
root_object = form_data.get(IMAGE_TYPES.get(image_class))
|
||||
if root_object and (type(root_object) is dict):
|
||||
request_data = root_object
|
||||
else:
|
||||
request_data = form_data
|
||||
|
||||
if image_class == 'ProviderImage':
|
||||
missing_values = required_values.difference(request_data)
|
||||
if len(missing_values) > 0:
|
||||
raise HTTPResponse(status=400, output='Missing required values: %s' % missing_values)
|
||||
|
||||
builder.delete_image(provider=request_data.get('provider'),
|
||||
credentials=request_data.get('credentials'),
|
||||
target=request_data.get('target'),
|
||||
image_object=image,
|
||||
parameters=request_data.get('parameters'))
|
||||
else:
|
||||
if image_class == 'ProviderImage':
|
||||
raise HTTPResponse(status=400, output='Missing required values:%s' % required_values)
|
||||
else:
|
||||
builder.delete_image(provider=None, credentials=None, target=None, image_object=image, parameters=None)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output=e)
|
||||
|
||||
@rest_api.get('/imagefactory/plugins')
|
||||
@rest_api.get('/imagefactory/plugins/')
|
||||
@rest_api.get('/imagefactory/plugins/<plugin_id>')
|
||||
@log_request
|
||||
@oauth_protect
|
||||
@check_accept_header
|
||||
def get_plugins(plugin_id=None):
|
||||
try:
|
||||
response.status = 200
|
||||
plugin_mgr = PluginManager()
|
||||
if(plugin_id):
|
||||
plugin = plugin_mgr.plugins[plugin_id].copy()
|
||||
plugin.update({'_type':'plugin',
|
||||
'id':plugin_id,
|
||||
'href':'%s/%s' % (request.url, plugin_id)})
|
||||
return converted_response(plugin)
|
||||
else:
|
||||
plugins = plugin_mgr.plugins.copy()
|
||||
for plugin in plugins:
|
||||
plugins[plugin].update({'_type':'plugin',
|
||||
'id':plugin,
|
||||
'href':'%s/%s' % (request.url, plugin)})
|
||||
return converted_response({'plugins':plugins.values()})
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output='%s %s' % (e, traceback.format_exc()))
|
||||
|
||||
@rest_api.get('/imagefactory/jeos')
|
||||
@log_request
|
||||
@check_accept_header
|
||||
def get_jeos_config():
|
||||
try:
|
||||
jeos_confs = dict()
|
||||
jeos_conf_list = ApplicationConfiguration().configuration['jeos_config']
|
||||
for item in jeos_conf_list:
|
||||
jeos_confs[jeos_conf_list.index(item)] = item
|
||||
return converted_response(jeos_confs)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output='%s %s' % (e, traceback.format_exc()))
|
||||
|
||||
@rest_api.get('/imagefactory/jeos/images')
|
||||
@rest_api.get('/imagefactory/jeos/images/<jeos_id>')
|
||||
@log_request
|
||||
@check_accept_header
|
||||
def get_jeos_info(jeos_id=None):
|
||||
try:
|
||||
if jeos_id:
|
||||
return HTTPResponse(status=501)
|
||||
|
||||
response.status = 200
|
||||
return converted_response(ApplicationConfiguration().jeos_images)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
raise HTTPResponse(status=500, output='%s %s' % (e, traceback.format_exc()))
|
||||
|
||||
# Things we have not yet implemented
|
||||
@rest_api.get('/imagefactory/targets')
|
||||
@rest_api.get('/imagefactory/targets/<target_id>')
|
||||
@rest_api.get('/imagefactory/targets/<target_id>/providers')
|
||||
@rest_api.get('/imagefactory/targets/<target_id>/providers/<provider_id>')
|
||||
@log_request
|
||||
@check_accept_header
|
||||
def method_not_implemented(**kw):
|
||||
"""
|
||||
@return 501 Not Implemented
|
||||
"""
|
||||
raise HTTPResponse(status=501)
|
||||
|
||||
# Things we don't plan to implement
|
||||
#@rest_api.route('/imagefactory', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/base_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/base_images/<base_image_id>', method=('PUT','POST'))
|
||||
#@rest_api.route('/imagefactory/target_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/target_images/<target_image_id>', method=('PUT','POST'))
|
||||
#@rest_api.route('/imagefactory/target_images/<target_image_id>/provider_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/provider_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/provider_images/<provider_image_id>', method=('PUT','POST'))
|
||||
#@rest_api.route('/imagefactory/base_images/<base_image_id>/target_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>', method=('PUT','POST'))
|
||||
#@rest_api.route('/imagefactory/base_images/<base_image_id>/target_images/<target_image_id>/provider_images', method=('PUT','DELETE'))
|
||||
#@rest_api.route('/imagefactory/targets', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/targets/<target_id>', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/targets/<target_id>/providers', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/targets/<target_id>/providers/<provider_id>', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/jeos', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/jeos/<jeos_id>', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/plugins', method=('PUT','POST','DELETE'))
|
||||
#@rest_api.route('/imagefactory/plugins/<plugin_id>', method=('PUT','POST','DELETE'))
|
||||
#def method_not_allowed(**kw):
|
||||
# """
|
||||
# @return 405 Method Not Allowed
|
||||
# """
|
||||
# raise HTTPResponse(status=405)
|
|
@ -9,6 +9,9 @@
|
|||
- name: copy imagefactory.conf config file
|
||||
copy: src=imagefactory.conf dest=/etc/imagefactory/imagefactory.conf owner=root group=root mode=0644
|
||||
|
||||
- name: hotfix imagefactory's REST api to allow file download
|
||||
copy: src=hotfix_imgfac_RESTv2.py dest=/usr/lib/python2.7/site-packages/imgfac/rest/RESTv2.py owner=root group=root mode=0644
|
||||
|
||||
- name: enable imagefactory
|
||||
service: name=imagefactoryd state=started enabled=yes
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue