diff --git a/.gitignore b/.gitignore index f76f900..1b69292 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index e5d4cc1..0000000 --- a/AUTHORS +++ /dev/null @@ -1,4 +0,0 @@ -efedorova -Ekaterina Fedorova -EkaterinaFedorova -Timur Sufiev \ No newline at end of file diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index ce6afa6..0000000 --- a/ChangeLog +++ /dev/null @@ -1,189 +0,0 @@ -commit 9cf280bdedc56a320ea60ca40b0bf54127aa0e4e -Author: Ekaterina Fedorova -Date: Wed Oct 23 19:58:40 2013 +0400 - - Enable relative path for service manifest - - Change-Id: I5fc5edd9abe0c4915d26282d5e71f6b80f437b28 - -commit c6a3f103ffc84aecca13ff2cc47274cbfdd464c1 -Author: Ekaterina Fedorova -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 -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 -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 -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 -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 -Date: Tue Oct 15 19:03:09 2013 +0400 - - Fix buf with manifests listing - -commit b24d260524d16dce96a682fd32629951e2ac17ee -Author: efedorova -Date: Tue Oct 15 18:47:27 2013 +0400 - - Update api - -commit ecb0c93b3077755192929fa8ddf045ef43d43112 -Author: efedorova -Date: Mon Oct 14 16:54:00 2013 +0400 - - Fix typos - -commit c46bfbde86728d689677a2d7d484b2db04893186 -Author: efedorova -Date: Mon Oct 14 16:34:33 2013 +0400 - - Remove service to muranorepository - - Add venv support - Update requirements - -commit 28cbd261871038cf1fc4fa67d36c26ae9e9a4747 -Author: efedorova -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 -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 -Date: Fri Oct 11 13:17:35 2013 +0400 - - Add api versioning - -commit eb3b446a9f0535709c393620680f9c0c005a6eff -Author: efedorova -Date: Thu Oct 10 19:29:15 2013 +0400 - - Unite root_dir with data_type root_dir - -commit 31472fb11b498b99d34b1d48a75643785729f451 -Author: efedorova -Date: Thu Oct 10 18:14:56 2013 +0400 - - All api calls implemented - -commit e1b704c61d76d204ce30c9822c9daa9fcda86c8c -Author: efedorova -Date: Thu Oct 10 14:40:17 2013 +0400 - - Add test.py with api calls - -commit b0c04f614e04f02a36e4435ff8d9e27f42271828 -Author: efedorova -Date: Thu Oct 10 14:33:57 2013 +0400 - - First version of murano Api added - -commit ac04b4e1b74868ebb2b71ef22008e886e3be01fe -Author: efedorova -Date: Wed Oct 9 12:05:20 2013 +0400 - - Update the result archive structure - -commit 63bd68cc2a87e961874eabf240be58912d6ec23a -Author: efedorova -Date: Tue Oct 8 20:09:29 2013 +0400 - - Add initial Archiver - -commit 7266c3b98c5851db00c7207bbdff60bdd9e71350 -Author: efedorova -Date: Tue Oct 8 16:29:06 2013 +0400 - - Fixed typos - - Add full manifest class defenition - -commit 8f18a1b75b68d8c97efd57673b160a9ceda608a3 -Author: efedorova -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 -Date: Tue Oct 8 14:55:48 2013 +0400 - - Add new files - -commit 20fafd31acfe062c1a06eeb299ef38ed27bbbbe7 -Author: efedorova -Date: Tue Oct 8 12:12:37 2013 +0400 - - Update service manifests - - Add parser.py - -commit 3c2b1b65f16b93b7bd3c542844aa4c70f48c3ec3 -Author: efedorova -Date: Mon Oct 7 15:30:11 2013 +0400 - - Initial commit - -commit 87ce33fcf7b03e2722a636e641eb72ea87d9f38d -Author: EkaterinaFedorova -Date: Mon Oct 7 04:10:43 2013 -0700 - - Initial commit \ No newline at end of file diff --git a/Services/demo-manifest.yaml b/Services/demo-manifest.yaml new file mode 100644 index 0000000..42fd155 --- /dev/null +++ b/Services/demo-manifest.yaml @@ -0,0 +1,24 @@ +version: 0.1 +service_display_name: Demo Service + +description: >- + Demo Service + 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 diff --git a/Services/heat_templates/Linux.template b/Services/heat_templates/Linux.template new file mode 100644 index 0000000..00ee06e --- /dev/null +++ b/Services/heat_templates/Linux.template @@ -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": { + } +} diff --git a/Services/scripts/TelnetDeploy.sh b/Services/scripts/TelnetDeploy.sh new file mode 100644 index 0000000..7ee6529 --- /dev/null +++ b/Services/scripts/TelnetDeploy.sh @@ -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 diff --git a/Services/ui_forms/LinuxTelnet.yaml b/Services/ui_forms/LinuxTelnet.yaml new file mode 100644 index 0000000..7c423ef --- /dev/null +++ b/Services/ui_forms/LinuxTelnet.yaml @@ -0,0 +1,86 @@ +name: Linux Telnet +type: linuxTelnetService + +description: >- + Linux Telnet Service + 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 diff --git a/Services/workflows/LinuxTelnet.xml b/Services/workflows/LinuxTelnet.xml new file mode 100644 index 0000000..235128c --- /dev/null +++ b/Services/workflows/LinuxTelnet.xml @@ -0,0 +1,80 @@ + + + + + ( + port- + + + + + + + + + + Linux instance ) created + + + + + ( + yum-ing telnet on unit ) + + + + + + + + telnet-server + + + + + + ( + Unable to deploy Telnet on ) due to + + + + + + + diff --git a/muranorepository/api/v1.py b/muranorepository/api/v1.py index 9e0f5d2..49fca92 100644 --- a/muranorepository/api/v1.py +++ b/muranorepository/api/v1.py @@ -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/', 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//', 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//', 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)) diff --git a/muranorepository/consts.py b/muranorepository/consts.py index a306d29..4f99d67 100644 --- a/muranorepository/consts.py +++ b/muranorepository/consts.py @@ -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' diff --git a/muranorepository/utils/archiver.py b/muranorepository/utils/archiver.py index fea30c1..bf443a0 100644 --- a/muranorepository/utils/archiver.py +++ b/muranorepository/utils/archiver.py @@ -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 diff --git a/setup.cfg b/setup.cfg index b9a835f..5537946 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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