2 # Copyright 2017 AT&T Intellectual Property, Inc
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 #. What this is: Setup script for Cloudify use with Kubernetes.
18 #. - Kubernetes cluster installed per k8s-cluster.sh (in this repo)
20 #. From a server with access to the kubernetes master node:
21 #. $ git clone https://gerrit.opnfv.org/gerrit/models ~/models
22 #. $ scp -r ~/models/tools/cloudify ubuntu@<k8s-master>:/home/ubuntu/.
23 #. <k8s-master>: IP or hostname of kubernetes master server
24 #. $ ssh -x ubuntu@<k8s-master> cloudify/k8s-cloudify.sh prereqs
25 #. prereqs: installs prerequisites and configures ubuntu user for kvm use
26 #. $ ssh -x ubuntu@<k8s-master> bash cloudify/k8s-cloudify.sh setup
27 #. setup: installs cloudify CLI and Manager
28 #. $ source ~/models/tools/cloudify/k8s-cloudify.sh demo <start|stop> <k8s-master>
29 #. demo: control demo blueprint
30 #. start|stop: start or stop the demo
31 #. <k8s-master>: IP or hostname of kubernetes master server
32 #. $ ssh -x ubuntu@<k8s-master> bash cloudify/k8s-cloudify.sh clean
33 #. clean: uninstalls cloudify CLI and Manager
35 #. Status: this is a work in progress, under test.
38 f=$(caller 0 | awk '{print $2}')
39 l=$(caller 0 | awk '{print $1}')
41 echo "$f:$l ($(date)) $1"
45 log "Install prerequisites"
46 sudo apt-get install -y virtinst qemu-kvm libguestfs-tools virtualenv git \
48 log "Setup $USER for kvm use"
49 # Per http://libguestfs.org/guestfs-faq.1.html
50 # workaround for virt-customize warning: libguestfs: warning: current user is not a member of the KVM group (group ID 121). This user cannot access /dev/kvm, so libguestfs may run very slowly. It is recommended that you 'chmod 0666 /dev/kvm' or add the current user to the KVM group (you might need to log out and log in again).
51 # Also see: https://help.ubuntu.com/community/KVM/Installation
52 # also to avoid permission denied errors in guestfish, from http://manpages.ubuntu.com/manpages/zesty/man1/guestfs-faq.1.html
53 sudo usermod -a -G kvm $USER
54 sudo chmod 0644 /boot/vmlinuz*
60 log "Setup Cloudify-CLI"
61 # Per http://docs.getcloudify.org/4.1.0/installation/bootstrapping/#installing-cloudify-manager-in-an-offline-environment
62 wget -q http://repository.cloudifysource.org/cloudify/17.9.21/community-release/cloudify-cli-community-17.9.21.deb
63 # Installs into /opt/cfy/
64 sudo dpkg -i cloudify-cli-community-17.9.21.deb
65 export MANAGER_BLUEPRINTS_DIR=/opt/cfy/cloudify-manager-blueprints
66 virtualenv ~/cloudify/env
67 source ~/cloudify/env/bin/activate
69 log "Setup Cloudify-Manager"
71 # sudo virsh destroy cloudify-manager; sudo virsh undefine cloudify-manager
72 wget -q http://repository.cloudifysource.org/cloudify/17.9.21/community-release/cloudify-manager-community-17.9.21.qcow2
73 # nohup and redirection of output is a workaround for some issue with virt-install never outputting anything beyond "Creadint domain..." and thus not allowing the script to continue.
74 nohup virt-install --connect qemu:///system --virt-type kvm \
75 --name cloudify-manager --vcpus 4 --memory 16192 \
76 --disk cloudify-manager-community-17.9.21.qcow2 --import \
77 --network network=default --os-type=linux \
78 --os-variant=rhel7 > /dev/null 2>&1 &
82 while [[ "x$VM_IP" == "x" ]]; do
83 log "$n minutes so far; waiting 60 seconds for cloudify-manager IP to be assigned"
86 VM_MAC=$(virsh domiflist cloudify-manager | grep default | grep -Eo "[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+")
87 VM_IP=$(/usr/sbin/arp -e | grep ${VM_MAC} | awk {'print $1'})
89 log "cloudify-manager IP=$VM_IP"
90 while ! cfy profiles use $VM_IP -u admin -p admin -t default_tenant ; do
91 log "waiting 60 seconds for cloudify-manager API to be active"
96 log "Install Cloudify Kubernetes Plugin"
97 # Per http://docs.getcloudify.org/4.1.0/plugins/container-support/
98 # Per https://github.com/cloudify-incubator/cloudify-kubernetes-plugin
99 pip install kubernetes wagon
100 # From https://github.com/cloudify-incubator/cloudify-kubernetes-plugin/releases
101 wget -q https://github.com/cloudify-incubator/cloudify-kubernetes-plugin/releases/download/1.2.1/cloudify_kubernetes_plugin-1.2.1-py27-none-linux_x86_64-centos-Core.wgn
102 # For Cloudify-CLI per http://docs.getcloudify.org/4.1.0/plugins/using-plugins/
104 cloudify_kubernetes_plugin-1.2.1-py27-none-linux_x86_64-centos-Core.wgn
105 # For Cloudify-Manager per https://github.com/cloudify-incubator/cloudify-kubernetes-plugin/blob/master/examples/persistent-volumes-blueprint.yaml
106 cfy plugins upload cloudify_kubernetes_plugin-1.2.1-py27-none-linux_x86_64-centos-Core.wgn
108 log "Create secrets for kubernetes as referenced in blueprints"
109 cfy secrets create -s $(grep server ~/.kube/config | awk -F '/' '{print $3}' \
110 | awk -F ':' '{print $1}') kubernetes_master_ip
111 cfy secrets create -s $(grep server ~/.kube/config | awk -F '/' '{print $3}' \
112 | awk -F ':' '{print $2}') kubernetes_master_port
113 cfy secrets create -s \
114 $(grep 'certificate-authority-data: ' ~/.kube/config | \
115 awk -F ' ' '{print $2}') kubernetes_certificate_authority_data
116 cfy secrets create -s $(grep 'client-certificate-data: ' ~/.kube/config \
117 | awk -F ' ' '{print $2}') kubernetes-admin_client_certificate_data
118 cfy secrets create -s $(grep 'client-key-data: ' ~/.kube/config \
119 | awk -F ' ' '{print $2}') kubernetes-admin_client_key_data
123 VM_MAC=$(sudo virsh domiflist cloudify-manager | grep default | grep -Eo "[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+:[0-9a-f\]+")
124 VM_IP=$(/usr/sbin/arp -e | grep ${VM_MAC} | awk {'print $1'})
127 HOST_IP=$(ip route get 8.8.8.8 | awk '{print $NF; exit}')
129 # Forward host port 80 to VM
130 sudo iptables -t nat -I PREROUTING -p tcp -d $HOST_IP --dport 80 -j DNAT --to-destination $VM_IP:80
131 sudo iptables -I FORWARD -m state -d $VM_IP/32 --state NEW,RELATED,ESTABLISHED -j ACCEPT
132 sudo iptables -t nat -A POSTROUTING -j MASQUERADE
134 while ! curl -u admin:admin --header 'Tenant: default_tenant' http://$HOST_IP/api/v3.1/status ; do
135 log "Cloudify API is not yet responding, waiting 10 seconds"
138 log "Cloudify CLI config is at ~/.cloudify/config.yaml"
139 log "Cloudify CLI log is at ~/.cloudify/logs/cli.log"
140 log "Cloudify API access example: curl -u admin:admin --header 'Tenant: default_tenant' http://$HOST_IP/api/v3.1/status"
141 log "Cloudify setup is complete!"
145 # Per http://docs.getcloudify.org/4.1.0/plugins/container-support/
146 # Per https://github.com/cloudify-incubator/cloudify-kubernetes-plugin
147 # Also per guidance at https://github.com/cloudify-incubator/cloudify-kubernetes-plugin/issues/18
148 # echo "master-ip: $(grep server ~/.kube/config | awk -F '/' '{print $3}' | awk -F ':' '{print $1}')" >~/cloudify/blueprints/k8s-hello-world/inputs.yaml
149 # echo "master-port: $(grep server ~/.kube/config | awk -F '/' '{print $3}' | awk -F ':' '{print $2}')" >>~/cloudify/blueprints/k8s-hello-world/inputs.yaml
150 # echo "file_content:" >>~/cloudify/blueprints/k8s-hello-world/inputs.yaml
151 # sed 's/^/ /' ~/.kube/config | tee -a ~/cloudify/blueprints/k8s-hello-world/inputs.yaml
153 cd ~/models/tools/cloudify/blueprints
155 if [[ "$1" == "start" ]]; then
156 log "copy kube config from k8s master for insertion into blueprint"
157 scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
158 ubuntu@$manager_ip:/home/ubuntu/.kube/config k8s-hello-world/kube.config
160 log "package the blueprint"
161 # CLI: cfy blueprints package -o ~/cloudify/blueprints/k8s-hello-world ~/cloudify/blueprints/k8s-hello-world
162 tar ckf /tmp/blueprint.tar k8s-hello-world
164 log "upload the blueprint"
165 # CLI: cfy blueprints upload -t default_tenant -b k8s-hello-world ~/cloudify/blueprints/k8s-hello-world.tar.gz
166 curl -X PUT -u admin:admin --header 'Tenant: default_tenant' \
167 --header "Content-Type: application/octet-stream" \
168 http://$manager_ip/api/v3.1/blueprints/k8s-hello-world?application_file_name=blueprint.yaml \
169 -T /tmp/blueprint.tar | jq
171 log "create a deployment for the blueprint"
172 # CLI: cfy deployments create -t default_tenant -b k8s-hello-world k8s-hello-world
173 curl -X PUT -u admin:admin --header 'Tenant: default_tenant' \
174 --header "Content-Type: application/json" \
175 -d '{"blueprint_id": "k8s-hello-world", "inputs": {}}' \
176 http://$manager_ip/api/v3.1/deployments/k8s-hello-world
179 # CLI: cfy workflows list -d k8s-hello-world
181 log "install the deployment pod and service"
182 # CLI: cfy executions start install -d k8s-hello-world
183 curl -X POST -u admin:admin --header 'Tenant: default_tenant' \
184 --header "Content-Type: application/json" \
185 -d '{"deployment_id":"k8s-hello-world", "workflow_id":"install"}' \
186 http://$manager_ip/api/v3.1/executions | jq
188 log "get the service's assigned node_port"
189 port=$(curl -u admin:admin --header 'Tenant: default_tenant' \
190 http://$manager_ip/api/v3.1/node-instances | \
191 jq -r '.items[0].runtime_properties.kubernetes.spec.ports[0].node_port')
192 while [[ "$port" == "null" ]]; do
194 port=$(curl -u admin:admin --header 'Tenant: default_tenant' \
195 http://$manager_ip/api/v3.1/node-instances | \
196 jq -r '.items[0].runtime_properties.kubernetes.spec.ports[0].node_port')
198 log "node_port = $port"
200 log "verify service is responding"
201 while ! curl http://$manager_ip:$port ; do
202 log "nginx service is not yet responding at http://$manager_ip:$port, waiting 10 seconds"
205 log "service is active at http://$manager_ip:$port"
207 log "uninstall the service"
208 curl -X POST -u admin:admin --header 'Tenant: default_tenant' \
209 --header "Content-Type: application/json" \
210 -d '{"deployment_id":"k8s-hello-world", "workflow_id":"uninstall", "force": "true"}' \
211 http://$manager_ip/api/v3.1/executions
213 state=$(curl -u admin:admin --header 'Tenant: default_tenant' \
214 http://$manager_ip/api/v3.1/node-instances | jq -r '.items[0].state')
215 while [[ "$state" == "deleting" ]]; do
216 if [[ $count > 10 ]]; then
217 log "try to cancel all current executions"
218 exs=$(curl -u admin:admin --header 'Tenant: default_tenant' \
219 http://$manager_ip/api/v3.1/executions | jq -r '.items[].status')
221 for status in $exs; do
222 log "checking execution $i in state $status"
223 if [[ "$status" == "started" ]]; then
224 id=$(curl -u admin:admin --header 'Tenant: default_tenant' \
225 http://$manager_ip/api/v3.1/executions | jq -r ".items[$i].id")
226 curl -X POST -u admin:admin --header 'Tenant: default_tenant' \
227 --header "Content-Type: application/json" \
228 -d '{"deployment_id": "k8s-hello-world", "action": "cancel"}' \
229 http://$manager_ip/api/v3.1/executions/$id
233 log "force delete deployment via cfy CLI"
234 ssh -x -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
235 ubuntu@$manager_ip cfy deployment delete -f \
236 -t default_tenant k8s-hello-world
239 state=$(curl -u admin:admin --header 'Tenant: default_tenant' \
240 http://$manager_ip/api/v3.1/node-instances | jq -r '.items[0].state')
243 log "delete the deployment"
244 curl -X DELETE -u admin:admin --header 'Tenant: default_tenant' \
245 http://$manager_ip/api/v3.1/deployments/k8s-hello-world
247 log "delete the blueprint"
248 curl -X DELETE -u admin:admin --header 'Tenant: default_tenant' \
249 http://$manager_ip/api/v3.1/blueprints/k8s-hello-world
251 log "verify the blueprint is deleted"
252 curl -u admin:admin --header 'Tenant: default_tenant' \
253 http://$manager_ip/api/v3.1/blueprints | jq
256 # API examples: use '| jq' to format JSON output
257 # curl -u admin:admin --header 'Tenant: default_tenant' http://$manager_ip/api/v3.1/blueprints | jq
258 # curl -u admin:admin --header 'Tenant: default_tenant' http://$manager_ip/api/v3.1/deployments | jq
259 # curl -u admin:admin --header 'Tenant: default_tenant' http://$manager_ip/api/v3.1/executions | jq
260 # curl -u admin:admin --header 'Tenant: default_tenant' http://$manager_ip/api/v3.1/deployments | jq -r '.items[0].blueprint_id'
261 # curl -u admin:admin --header 'Tenant: default_tenant' http://$manager_ip/api/v3.1/node-instances | jq
265 log "Cleanup cloudify"
269 dist=`grep DISTRIB_ID /etc/*-release | awk -F '=' '{print $2}'`