Merge "Add new api call: add new service in one archive"

This commit is contained in:
Jenkins 2013-10-30 13:10:34 +00:00 committed by Gerrit Code Review
commit 38a5426553
2 changed files with 87 additions and 7 deletions

View File

@ -14,6 +14,7 @@
import os
import re
import tarfile
import tempfile
from flask import Blueprint, send_file
from flask import jsonify, request, abort
@ -56,7 +57,7 @@ def _update_cache(data_type):
archive_manager.create(cache_dir, manifests, CLIENTS_DICT[client])
def _get_archive(manifests, client, hash_sum):
def _get_archive(client, hash_sum):
types = CLIENTS_DICT.get(client)
archive_manager = Archiver()
cache_dir = os.path.join(CACHE_DIR, client)
@ -70,6 +71,7 @@ def _get_archive(manifests, client, hash_sum):
if archive_manager.hashes_match(cache_dir, existing_hash, hash_sum):
return None
manifests = ManifestParser().parse()
return archive_manager.create(cache_dir, manifests, types)
@ -124,17 +126,15 @@ def _check_data_type(data_type):
def _get_manifest_files(manifest):
return dict((k, v)
for k, v in manifest.__dict__.iteritems() if k in DATA_TYPES)
return dict((k, v) for k, v in manifest.__dict__.iteritems()
if k in DATA_TYPES)
@v1_api.route('/client/<path:client_type>')
def get_archive_data(client_type):
manifests = ManifestParser().parse()
if client_type not in CLIENTS_DICT.keys():
abort(404)
path_to_archive = _get_archive(manifests,
client_type,
path_to_archive = _get_archive(client_type,
request.args.get('hash'))
if path_to_archive:
return send_file(path_to_archive, mimetype='application/octet-stream')
@ -193,6 +193,7 @@ def _get_locations_in_nested_path_or_get_file(data_type, path):
@v1_api.route('/admin/<data_type>/<path:path>', methods=['POST'])
def upload_file_in_nested_path(data_type, path):
_check_data_type(data_type)
if data_type == MANIFEST:
make_response('It is forbidden to upload manifests to subfolders', 403)
return _save_file(request, data_type, path)
@ -262,3 +263,27 @@ def get_files_for_service(service_name):
if not data:
abort(404)
return jsonify(service_files=data)
@v1_api.route('/admin/services/<service_name>', methods=['POST'])
def upload_new_service(service_name):
if not re.match(r'^\w+(\.\w+)*\w+$', service_name):
abort(404)
file_to_upload = request.files.get('file')
if file_to_upload:
filename = secure_filename(file_to_upload.filename)
else:
return make_response('There is no file to upload', 403)
path_to_archive = os.path.join(CACHE_DIR, filename)
file_to_upload.save(path_to_archive)
if not tarfile.is_tarfile(path_to_archive):
return make_response('Uploading file should be a tar archive', 403)
archive_manager = Archiver()
result = archive_manager.extract(path_to_archive)
if result:
return jsonify(result='success')
else:
#ToDo: Pass error msg there
return make_response('Uploading file failed.', 400)

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import glob
import tarfile
import tempfile
import shutil
@ -82,7 +83,7 @@ class Archiver(object):
return hsum
else:
log.info(
'Archive {0} does not exist, no hash to calculate'.format(
"Archive '{0}' doesn't exist, no hash to calculate".format(
archive_path))
return None
@ -209,3 +210,57 @@ class Archiver(object):
path = os.path.join(cache_dir, hash)
log.info('Deleting archive package from {0}.'.format(path))
shutil.rmtree(path, ignore_errors=True)
def extract(self, path_to_archive):
"""
path_to_archive - path to archive to extract from
---
return value - True if succeeded , False otherwise
"""
try:
path_to_extract = tempfile.mkdtemp()
with tarfile.open(path_to_archive) as archive:
archive.extractall(path_to_extract)
# assert manifest file
manifests = glob.glob(os.path.join(path_to_extract,
'*-manifest.yaml'))
if len(manifests) != 1:
raise AssertionError('There should be one '
'manifest file in archive')
shutil.copy(manifests[0], CONF.manifests)
#Todo: Check manifest is valid
for item in os.listdir(path_to_extract):
item_path = os.path.join(path_to_extract, item)
if os.path.isdir(item_path):
if item in DATA_TYPES:
file_list = []
for path, subdirs, files in os.walk(item_path):
# ToDo: Extract to a separate
# function and use in v1.py also
nested = False
if path != item_path:
base, subfolder = path.rsplit(item_path, 2)
nested = True
for name in files:
if nested:
name = os.path.join(subfolder[1:], name)
file_list.append(name)
self._copy_data(file_list,
item_path,
os.path.join(
CONF.manifests,
self.src_directories[item]),
overwrite=False)
else:
log.warning(
'Uploading archive contents folder {0} that does '
'not correspond to supported data types: {1}. '
'It will be ignored'.format(item, DATA_TYPES))
return True
except Exception as e:
log.error('Unable to extract archive due to {0}'.format(e.message))
return False
finally:
os.remove(path_to_archive)
shutil.rmtree(path_to_extract, ignore_errors=True)