contrib: Add devstack-heat

Devstack heat is a convenience set of heat templates and cli to get
devstack deployments without hassles when you already have access to an
OpenStack cloud.

Change-Id: I2de8d12b2e8c805a86d03311857ca9be41ff0c75
Signed-off-by: Antoni Segura Puimedon <antonisp@celebdor.com>
This commit is contained in:
Antoni Segura Puimedon 2017-05-19 15:57:41 +02:00
parent c8ccd2ce9a
commit cb7bec573e
No known key found for this signature in database
GPG Key ID: B71BE48A9A349926
7 changed files with 555 additions and 0 deletions

View File

@ -0,0 +1,86 @@
Kuryr Heat Templates
====================
This set of scripts and Heat templates are useful for deploying devstack
scenarios. It handles the creation of an allinone devstack nova instance and its
networking needs.
Prerequisites
~~~~~~~~~~~~~
Packages to install on the host you run devstack-heat (not on the cloud server):
* jq
* openstack-cli
If you want to run devstack from the master commit, this application requires a
github token due to the github api rate limiting:
You can generate one without any permissions at:
https://github.com/settings/tokens/new
Then put it in your ~/.bashrc an ENV variable called DEVSTACK_HEAT_GH_TOKEN like
so:
echo "export DEVSTACK_HEAT_GH_TOKEN=my_token" >> ~/.bashrc
After creating the instance, devstack-heat will immediately start creating a
devstack `stack` user and using devstack to stack kuryr-kubernetes. When it is
finished, there'll be a file names `/opt/stack/ready`.
How to run
~~~~~~~~~~
In order to run it, make sure that you have sourced your OpenStack cloud
provider openrc file and tweaked `hot/parameters.yml` to your liking then launch
with::
./devstack-heat stack
This will deploy the latest master. You can also specify specific gerrit change
numbers::
./devstack-heat stack 465657
To obtain this number, just look for example at the following change::
https://review.openstack.org/#/c/465657
In this instance, the number to pass to the *stack* subcommand is 466291.
This will create a stack named *gerrit_465657*. Further devstack-heat
subcommands should be called with the whole name of the stack, i.e.,
*gerrit_465657*.
Getting inside the deployment
-----------------------------
You can then ssh into the deployment in two ways::
./devstack-heat show name_of_my_stack
Write down the FIP it tells you and then::
./devstack-heat getkey name_of_my_stack > ~/name_of_my_stack.pem
Finally to get in (use the default username for the distro of your chosen
glance image, in the example below centos)::
ssh -i ~/name_of_my_stack.pem centos@obtained_fip
Alternatively, if you wait a bit, devstack-heat will have set up the devstack
stack user and you can just do::
./devstack-heat ssh name_of_my_stack
To delete the deployment::
./devstack-heat unstack name_of_my_stack
Supported images
----------------
It should work with the latest centos7 image. It is not tested with the latest
ubuntu 16.04 cloud image but it will probably work.

View File

@ -0,0 +1,125 @@
#!/bin/bash
function sub_stack() {
local latest_commit
local deployment=${1:-master_}
local tmpdir
if [[ "${deployment}" == "master_" ]]; then
if [[ "$DEVSTACK_HEAT_GH_TOKEN" == "" ]]; then
set -e
echo "Didn't find a Github token in ENV var DEVSTACK_HEAT_GH_TOKEN. Falling back to cloning repo..."
tmpdir=$(mktemp -d)
git clone https://github.com/openstack/kuryr-kubernetes "${tmpdir}/kuryr-kubernetes"
pushd "${tmpdir}/kuryr-kubernetes"
latest_commit=$(git rev-parse HEAD)
popd
rm -fr "${tmpdir}"
set +e
else
latest_commit=$(curl -s -H "Authorization: token $DEVSTACK_HEAT_GH_TOKEN" https://api.github.com/repos/openstack/kuryr-kubernetes/commits/master | jq -r '.sha')
fi
if [[ "$latest_commit" == "null" ]]; then
echo "Couldn't get a valid master commit"
exit 1
fi
deployment="${deployment}${latest_commit}"
else
deployment="gerrit_${deployment}"
fi
# create stack
read -p "Deploying the stack ${deployment}[y/N]?" -n 1 -r
echo
if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
exit 1
fi
echo "Starting..."
openstack stack create -e hot/parameters.yml -t hot/devstack_heat_template.yml "$deployment"
sub_show "$deployment"
}
function sub_unstack()
{
local deployment
deployment=${1:-master_}
if [[ "${deployment}" == "master_" ]]; then
echo "You must put the whole stack name for unstacking"
exit 1
fi
openstack stack delete "$deployment"
}
function sub_show() {
local deployment
deployment=${1:-master_}
if [[ "${deployment}" == "master_" ]]; then
echo "You must put the whole stack name for showing the stack resources"
exit 1
fi
echo "VM subnet: $(openstack stack output show "${deployment}" vm_subnet -f json | jq -r '.output_value')"
echo "Nodes FIPs: $(openstack stack output show "${deployment}" node_fips -f json | jq -r '.output_value' | jq -r '.[]?' | xargs echo)"
printf "\n"
}
function sub_getkey() {
local deployment
deployment=${1:-master_}
if [[ "${deployment}" == "master_" ]]; then
echo "You must put the whole stack name for getting the key"
exit 1
fi
openstack stack output show "${deployment}" master_key_priv -f json | jq -r '.output_value'
}
function sub_ssh() {
local deployment
local key
local fip
deployment=${1:-master_}
if [[ "${deployment}" == "master_" ]]; then
echo "You must put the whole stack name for getting the key"
exit 1
fi
key="${deployment}.pem"
fip=$(openstack stack output show "${deployment}" node_fips -f json | jq -r '.output_value' | jq -r '.[]?' | xargs echo)
sub_getkey "${deployment}" > "${key}"
chmod 0600 "${key}"
ssh -i "${deployment}.pem" -o "StrictHostKeyChecking no" "stack@${fip}"
exit $?
}
function sub_help() {
local myname
myname=$(basename "$0")
printf "Usage: %s <subcommand> [options]\n" "$myname"
printf "Subcommands:\n"
printf " stack gerrit_change_number Create Heat stack\n"
printf " unstack my_stack_name Delete Heat stack\n"
printf " show my_stack_name Show important info about the deployed Heat stack\n"
printf " getkey my_stack_name Output the Heat stack instances privkey to stdout\n"
printf " ssh my_stack_name gets the key and sshs into the stack user of the Stack\n"
}
command=$1
case $command in
"" | "-h" | "--help")
sub_help
;;
*)
shift
"sub_${command}" "$@"
if [ $? = 127 ]; then
echo "Error: '$command' is not a known $(basename "$0") command." >&2
echo " Run \'$(basename "$0") --help\' for a list of known subcommands." >&2
exit 1
fi
;;
esac

View File

@ -0,0 +1,85 @@
heat_template_version: 2015-10-15
description: Simple template to deploy kuryr resources
parameters:
image:
type: string
label: Image name or ID
description: Image to be used for the kuryr nodes
default: centos7
flavor:
type: string
label: Flavor
description: Flavor to be used for the masters
default: m1.small
worker_flavor:
type: string
label: Flavor
description: Flavor to be used for the workers
default: m1.small
public_net:
type: string
description: public network for the instances
default: public
vm_net_cidr:
type: string
description: vm_net network address (CIDR notation)
default: 10.11.0.0/24
vm_net_gateway:
type: string
description: vm_net network gateway address
default: 10.11.0.1
node_num:
type: number
description: Number of VMs
default: 1
resources:
network:
type: OS::Kuryr::DevstackNetworking
properties:
public_net: { get_param: public_net }
vm_net_cidr: { get_param: vm_net_cidr }
vm_net_gateway: { get_param: vm_net_gateway }
master_key:
type: OS::Nova::KeyPair
properties:
name: { get_param: 'OS::stack_name' }
save_private_key: true
nodes:
type: OS::Heat::ResourceGroup
properties:
count: { get_param: node_num }
resource_def:
type: OS::Kuryr::DevstackNode
properties:
public_net: { get_param: public_net }
image: { get_param: image }
flavor: { get_param: flavor }
key: { get_resource: master_key }
private_key: { get_attr: [master_key, private_key] }
public_key: { get_attr: [master_key, public_key] }
vm_net: { get_attr: [network, vm_net_id] }
vm_subnet: { get_attr: [network, vm_subnet_id] }
k8s_api_sg: { get_attr: [network, k8s_api_sg_id] }
name:
str_replace:
template: "__stack__/vm-%index%"
params:
__stack__: { get_param: 'OS::stack_name' }
change_number: { get_param: 'OS::stack_name' }
outputs:
node_fips:
value: { get_attr: [nodes, node_fip] }
vm_subnet:
value: { get_attr: [network, vm_subnet_id] }
k8s_api_sg:
value: { get_attr: [network, k8s_api_sg_id] }
master_key_pub:
value: { get_attr: [master_key, public_key] }
master_key_priv:
value: { get_attr: [master_key, private_key] }

View File

@ -0,0 +1,16 @@
distro=$(awk -F'=' '/^ID=/ {print $2}' /etc/os-release)
distro="${distro%\"}"
distro="${distro#\"}"
if [[ "$distro" =~ centos|fedora ]]; then
yum install -y git python-devel
yum group install -y Development Tools
if [[ "$distro" == "centos" ]]; then
yum install -y epel-release
sed -i -e '/Defaults requiretty/{ s/.*/# Defaults requiretty/ }' /etc/sudoers
fi
yum install -y jq
elif [[ "$distro" =~ ubuntu|debian ]]; then
apt-get install -y build-essential git python-dev jq
fi

View File

@ -0,0 +1,80 @@
heat_template_version: 2014-10-16
description: Simple template to deploy kuryr resources
parameters:
public_net:
type: string
label: public net ID
description: Public network for the node FIPs
vm_net_cidr:
type: string
description: vm_net network address (CIDR notation)
vm_net_gateway:
type: string
description: vm_net network gateway address
resources:
vm_net:
type: OS::Neutron::Net
properties:
name:
str_replace:
template: __stack__/vm_net
params:
__stack__: { get_param: 'OS::stack_name' }
vm_subnet:
type: OS::Neutron::Subnet
properties:
network_id: { get_resource: vm_net }
cidr: { get_param: vm_net_cidr }
gateway_ip: { get_param: vm_net_gateway }
name:
str_replace:
template: __stack__/vm_subnet
params:
__stack__: { get_param: 'OS::stack_name' }
kuryr_router:
type: OS::Neutron::Router
properties:
external_gateway_info:
network: { get_param: public_net }
name:
str_replace:
template: __stack__/router
params:
__stack__: { get_param: 'OS::stack_name' }
kr_vm_iface:
type: OS::Neutron::RouterInterface
properties:
router_id: { get_resource: kuryr_router }
subnet_id: { get_resource: vm_subnet }
k8s_api_sg:
type: OS::Neutron::SecurityGroup
properties:
name: K8s_api_sg
description: Ping and SSH
rules:
- protocol: icmp
- ethertype: IPv4
remote_mode: remote_group_id
- ethertype: IPv6
remote_mode: remote_group_id
- protocol: tcp
port_range_min: 22
port_range_max: 22
- protocol: tcp
port_range_min: 8080
port_range_max: 8080
outputs:
vm_net_id:
value: { get_resource: vm_net }
vm_subnet_id:
value: { get_resource: vm_subnet }
k8s_api_sg_id:
value: { get_resource: k8s_api_sg }

View File

@ -0,0 +1,152 @@
heat_template_version: 2015-10-15
description: template to deploy devstack nodes
parameters:
public_net:
type: string
label: public net ID
description: Public network for the node FIPs
image:
type: string
label: Image name or ID
description: Image to be used for the kuryr nodes
flavor:
type: string
label: Flavor
description: Flavor to be used for the image
default: m1.small
key:
type: string
label: key name
description: Keypair to be used for the instance
public_key:
type: string
label: key content for stack user authorized_keys
description: private key to configure all nodes
private_key:
type: string
label: key content to access other nodes
description: private key to configure all nodes
vm_net:
type: string
label: VM Network
description: Neutron network for VMs
vm_subnet:
type: string
label: VM Subnet
description: Neutron subnet for VMs
k8s_api_sg:
type: string
label: kubernetes API sg
description: Security Group for Kubernetes API
name:
type: string
label: Instance name
description: devstack node instance name
change_number:
type: string
label: Gerrit change number
description: Either the gerrit change number or master-sha_of_the_commit
resources:
instance_port:
type: OS::Neutron::Port
properties:
network: { get_param: vm_net }
security_groups:
- default
- { get_param: k8s_api_sg }
fixed_ips:
- subnet: { get_param: vm_subnet }
instance_fip:
type: OS::Neutron::FloatingIP
properties:
floating_network: { get_param: public_net }
port_id: { get_resource: instance_port }
instance:
type: OS::Nova::Server
properties:
name: { get_param: name }
image: { get_param: image }
flavor: { get_param: flavor }
key_name: { get_param: key }
networks:
- port: { get_resource: instance_port }
user_data_format: RAW
user_data:
str_replace:
params:
__distro_deps__: { get_file: distro_deps.sh }
__change_number__: { get_param: change_number }
__pubkey__: { get_param: public_key }
template: |
#!/bin/bash
set -ex
# Wait a bit for connectivity
sleep 10
# Deps for devstack
__distro_deps__
# Stack user config
useradd -s /bin/bash -d /opt/stack -m stack
mkdir /opt/stack/.ssh
cat > /opt/stack/.ssh/authorized_keys << EOF
__pubkey__
EOF
echo "stack ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/stack
# Stacking
sudo -i -u stack /bin/bash - <<"EOF"
function get_from_gerrit() {
local stackname
local change_number
local ref
stackname="__change_number__"
change_number=${stackname#*_}
echo "Finding latest ref for change ${change_number}"
ref=$(curl -s "https://review.openstack.org/changes/${change_number}?o=CURRENT_REVISION" | tail -n +2 | jq -r '.revisions[].ref')
echo "Fetching ref ${ref}"
git fetch https://git.openstack.org/openstack/kuryr-kubernetes "${ref}" && git checkout FETCH_HEAD
}
function get_from_sha() {
local commit_sha
commit_sha=$(echo "__change_number__" | cut -d'_' -f2)
echo "Sha to fetch: ${commit_sha}"
git checkout "$commit_sha"
}
cd /opt/stack
git clone https://git.openstack.org/openstack-dev/devstack
git clone https://github.com/openstack/kuryr-kubernetes
pushd kuryr-kubernetes
if [[ "__change_number__" =~ ^master.* ]]; then
get_from_sha
elif [[ "__change_number__" =~ ^gerrit.* ]]; then
get_from_gerrit
else
echo "Unrecognized stack name. Quitting..."
exit 1
fi
popd
pushd devstack
# The change is already downloaded, do not reclone
sed -e 's/# RECLONE=/RECLONE=/' /opt/stack/kuryr-kubernetes/devstack/local.conf.sample > /opt/stack/devstack/local.conf
./stack.sh
popd
touch ready
EOF
outputs:
node_fip:
description: FIP address of the node
value: { get_attr: [instance_fip, floating_ip_address] }

View File

@ -0,0 +1,11 @@
parameters:
image: centos7
flavor: m1.medium
public_net: public
vm_net_cidr: 10.11.0.0/24
vm_net_gateway: 10.11.0.1
node_num: 1
resource_registry:
OS::Kuryr::DevstackNetworking: networking_deployment.yaml
OS::Kuryr::DevstackNode: node.yaml