Merge "Improve server-side caching."
This commit is contained in:
commit
229645c468
6
.gitignore
vendored
6
.gitignore
vendored
@ -26,6 +26,9 @@ pip-log.txt
|
|||||||
.tox
|
.tox
|
||||||
nosetests.xml
|
nosetests.xml
|
||||||
|
|
||||||
|
AUTHORS
|
||||||
|
Changelog
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
|
|
||||||
@ -34,4 +37,5 @@ nosetests.xml
|
|||||||
.project
|
.project
|
||||||
.pydevproject
|
.pydevproject
|
||||||
.idea
|
.idea
|
||||||
etc/murano-repository.conf
|
|
||||||
|
/etc/murano-repository.conf
|
||||||
|
4
AUTHORS
4
AUTHORS
@ -1,4 +0,0 @@
|
|||||||
efedorova <efedorova@mirantis.com>
|
|
||||||
Ekaterina Fedorova <efedorova@mirantis.com>
|
|
||||||
EkaterinaFedorova <efedorova@mirantis.com>
|
|
||||||
Timur Sufiev <tsufiev@mirantis.com>
|
|
189
ChangeLog
189
ChangeLog
@ -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
|
|
24
Services/demo-manifest.yaml
Normal file
24
Services/demo-manifest.yaml
Normal 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
|
127
Services/heat_templates/Linux.template
Normal file
127
Services/heat_templates/Linux.template
Normal 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": {
|
||||||
|
}
|
||||||
|
}
|
74
Services/scripts/TelnetDeploy.sh
Normal file
74
Services/scripts/TelnetDeploy.sh
Normal 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
|
86
Services/ui_forms/LinuxTelnet.yaml
Normal file
86
Services/ui_forms/LinuxTelnet.yaml
Normal 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
|
80
Services/workflows/LinuxTelnet.xml
Normal file
80
Services/workflows/LinuxTelnet.xml
Normal 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>
|
@ -22,28 +22,57 @@ from werkzeug import secure_filename
|
|||||||
from muranorepository.utils.parser import ManifestParser
|
from muranorepository.utils.parser import ManifestParser
|
||||||
from muranorepository.utils.archiver import Archiver
|
from muranorepository.utils.archiver import Archiver
|
||||||
from muranorepository.consts import DATA_TYPES, MANIFEST
|
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
|
from oslo.config import cfg
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
v1_api = Blueprint('v1', __name__)
|
v1_api = Blueprint('v1', __name__)
|
||||||
CACHE_DIR = os.path.join(v1_api.root_path, 'cache')
|
CACHE_DIR = os.path.join(v1_api.root_path, 'cache')
|
||||||
|
|
||||||
if not os.path.exists(CACHE_DIR):
|
if not os.path.exists(CACHE_DIR):
|
||||||
os.mkdir(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):
|
def _get_archive(client, hash_sum):
|
||||||
parser = ManifestParser(CONF.manifests)
|
parser = ManifestParser(CONF.manifests)
|
||||||
manifests = parser.parse()
|
manifests = parser.parse()
|
||||||
types = None
|
types = CLIENTS_DICT.get(client)
|
||||||
if client == 'conductor':
|
if not types:
|
||||||
types = ('heat', 'agent', 'scripts', 'workflows')
|
|
||||||
elif client == 'ui':
|
|
||||||
types = ('ui',)
|
|
||||||
else:
|
|
||||||
abort(404)
|
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):
|
def _get_locations(data_type, result_path):
|
||||||
@ -64,11 +93,19 @@ def _get_locations(data_type, result_path):
|
|||||||
return jsonify({data_type: locations})
|
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')
|
file_to_upload = request.files.get('file')
|
||||||
if file_to_upload:
|
if file_to_upload:
|
||||||
filename = secure_filename(file_to_upload.filename)
|
filename = secure_filename(file_to_upload.filename)
|
||||||
file_to_upload.save(os.path.join(result_path, filename))
|
file_to_upload.save(os.path.join(result_path, filename))
|
||||||
|
_update_hash(data_type)
|
||||||
return jsonify(result='success')
|
return jsonify(result='success')
|
||||||
else:
|
else:
|
||||||
abort(400)
|
abort(400)
|
||||||
@ -105,9 +142,8 @@ def get_data_type_locations(data_type):
|
|||||||
@v1_api.route('/admin/<data_type>', methods=['POST'])
|
@v1_api.route('/admin/<data_type>', methods=['POST'])
|
||||||
def upload_file(data_type):
|
def upload_file(data_type):
|
||||||
_check_data_type(data_type)
|
_check_data_type(data_type)
|
||||||
result_path = _compose_path(data_type)
|
|
||||||
try:
|
try:
|
||||||
return _save_file(request, result_path)
|
return _save_file(request, data_type)
|
||||||
except:
|
except:
|
||||||
abort(403)
|
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'])
|
@v1_api.route('/admin/<data_type>/<path:path>', methods=['POST'])
|
||||||
def upload_file_in_nested_path(data_type, path):
|
def upload_file_in_nested_path(data_type, path):
|
||||||
_check_data_type(data_type)
|
_check_data_type(data_type)
|
||||||
result_path = _compose_path(data_type, path)
|
# it's forbidden to upload manifests to subfolders
|
||||||
# it's forbidden to upload manifests to subfolder
|
|
||||||
if data_type == MANIFEST:
|
if data_type == MANIFEST:
|
||||||
abort(403)
|
abort(403)
|
||||||
if not os.path.exists(result_path):
|
return _save_file(request, data_type, path)
|
||||||
abort(404)
|
|
||||||
return _save_file(request, result_path)
|
|
||||||
|
|
||||||
|
|
||||||
@v1_api.route('/admin/<data_type>/<path:path>', methods=['PUT'])
|
@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):
|
if os.path.isfile(result_path):
|
||||||
try:
|
try:
|
||||||
os.remove(result_path)
|
os.remove(result_path)
|
||||||
|
_update_hash(data_type)
|
||||||
except Exception:
|
except Exception:
|
||||||
abort(404)
|
abort(404)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
# enable to delete only empty directories
|
||||||
os.rmdir(result_path)
|
os.rmdir(result_path)
|
||||||
except Exception:
|
except Exception:
|
||||||
abort(403)
|
abort(403)
|
||||||
return jsonify(result='success')
|
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))
|
|
||||||
|
@ -21,3 +21,7 @@ AGENT = 'agent'
|
|||||||
SCRIPTS = 'scripts'
|
SCRIPTS = 'scripts'
|
||||||
|
|
||||||
DATA_TYPES = [UI, WORKFLOW, HEAT, AGENT, SCRIPTS, MANIFEST]
|
DATA_TYPES = [UI, WORKFLOW, HEAT, AGENT, SCRIPTS, MANIFEST]
|
||||||
|
CLIENTS_DICT = {'conductor': (WORKFLOW, HEAT, AGENT, SCRIPTS),
|
||||||
|
'ui': (UI,)}
|
||||||
|
|
||||||
|
ARCHIVE_PKG_NAME = 'data.tar.gz'
|
||||||
|
@ -18,10 +18,9 @@ import shutil
|
|||||||
import hashlib
|
import hashlib
|
||||||
import logging as log
|
import logging as log
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from muranorepository.consts import DATA_TYPES
|
from muranorepository.consts import DATA_TYPES, ARCHIVE_PKG_NAME
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
ARCHIVE_PKG_NAME = 'data.tar.gz'
|
|
||||||
CHUNK_SIZE = 1 << 20 # 1MB
|
CHUNK_SIZE = 1 << 20 # 1MB
|
||||||
|
|
||||||
|
|
||||||
@ -75,49 +74,48 @@ class Archiver(object):
|
|||||||
shutil.rmtree(path, ignore_errors=True)
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("Unable to delete temp directory: {0}".format(e))
|
log.error("Unable to delete temp directory: {0}".format(e))
|
||||||
hash_sum = self._get_hash(ARCHIVE_PKG_NAME)
|
hash_folder = self._create_hash_folder(ARCHIVE_PKG_NAME, cache_dir)
|
||||||
pkg_dir = os.path.join(cache_dir, hash_sum)
|
try:
|
||||||
if not os.path.exists(pkg_dir):
|
shutil.move(ARCHIVE_PKG_NAME, os.path.join(hash_folder,
|
||||||
os.mkdir(pkg_dir)
|
ARCHIVE_PKG_NAME))
|
||||||
shutil.move(ARCHIVE_PKG_NAME, os.path.join(pkg_dir, ARCHIVE_PKG_NAME))
|
except Exception as e:
|
||||||
return os.path.abspath(os.path.join(pkg_dir, ARCHIVE_PKG_NAME))
|
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):
|
def get_existing_hash(self, cache_dir):
|
||||||
#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
|
|
||||||
existing_caches = os.listdir(cache_dir)
|
existing_caches = os.listdir(cache_dir)
|
||||||
if len(existing_caches) == 1:
|
log.debug('Asserting there is just one archive in cache folder. Clear '
|
||||||
if existing_caches[0] == hash_sum:
|
'folder {0} in case of Assertion Error'.format(cache_dir))
|
||||||
path = os.path.join(cache_dir, hash_sum, ARCHIVE_PKG_NAME)
|
assert len(existing_caches) < 2
|
||||||
if not os.path.exists(path):
|
if not len(existing_caches):
|
||||||
raise RuntimeError(
|
return None
|
||||||
'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
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('Too many cached archives at {0}'.format(
|
path = os.path.join(cache_dir,
|
||||||
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
|
manifests -- list of Manifest objects
|
||||||
hash_sum -- hash to compare to
|
|
||||||
types -- desired data types to be added to archive
|
types -- desired data types to be added to archive
|
||||||
return: absolute path to created archive
|
return: absolute path to created archive
|
||||||
"""
|
"""
|
||||||
@ -126,14 +124,6 @@ class Archiver(object):
|
|||||||
temp_dir = tempfile.mkdtemp()
|
temp_dir = tempfile.mkdtemp()
|
||||||
except:
|
except:
|
||||||
temp_dir = '/tmp'
|
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:
|
for data_type in types:
|
||||||
if data_type not in DATA_TYPES:
|
if data_type not in DATA_TYPES:
|
||||||
raise Exception("Please, specify one of the supported data "
|
raise Exception("Please, specify one of the supported data "
|
||||||
@ -157,3 +147,20 @@ class Archiver(object):
|
|||||||
"{1}".format(manifest.service_display_name, data_type))
|
"{1}".format(manifest.service_display_name, data_type))
|
||||||
|
|
||||||
return self._compose_archive(temp_dir, cache_dir)
|
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
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
name = muranorepository
|
name = murano-repository
|
||||||
version = 0.1
|
version = 0.4
|
||||||
summary = Murano Metadata Repository
|
summary = Murano Metadata Repository
|
||||||
description-file = README.rst
|
description-file = README.rst
|
||||||
license = Apache Software License
|
license = Apache Software License
|
||||||
|
Loading…
Reference in New Issue
Block a user