Wireframe for Heat usage
This commit is contained in:
parent
25b666782c
commit
4a9c87b0cf
17
bin/functions.sh
Executable file
17
bin/functions.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
error() {
|
||||
printf "\e[31mError: %s\e[0m\n" "${*}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
message() {
|
||||
printf "\e[33m%s\e[0m\n" "${1}"
|
||||
}
|
||||
|
||||
remote_shell() {
|
||||
host=$1
|
||||
key=$2
|
||||
command=$3
|
||||
ssh -i ${key} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@${host} "$command"
|
||||
}
|
36
bin/install.sh → bin/prepare.sh
Normal file → Executable file
36
bin/install.sh → bin/prepare.sh
Normal file → Executable file
@ -10,9 +10,12 @@ setup_image() {
|
||||
message "Installing Shaker image, will take some time"
|
||||
|
||||
message "Downloading Ubuntu cloud image"
|
||||
IMG_FILE="ubuntu-cloud.img"
|
||||
wget -O ${IMG_FILE} ${UBUNTU_CLOUD_IMAGE_URL}
|
||||
glance image-create --name ${IMG_FILE} --disk-format qcow2 --container-format bare --is-public True --file ${IMG_FILE}
|
||||
IMG_FILE="shaker-template-image"
|
||||
glance image-create --name ${IMG_FILE} --disk-format qcow2 --container-format bare --is-public True --copy-from ${UBUNTU_CLOUD_IMAGE_URL}
|
||||
|
||||
until [ -n "$(glance image-show ${IMG_FILE} | grep status | grep active)" ]; do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
message "Creating security group"
|
||||
SEC_GROUP="shaker-access"
|
||||
@ -25,9 +28,10 @@ setup_image() {
|
||||
nova flavor-create --is-public true m1.mini 6 1024 10 1
|
||||
|
||||
message "Creating key pair"
|
||||
KEY="shaker-key"
|
||||
nova keypair-add ${KEY} > ${KEY}.pem
|
||||
chmod og-rw ${KEY}.pem
|
||||
KEY_NAME="shaker-key"
|
||||
KEY="`mktemp`"
|
||||
nova keypair-add ${KEY_NAME} > ${KEY_NAME}
|
||||
chmod og-rw ${KEY}
|
||||
|
||||
message "Booting VM"
|
||||
NETWORK_ID=`neutron net-show net04 -f value -c id`
|
||||
@ -36,17 +40,27 @@ setup_image() {
|
||||
|
||||
message "Associating a floating IP with VM"
|
||||
FLOATING_IP=`neutron floatingip-create -f value -c floating_ip_address net04_ext | tail -1`
|
||||
FLOATING_IP="172.18.161.251"
|
||||
nova floating-ip-associate ${VM} ${FLOATING_IP}
|
||||
|
||||
message "Waiting for VM to boot up"
|
||||
until remote_shell ${FLOATING_IP} ${KEY} "echo"; do
|
||||
sleep 5
|
||||
done
|
||||
|
||||
message "Installing packages into VM"
|
||||
ssh -i ${KEY}.pem ubuntu@${FLOATING_IP} "sudo apt-add-repository \"deb http://nova.clouds.archive.ubuntu.com/ubuntu/ trusty multiverse\""
|
||||
ssh -i ${KEY}.pem ubuntu@${FLOATING_IP} "sudo apt-get update"
|
||||
ssh -i ${KEY}.pem ubuntu@${FLOATING_IP} "sudo apt-get -y install iperf netperf python-pip"
|
||||
ssh -i ${KEY}.pem ubuntu@${FLOATING_IP} "sudo pip install netperf-wrapper"
|
||||
remote_shell ${FLOATING_IP} ${KEY} "sudo apt-add-repository \"deb http://nova.clouds.archive.ubuntu.com/ubuntu/ trusty multiverse\""
|
||||
remote_shell ${FLOATING_IP} ${KEY} "sudo apt-get update"
|
||||
remote_shell ${FLOATING_IP} ${KEY} "sudo apt-get -y install iperf netperf python-pip python-dev"
|
||||
remote_shell ${FLOATING_IP} ${KEY} "sudo pip install netperf-wrapper numpy"
|
||||
|
||||
message "Making VM snapshot"
|
||||
nova image-create --poll ${VM} ${IMAGE_NAME}
|
||||
|
||||
message "Destroy VM"
|
||||
nova delete ${VM}
|
||||
|
||||
FP_ID=`neutron floatingip-list -f csv -c id -c floating_ip_address --quote none | grep ${FLOATING_IP} | awk -F "," '{print $1}'`
|
||||
neutron floatingip-delete ${FP_ID}
|
||||
}
|
||||
|
||||
main() {
|
@ -8,4 +8,6 @@ oslo.config>=1.4.0 # Apache-2.0
|
||||
oslo.i18n>=1.0.0 # Apache-2.0
|
||||
oslo.serialization>=1.0.0 # Apache-2.0
|
||||
oslo.utils>=1.1.0 # Apache-2.0
|
||||
python-keystoneclient
|
||||
python-heatclient
|
||||
PyYAML>=3.1.0
|
||||
|
5
scenarios/networking_between_two_vms.yaml
Normal file
5
scenarios/networking_between_two_vms.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
deploy:
|
||||
scenarios/deploy_two_vms.sh
|
||||
tests:
|
||||
- netperf: tcp_bidirectional
|
||||
- dummy-type: nope
|
@ -24,4 +24,4 @@ packages =
|
||||
|
||||
[entry_points]
|
||||
console_scripts =
|
||||
shaker = shaker.server:main
|
||||
shaker = shaker.engine.main:main
|
||||
|
@ -14,10 +14,21 @@
|
||||
# limitations under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
from shaker.engine import utils
|
||||
|
||||
|
||||
OPTS = [
|
||||
cfg.StrOpt('scenario',
|
||||
required=True,
|
||||
help='Scenario to run'),
|
||||
cfg.StrOpt('os-auth-url', metavar='<auth-url>',
|
||||
default=utils.env('OS_AUTH_URL'),
|
||||
help='Authentication URL, defaults to env[OS_AUTH_URL].'),
|
||||
cfg.StrOpt('os-tenant-name', metavar='<auth-tenant-name>',
|
||||
default=utils.env('OS_TENANT_NAME'),
|
||||
help='Authentication tenant name, defaults to '
|
||||
'env[OS_TENANT_NAME].'),
|
||||
cfg.StrOpt('os-username', metavar='<auth-username>',
|
||||
default=utils.env('OS_USERNAME'),
|
||||
help='Authentication username, defaults to env[OS_USERNAME].'),
|
||||
cfg.StrOpt('os-password', metavar='<auth-password>',
|
||||
default=utils.env('OS_PASSWORD'),
|
||||
help='Authentication password, defaults to env[OS_PASSWORD].'),
|
||||
]
|
||||
|
40
shaker/engine/heat.py
Normal file
40
shaker/engine/heat.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2015 Mirantis 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.
|
||||
|
||||
from heatclient import client as heat_client_pkg
|
||||
import time
|
||||
|
||||
|
||||
HEAT_CLIENT_VERSION = '1'
|
||||
|
||||
|
||||
def create_heat_client(keystone_client):
|
||||
orchestration_api_url = keystone_client.service_catalog.url_for(
|
||||
service_type='orchestration')
|
||||
client = heat_client_pkg.Client(HEAT_CLIENT_VERSION,
|
||||
endpoint=orchestration_api_url,
|
||||
token=keystone_client.auth_token, )
|
||||
return client
|
||||
|
||||
|
||||
def wait_stack_completion(stack):
|
||||
# NOTE: expected empty status because status of stack
|
||||
# maybe is not set in heat database
|
||||
while stack.status in ['IN_PROGRESS', '']:
|
||||
time.sleep(1)
|
||||
stack.get()
|
||||
|
||||
if stack.status != 'COMPLETE':
|
||||
raise Exception(stack.stack_status)
|
30
shaker/engine/keystone.py
Normal file
30
shaker/engine/keystone.py
Normal file
@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2015 Mirantis 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.
|
||||
|
||||
from keystoneclient import discover as keystone_discover
|
||||
from keystoneclient.v2_0 import client as keystone_v2
|
||||
from keystoneclient.v3 import client as keystone_v3
|
||||
|
||||
|
||||
def create_keystone_client(args):
|
||||
discover = keystone_discover.Discover(**args)
|
||||
for version_data in discover.version_data():
|
||||
version = version_data["version"]
|
||||
if version[0] <= 2:
|
||||
return keystone_v2.Client(**args)
|
||||
elif version[0] == 3:
|
||||
return keystone_v3.Client(**args)
|
||||
raise Exception(
|
||||
'Failed to discover keystone version for url %(auth_url)s.', **args)
|
@ -16,12 +16,27 @@
|
||||
from oslo.config import cfg
|
||||
|
||||
from shaker.engine import config
|
||||
from shaker.engine import heat
|
||||
from shaker.engine import keystone
|
||||
from shaker.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run():
|
||||
keystone_kwargs = {'username': cfg.CONF.os_username,
|
||||
'password': cfg.CONF.os_password,
|
||||
'tenant_name': cfg.CONF.os_tenant_name,
|
||||
'auth_url': cfg.CONF.os_auth_url,
|
||||
}
|
||||
keystone_client = keystone.create_keystone_client(keystone_kwargs)
|
||||
|
||||
heat_client = heat.create_heat_client(keystone_client)
|
||||
for stack in heat_client.stacks.list():
|
||||
LOG.info('Stacks: %s', stack)
|
||||
|
||||
|
||||
def main():
|
||||
# init conf and logging
|
||||
conf = cfg.CONF
|
||||
@ -32,6 +47,8 @@ def main():
|
||||
logging.setup('shaker')
|
||||
LOG.info('Logging enabled')
|
||||
|
||||
run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
28
shaker/engine/utils.py
Normal file
28
shaker/engine/utils.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2015 Mirantis 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 os
|
||||
|
||||
|
||||
def env(*_vars, **kwargs):
|
||||
"""Returns the first environment variable set.
|
||||
|
||||
If none are non-empty, defaults to '' or keyword arg default.
|
||||
"""
|
||||
for v in _vars:
|
||||
value = os.environ.get(v)
|
||||
if value:
|
||||
return value
|
||||
return kwargs.get('default', '')
|
125
shaker/resources/servers_and_net.heat
Normal file
125
shaker/resources/servers_and_net.heat
Normal file
@ -0,0 +1,125 @@
|
||||
heat_template_version: 2013-05-23
|
||||
|
||||
description: >
|
||||
HOT template to create a new neutron network plus a router to the public
|
||||
network, and for deploying two servers into the new network. The template also
|
||||
assigns floating IP addresses to each server so they are routable from the
|
||||
public network.
|
||||
|
||||
parameters:
|
||||
key_name:
|
||||
type: string
|
||||
description: Name of keypair to assign to servers
|
||||
image:
|
||||
type: string
|
||||
description: Name of image to use for servers
|
||||
flavor:
|
||||
type: string
|
||||
description: Flavor to use for servers
|
||||
public_net:
|
||||
type: string
|
||||
description: >
|
||||
ID or name of public network for which floating IP addresses will be allocated
|
||||
private_net_name:
|
||||
type: string
|
||||
description: Name of private network to be created
|
||||
private_net_cidr:
|
||||
type: string
|
||||
description: Private network address (CIDR notation)
|
||||
private_net_gateway:
|
||||
type: string
|
||||
description: Private network gateway address
|
||||
private_net_pool_start:
|
||||
type: string
|
||||
description: Start of private network IP address allocation pool
|
||||
private_net_pool_end:
|
||||
type: string
|
||||
description: End of private network IP address allocation pool
|
||||
|
||||
resources:
|
||||
private_net:
|
||||
type: OS::Neutron::Net
|
||||
properties:
|
||||
name: { get_param: private_net_name }
|
||||
|
||||
private_subnet:
|
||||
type: OS::Neutron::Subnet
|
||||
properties:
|
||||
network_id: { get_resource: private_net }
|
||||
cidr: { get_param: private_net_cidr }
|
||||
gateway_ip: { get_param: private_net_gateway }
|
||||
allocation_pools:
|
||||
- start: { get_param: private_net_pool_start }
|
||||
end: { get_param: private_net_pool_end }
|
||||
|
||||
router:
|
||||
type: OS::Neutron::Router
|
||||
properties:
|
||||
external_gateway_info:
|
||||
network: { get_param: public_net }
|
||||
|
||||
router_interface:
|
||||
type: OS::Neutron::RouterInterface
|
||||
properties:
|
||||
router_id: { get_resource: router }
|
||||
subnet_id: { get_resource: private_subnet }
|
||||
|
||||
server1:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
name: Server1
|
||||
image: { get_param: image }
|
||||
flavor: { get_param: flavor }
|
||||
key_name: { get_param: key_name }
|
||||
networks:
|
||||
- port: { get_resource: server1_port }
|
||||
|
||||
server1_port:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network_id: { get_resource: private_net }
|
||||
fixed_ips:
|
||||
- subnet_id: { get_resource: private_subnet }
|
||||
|
||||
server1_floating_ip:
|
||||
type: OS::Neutron::FloatingIP
|
||||
properties:
|
||||
floating_network: { get_param: public_net }
|
||||
port_id: { get_resource: server1_port }
|
||||
|
||||
server2:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
name: Server2
|
||||
image: { get_param: image }
|
||||
flavor: { get_param: flavor }
|
||||
key_name: { get_param: key_name }
|
||||
networks:
|
||||
- port: { get_resource: server2_port }
|
||||
|
||||
server2_port:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network_id: { get_resource: private_net }
|
||||
fixed_ips:
|
||||
- subnet_id: { get_resource: private_subnet }
|
||||
|
||||
server2_floating_ip:
|
||||
type: OS::Neutron::FloatingIP
|
||||
properties:
|
||||
floating_network: { get_param: public_net }
|
||||
port_id: { get_resource: server2_port }
|
||||
|
||||
outputs:
|
||||
server1_private_ip:
|
||||
description: IP address of server1 in private network
|
||||
value: { get_attr: [ server1, first_address ] }
|
||||
server1_public_ip:
|
||||
description: Floating IP address of server1 in public network
|
||||
value: { get_attr: [ server1_floating_ip, floating_ip_address ] }
|
||||
server2_private_ip:
|
||||
description: IP address of server2 in private network
|
||||
value: { get_attr: [ server2, first_address ] }
|
||||
server2_public_ip:
|
||||
description: Floating IP address of server2 in public network
|
||||
value: { get_attr: [ server2_floating_ip, floating_ip_address ] }
|
Loading…
x
Reference in New Issue
Block a user