Merge "Improve server-side caching."

This commit is contained in:
Jenkins 2013-10-28 11:05:29 +00:00 committed by Gerrit Code Review
commit 229645c468
12 changed files with 508 additions and 271 deletions

6
.gitignore vendored
View File

@ -26,6 +26,9 @@ pip-log.txt
.tox
nosetests.xml
AUTHORS
Changelog
# Translations
*.mo
@ -34,4 +37,5 @@ nosetests.xml
.project
.pydevproject
.idea
etc/murano-repository.conf
/etc/murano-repository.conf

View File

@ -1,4 +0,0 @@
efedorova <efedorova@mirantis.com>
Ekaterina Fedorova <efedorova@mirantis.com>
EkaterinaFedorova <efedorova@mirantis.com>
Timur Sufiev <tsufiev@mirantis.com>

189
ChangeLog
View File

@ -1,189 +0,0 @@
commit 9cf280bdedc56a320ea60ca40b0bf54127aa0e4e
Author: Ekaterina Fedorova <efedorova@mirantis.com>
Date: Wed Oct 23 19:58:40 2013 +0400
Enable relative path for service manifest
Change-Id: I5fc5edd9abe0c4915d26282d5e71f6b80f437b28
commit c6a3f103ffc84aecca13ff2cc47274cbfdd464c1
Author: Ekaterina Fedorova <efedorova@mirantis.com>
Date: Tue Oct 22 15:40:46 2013 +0400
Fix bugs
1) Handle hash_sum = None situation
2) Add workflows to horizon archive
Change-Id: Ie44e43bdabab239fbdfdcaae90c533f663041dd3
commit d121a4195342fe3d9517a6f8f6176372d2e62ee9
Author: Timur Sufiev <tsufiev@mirantis.com>
Date: Mon Oct 21 20:48:28 2013 +0400
Implement server-side caching.
For the beginning, let's place server package cache into
muranorepository/api dir (this path can be easily got with
v1_api.root_path).
Change-Id: I7acbb174491f153eb340efb92ed3b0ce4c5f840f
Implements-feature: MRN-1149
commit b6613f9ecb5b90baf070f5c581a218d503b47e19
Author: Timur Sufiev <tsufiev@mirantis.com>
Date: Mon Oct 21 16:36:13 2013 +0400
Add authentication against Keystone.
Change-Id: Ifb581cc809074354d7db1404c28561ec722cf0f0
Implements-feature: MRN-1146.
commit 367d90f116d399754436060ddb221539911c2211
Author: Ekaterina Fedorova <efedorova@mirantis.com>
Date: Mon Oct 21 11:45:08 2013 +0400
Add some unit tests
Refactor v1 api and archiver
Change-Id: I193023dd8eca4f8cc665a29a6b86698bb38edc83
commit de388f5e64d887ff6b20790fb540c05ab43dacf7
Author: efedorova <efedorova@mirantis.com>
Date: Thu Oct 17 19:18:08 2013 +0400
Refactoring API and Archiver module
* Set uo manifest.in and tox.ini
* Add test module
Change-Id: I265401658922c75b50db4d1232af17215ee1b6fc
commit e4b9fe765e912a13ff02a394b329ecd117a0edb7
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 15 19:03:09 2013 +0400
Fix buf with manifests listing
commit b24d260524d16dce96a682fd32629951e2ac17ee
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 15 18:47:27 2013 +0400
Update api
commit ecb0c93b3077755192929fa8ddf045ef43d43112
Author: efedorova <efedorova@mirantis.com>
Date: Mon Oct 14 16:54:00 2013 +0400
Fix typos
commit c46bfbde86728d689677a2d7d484b2db04893186
Author: efedorova <efedorova@mirantis.com>
Date: Mon Oct 14 16:34:33 2013 +0400
Remove service to muranorepository
Add venv support
Update requirements
commit 28cbd261871038cf1fc4fa67d36c26ae9e9a4747
Author: efedorova <efedorova@mirantis.com>
Date: Mon Oct 14 13:27:09 2013 +0400
Fix bug with subfolder copying
Save path in manifest object in relative way, not in absolute
commit e98258043d9acbbf8f13d3017eebba9e04066cc9
Author: efedorova <efedorova@mirantis.com>
Date: Mon Oct 14 11:07:48 2013 +0400
Add wsgi support.
Add config file
Fix interacting with consts
Change section names in manifests to correspond data_type
commit f40fe7372c220fbf6c29acd80186c34a515f9792
Author: efedorova <efedorova@mirantis.com>
Date: Fri Oct 11 13:17:35 2013 +0400
Add api versioning
commit eb3b446a9f0535709c393620680f9c0c005a6eff
Author: efedorova <efedorova@mirantis.com>
Date: Thu Oct 10 19:29:15 2013 +0400
Unite root_dir with data_type root_dir
commit 31472fb11b498b99d34b1d48a75643785729f451
Author: efedorova <efedorova@mirantis.com>
Date: Thu Oct 10 18:14:56 2013 +0400
All api calls implemented
commit e1b704c61d76d204ce30c9822c9daa9fcda86c8c
Author: efedorova <efedorova@mirantis.com>
Date: Thu Oct 10 14:40:17 2013 +0400
Add test.py with api calls
commit b0c04f614e04f02a36e4435ff8d9e27f42271828
Author: efedorova <efedorova@mirantis.com>
Date: Thu Oct 10 14:33:57 2013 +0400
First version of murano Api added
commit ac04b4e1b74868ebb2b71ef22008e886e3be01fe
Author: efedorova <efedorova@mirantis.com>
Date: Wed Oct 9 12:05:20 2013 +0400
Update the result archive structure
commit 63bd68cc2a87e961874eabf240be58912d6ec23a
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 8 20:09:29 2013 +0400
Add initial Archiver
commit 7266c3b98c5851db00c7207bbdff60bdd9e71350
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 8 16:29:06 2013 +0400
Fixed typos
Add full manifest class defenition
commit 8f18a1b75b68d8c97efd57673b160a9ceda608a3
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 8 16:25:07 2013 +0400
Add Manifest class
Add valid fields if all files specified in manifests exists
commit 77cefffbf829ed8b5de0db24d2d4479ec6ce1223
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 8 14:55:48 2013 +0400
Add new files
commit 20fafd31acfe062c1a06eeb299ef38ed27bbbbe7
Author: efedorova <efedorova@mirantis.com>
Date: Tue Oct 8 12:12:37 2013 +0400
Update service manifests
Add parser.py
commit 3c2b1b65f16b93b7bd3c542844aa4c70f48c3ec3
Author: efedorova <efedorova@mirantis.com>
Date: Mon Oct 7 15:30:11 2013 +0400
Initial commit
commit 87ce33fcf7b03e2722a636e641eb72ea87d9f38d
Author: EkaterinaFedorova <efedorova@mirantis.com>
Date: Mon Oct 7 04:10:43 2013 -0700
Initial commit

View File

@ -0,0 +1,24 @@
version: 0.1
service_display_name: Demo Service
description: >-
<strong> Demo Service </strong>
shows how Murano is working.
full_service_name: demoService
author: Mirantis Inc.
service_version: 1.0
enabled: True
ui:
- Demo.yaml
workflows:
- Demo.xml
heat:
- Demo.template
- Linux.template
agent:
- Demo.template

View File

@ -0,0 +1,127 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"KeyName": {
"Description": "Key Pair name for Load Balancer",
"Type": "String",
"Default": "murano-lb-key"
}
},
"Resources": {
"$instanceName": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "$instanceType",
"ImageId": "$imageName",
"AvailabilityZone": "$availabilityZone",
"UserData": "$userData",
"NetworkInterfaces": [ { "Ref": "$instancePort" } ]
}
},
"$instancePort": {
"Type": "OS::Quantum::Port",
"Properties": {
"network_id": {
"Ref": "network"
},
"security_groups" : [ { "Ref" : "MuranoDefaultSecurityGroup"}],
"fixed_ips": [
{
"subnet_id": {
"Ref": "subnet"
}
}
]
}
},
"MuranoDefaultSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "22",
"IpProtocol": "tcp",
"FromPort": "22",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "23",
"IpProtocol": "tcp",
"FromPort": "23",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "-1",
"IpProtocol": "icmp",
"FromPort": "-1",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort" : "1",
"ToPort": "65535",
"CidrIp": "10.0.0.0/24"
},
{
"IpProtocol": "udp",
"FromPort" : "1",
"ToPort": "65535",
"CidrIp": "10.0.0.0/24"
}
],
"GroupDescription": "Default security group for Linux Murano Environments"
}
},
"network": {
"Type": "OS::Quantum::Net",
"Properties": {
"name": "$networkName"
}
},
"subnet": {
"Type": "OS::Quantum::Subnet",
"Properties": {
"network_id": {
"Ref": "network"
},
"ip_version": 4,
"cidr": "10.0.0.0/24",
"dns_nameservers": ["8.8.8.8"],
"allocation_pools": [
{
"start": "10.0.0.20",
"end": "10.0.0.250"
}
]
}
},
"router": {
"Type": "OS::Quantum::Router"
},
"router_interface": {
"Type": "OS::Quantum::RouterInterface",
"Properties": {
"router_id": {
"Ref": "router"
},
"subnet_id": {
"Ref": "subnet"
}
}
},
"router_gateway": {
"Type": "OS::Quantum::RouterGateway",
"Properties": {
"router_id": {
"Ref": "router"
},
"network_id": "$externalNetworkId"
}
}
},
"Outputs": {
}
}

View File

@ -0,0 +1,74 @@
#!/bin/sh
#
#
#install app
rpm -aq | grep $1 > /dev/null
if [ $? -ne 0 ];then
yum install $1 --assumeyes --quiet
if [ $? -ne 0 ]; then
echo -e "Can't install $1, exiting..."
exit 1
fi
else
echo "$1 already installed."
fi
#find iptables and add telnet rule
iptcmd=$(which iptables)
if [ -n "$iptcmd" ]; then
$iptcmd -nvL INPUT | grep "Telnet server access on TCP port 23" > /dev/null
if [ $? -ne 0 ]; then
$iptcmd -I INPUT 1 -p tcp -m tcp --dport 23 -j ACCEPT -m comment --comment "Telnet server access on TCP port 23"
if [ $? -ne 0 ]; then
echo -e "Can't set $1 access firewall rules, exiting..."
exit 1
else
echo "$iptcmd rule for $1 set."
fi
else
echo "$iptcmd rule for $1 exists."
fi
else
echo "There's no iptables found..."
fi
# check telnet start disabled
xinetd_tlnt_cfg=/etc/xinetd.d/telnet
if [ -f "$xinetd_tlnt_cfg" ]; then
sed -i '/disable.*=/ s/yes/no/' $xinetd_tlnt_cfg
if [ $? -ne 0 ]; then
echo "can't modify $xinetd_tlnt_cfg"
exit 1
fi
else
echo "$ serviec startup config not found under $xinetd_tlnt_cfg"
fi
#security tty for telnet
setty=/etc/securetty
lines=$(sed -ne '/^pts\/[0-9]/,/^pts\/[0-9]/ =' $setty)
if [ -z "$lines" ]; then
cat >> $setty << "EOF"
pts/0
pts/1
pts/2
pts/3
pts/4
pts/5
pts/6
pts/7
pts/8
pts/9
EOF
if [ $? -ne 0 ]; then
echo "Error occured during $setty changing..."
exit 1
fi
else
echo "$setty has pts/0-9 options..."
fi
#restart xinetd
service xinetd restart
if [ $? -ne 0 ]; then
echo "Error occured during xinetd restart..."
exit 1
fi

View File

@ -0,0 +1,86 @@
name: Linux Telnet
type: linuxTelnetService
description: >-
<strong> Linux Telnet Service </strong>
Demonstrates a simple linux agent, which installs Telnet if required.
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: Telnet service that can be installed at linux
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: dcInstances
type: instance
hidden: true
attributeNames: units
initial: 1
- name: deployTelnet
type: boolean
label: Deploy Telnet
description: >-
Indicates if the target machine has to get telnet deployed
initial: true
required: false
widgetMedia:
css: {all: [muranodashboard/css/checkbox.css]}
- name: unitNamingPattern
type: string
label: Hostname
description: >-
For your convenience instance hostname can be specified.
Enter a name or leave blank for random name generation.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
imageType: linux
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,80 @@
<workflow>
<rule match="$.services[?(@.type == 'linuxTelnetService')].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of Linux Telnet service having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating Linux instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Linux" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data template="Linux" initFile="linux_init.sh">
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Linux instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy Linux instance <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/> </parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'linuxTelnetService')].units[?(@.temp.instanceName and not @.state.TelnetInstalled)]"
desc="Units of Linux Telnet service which have got an instance deployed but have not got telnet service installed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">yum-ing telnet on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="DeployTelnet" error='exception'>
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="appName">telnet-server</mapping>
</map>
</parameter>
<success>
<set path="state.TelnetInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Telnet deployed on <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy Telnet on <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>

View File

@ -22,28 +22,57 @@ from werkzeug import secure_filename
from muranorepository.utils.parser import ManifestParser
from muranorepository.utils.archiver import Archiver
from muranorepository.consts import DATA_TYPES, MANIFEST
from muranorepository.consts import CLIENTS_DICT
from muranorepository.consts import ARCHIVE_PKG_NAME
import logging as log
from oslo.config import cfg
CONF = cfg.CONF
v1_api = Blueprint('v1', __name__)
CACHE_DIR = os.path.join(v1_api.root_path, 'cache')
if not os.path.exists(CACHE_DIR):
os.mkdir(CACHE_DIR)
def _update_hash(data_type):
client = None
for client_type, client_data_types in CLIENTS_DICT.iteritems():
if data_type in client_data_types:
client = client_type
break
if not client:
abort(404)
cache_dir = os.path.join(CACHE_DIR, client)
if not os.path.exists(cache_dir):
os.mkdir(cache_dir)
manifests = ManifestParser(CONF.manifests).parse()
archive_manager = Archiver()
existing_hash = archive_manager.get_existing_hash(cache_dir)
if existing_hash:
archive_manager.remove_existing_hash(cache_dir, existing_hash)
archive_manager.create(cache_dir, manifests, CLIENTS_DICT[client])
def _get_archive(client, hash_sum):
parser = ManifestParser(CONF.manifests)
manifests = parser.parse()
types = None
if client == 'conductor':
types = ('heat', 'agent', 'scripts', 'workflows')
elif client == 'ui':
types = ('ui',)
else:
types = CLIENTS_DICT.get(client)
if not types:
abort(404)
return Archiver().create(client, CACHE_DIR, manifests, hash_sum, types)
archive_manager = Archiver()
cache_dir = os.path.join(CACHE_DIR, client)
if not os.path.exists(cache_dir):
os.mkdir(cache_dir)
existing_hash = archive_manager.get_existing_hash(cache_dir)
if existing_hash and hash_sum is None:
log.debug('Transfering existing archive')
return os.path.join(cache_dir, existing_hash, ARCHIVE_PKG_NAME)
if archive_manager.hashes_match(cache_dir, existing_hash, hash_sum):
return None
return archive_manager.create(cache_dir, manifests, types)
def _get_locations(data_type, result_path):
@ -64,11 +93,19 @@ def _get_locations(data_type, result_path):
return jsonify({data_type: locations})
def _save_file(request, result_path):
def _save_file(request, data_type, path=None):
if path:
result_path = _compose_path(data_type, path)
#subfolder should already exists
if not os.path.exists(result_path):
abort(404)
else:
result_path = _compose_path(data_type)
file_to_upload = request.files.get('file')
if file_to_upload:
filename = secure_filename(file_to_upload.filename)
file_to_upload.save(os.path.join(result_path, filename))
_update_hash(data_type)
return jsonify(result='success')
else:
abort(400)
@ -105,9 +142,8 @@ def get_data_type_locations(data_type):
@v1_api.route('/admin/<data_type>', methods=['POST'])
def upload_file(data_type):
_check_data_type(data_type)
result_path = _compose_path(data_type)
try:
return _save_file(request, result_path)
return _save_file(request, data_type)
except:
abort(403)
@ -125,13 +161,10 @@ 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)
result_path = _compose_path(data_type, path)
# it's forbidden to upload manifests to subfolder
# it's forbidden to upload manifests to subfolders
if data_type == MANIFEST:
abort(403)
if not os.path.exists(result_path):
abort(404)
return _save_file(request, result_path)
return _save_file(request, data_type, path)
@v1_api.route('/admin/<data_type>/<path:path>', methods=['PUT'])
@ -159,22 +192,13 @@ def delete_directory_or_file(data_type, path):
if os.path.isfile(result_path):
try:
os.remove(result_path)
_update_hash(data_type)
except Exception:
abort(404)
else:
try:
# enable to delete only empty directories
os.rmdir(result_path)
except Exception:
abort(403)
return jsonify(result='success')
@v1_api.route('/admin/services', methods=['GET'])
def get_services_list():
manifests = ManifestParser(CONF.manifests).parse()
excluded_fields = set(DATA_TYPES) - set(MANIFEST)
data = []
for manifest in manifests:
data.append(dict((k, v) for k, v in manifest.__dict__.iteritems()
if not k in excluded_fields))
return jsonify(tuple(data))

View File

@ -21,3 +21,7 @@ AGENT = 'agent'
SCRIPTS = 'scripts'
DATA_TYPES = [UI, WORKFLOW, HEAT, AGENT, SCRIPTS, MANIFEST]
CLIENTS_DICT = {'conductor': (WORKFLOW, HEAT, AGENT, SCRIPTS),
'ui': (UI,)}
ARCHIVE_PKG_NAME = 'data.tar.gz'

View File

@ -18,10 +18,9 @@ import shutil
import hashlib
import logging as log
from oslo.config import cfg
from muranorepository.consts import DATA_TYPES
from muranorepository.consts import DATA_TYPES, ARCHIVE_PKG_NAME
CONF = cfg.CONF
ARCHIVE_PKG_NAME = 'data.tar.gz'
CHUNK_SIZE = 1 << 20 # 1MB
@ -75,49 +74,48 @@ class Archiver(object):
shutil.rmtree(path, ignore_errors=True)
except Exception as e:
log.error("Unable to delete temp directory: {0}".format(e))
hash_sum = self._get_hash(ARCHIVE_PKG_NAME)
pkg_dir = os.path.join(cache_dir, hash_sum)
if not os.path.exists(pkg_dir):
os.mkdir(pkg_dir)
shutil.move(ARCHIVE_PKG_NAME, os.path.join(pkg_dir, ARCHIVE_PKG_NAME))
return os.path.abspath(os.path.join(pkg_dir, ARCHIVE_PKG_NAME))
hash_folder = self._create_hash_folder(ARCHIVE_PKG_NAME, cache_dir)
try:
shutil.move(ARCHIVE_PKG_NAME, os.path.join(hash_folder,
ARCHIVE_PKG_NAME))
except Exception as e:
log.error('Unable to move created archive {0}'
' to hash folder {1} due to {2}'.format(ARCHIVE_PKG_NAME,
hash_folder,
e))
return os.path.abspath(os.path.join(hash_folder, ARCHIVE_PKG_NAME))
def _is_data_cached(self, cache_dir, hash_sum):
#ToDo: optimize archive creation: use existing cached version of
# archive package when no hash sum is provided by client
if not hash_sum:
log.warning('Hash parameter was not found in request')
return False
def get_existing_hash(self, cache_dir):
existing_caches = os.listdir(cache_dir)
if len(existing_caches) == 1:
if existing_caches[0] == hash_sum:
path = os.path.join(cache_dir, hash_sum, ARCHIVE_PKG_NAME)
if not os.path.exists(path):
raise RuntimeError(
'Archive package is missing at dir {0}'.format(
os.path.join(cache_dir, hash_sum)))
log.debug('Archive package already exists at {0} and it ' +
'matches hash-sum {1}.'.format(path, hash_sum))
return True
else:
path = os.path.join(cache_dir, hash_sum)
log.info('Archive package already exists at {0}, but it '
"doesn't match requested hash-sum {1}. "
'Deleting it.'.format(path))
shutil.rmtree(path)
return False
elif len(existing_caches) == 0:
return False
log.debug('Asserting there is just one archive in cache folder. Clear '
'folder {0} in case of Assertion Error'.format(cache_dir))
assert len(existing_caches) < 2
if not len(existing_caches):
return None
else:
raise RuntimeError('Too many cached archives at {0}'.format(
cache_dir))
path = os.path.join(cache_dir,
existing_caches[0],
ARCHIVE_PKG_NAME)
if not os.path.exists(path):
raise RuntimeError(
'Archive package is missing at dir {0}'.format(
os.path.join(cache_dir)))
return existing_caches[0]
def create(self, client_type, cache_root, manifests, hash_sum, types):
def hashes_match(self, cache_dir, existing_hash, hash_to_check):
if hash_to_check is None or existing_hash is None:
return False
if existing_hash == hash_to_check:
log.debug('Archive package matches hash-sum {0}.'.format(
hash_to_check))
return True
else:
self.remove_existing_hash(cache_dir, existing_hash)
return False
def create(self, cache_dir, manifests, types):
"""
client_type -- client asked for metadata
cache_root -- directory where cache is stored
manifests -- list of Manifest objects
hash_sum -- hash to compare to
types -- desired data types to be added to archive
return: absolute path to created archive
"""
@ -126,14 +124,6 @@ class Archiver(object):
temp_dir = tempfile.mkdtemp()
except:
temp_dir = '/tmp'
cache_dir = os.path.join(cache_root, client_type)
if not os.path.exists(cache_dir):
os.mkdir(cache_dir)
if self._is_data_cached(cache_dir, hash_sum):
return None
for data_type in types:
if data_type not in DATA_TYPES:
raise Exception("Please, specify one of the supported data "
@ -157,3 +147,20 @@ class Archiver(object):
"{1}".format(manifest.service_display_name, data_type))
return self._compose_archive(temp_dir, cache_dir)
def remove_existing_hash(self, cache_dir, hash):
path = os.path.join(cache_dir, hash)
log.info('Deleting archive package from {0}.'.format(path))
shutil.rmtree(path, ignore_errors=True)
def _create_hash_folder(self, archive_name, cache_dir):
"""
Creates folder with data archive inside that has
name equals to hash calculated from archive
Return path to created hash folder
"""
hash_sum = self._get_hash(archive_name)
pkg_dir = os.path.join(cache_dir, hash_sum)
if not os.path.exists(pkg_dir):
os.mkdir(pkg_dir)
return pkg_dir

View File

@ -13,8 +13,8 @@
# under the License.
[metadata]
name = muranorepository
version = 0.1
name = murano-repository
version = 0.4
summary = Murano Metadata Repository
description-file = README.rst
license = Apache Software License