4 # POC Script to build/install/deploy/orchestrate Tacker on an OPNFV Brhamaputra Fuel cluster
5 # Script assuming it runs on the openstack primary controller (where is opendaylight
6 # present) and there is a fuel master on 10.20.0.2 and can be reached with default
9 # author: Ferenc Cserepkei <ferenc.cserepkei@ericsson.com>
11 # (c) 2016 Telefonaktiebolaget L. M. ERICSSON
13 # All rights reserved. This program and the accompanying materials are made available
14 # under the terms of the Apache License, Version 2.0 which accompanies this distribution,
15 # and is available at http://www.apache.org/licenses/LICENSE-2.0
19 SSH_OPTIONS=(-o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o LogLevel=error)
21 MYDIR=$(dirname $(readlink -f "$0"))
22 MYREPO="tacker-server"
23 CLIREPO="tacker-client"
26 CLIENT=$(echo python-python-tackerclient_*_all.deb)
27 JSONRPC=$(echo python-jsonrpclib_*_all.deb)
28 SERVER=$(echo python-tacker_*_all.deb)
33 # Function checks whether crudini is available, if not - installs
34 function chkCrudini () {
35 if [[ ! -f '/usr/bin/crudini' ]]; then
36 wget -N http://mirrors.kernel.org/ubuntu/pool/universe/p/python-iniparse/python-iniparse_0.4-2.1build1_all.deb
37 wget -N http://archive.ubuntu.com/ubuntu/pool/universe/c/crudini/crudini_0.3-1_amd64.deb
38 dpkg -i python-iniparse_0.4-2.1build1_all.deb crudini_0.3-1_amd64.deb
42 # Function checks whether a python egg is available, if not, installs
45 IPPACK=$(python - <<'____EOF'
47 from os.path import join
48 for package in pip.get_installed_distributions():
49 print(package.location)
50 print(join(package.location, *package._get_metadata("top_level.txt")))
53 echo "$IPPACK" | grep -q "$PKG"
59 # Function setting up the build/deploy environment
60 function envSetup () {
61 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BCE5CC461FA22B08
63 apt-get install -y git python-pip python-all debhelper
68 # Function installs jsonrpclib from github
69 function deployJsonrpclib () {
70 if [[ -e "${MYDIR}/${JSONRPC}" ]]; then
71 echo "$JSONRPC exists."
76 git clone https://github.com/joshmarshall/jsonrpclib.git $DEPREPO
78 dpkg --purge python-jsonrpclib
79 python setup.py --command-packages=stdeb.command bdist_deb
81 JSONRPC=$(echo python-jsonrpclib_*_all.deb)
86 # Function builds Tacker server from github
87 function buildTackerServer () {
88 if [[ -e "${MYDIR}/${SERVER}" ]]; then
89 echo "$SERVER exists."
94 git clone -b 'SFC_colorado' https://github.com/trozet/tacker.git $MYREPO
97 diff -ruN a/setup.cfg b/setup.cfg
98 --- a/setup.cfg 2016-02-08 10:54:37.416525934 +0100
99 +++ b/setup.cfg 2016-02-08 10:55:29.293428896 +0100
106 etc/tacker/api-paste.ini
107 etc/tacker/policy.json
108 etc/tacker/tacker.conf
109 etc/tacker/rootwrap.conf
112 etc/tacker/rootwrap.d/servicevm.filters
113 - etc/init.d = etc/init.d/tacker-server
114 + /etc/init.d = etc/init.d/tacker-server
119 dpkg --purge python-tacker
120 python setup.py --command-packages=stdeb.command bdist_deb
123 # Function corrects and installs the Tacker-server debian package
124 function blessPackage () {
125 pushd "${MYDIR}/${MYREPO}/deb_dist"
126 SERVER=$(echo python-tacker_*_all.deb)
128 DEBFILE="${MYDIR}/${MYREPO}/deb_dist/${SERVER}"
129 TMPDIR=$(mktemp -d /tmp/deb.XXXXXX) || exit 1
130 OUTPUT=$(basename "$DEBFILE")
131 if [[ -e "${MYDIR}/${OUTPUT}" ]]; then
132 echo "$OUTPUT exists."
136 dpkg-deb -x "$DEBFILE" "$TMPDIR"
137 dpkg-deb --control "$DEBFILE" "${TMPDIR}/DEBIAN"
140 diff -ruN DEBIAN/control DEBIAN/control
141 --- a/DEBIAN/control 2016-08-19 11:53:10.000000000 +0000
142 +++ b/DEBIAN/control 2016-08-19 12:01:49.629096317 +0000
145 Maintainer: OpenStack <openstack-dev@lists.openstack.org>
147 -Depends: python (>= 2.7), python (<< 2.8), python:any (>= 2.7.1-0ubuntu2), python-pbr, python-paste, python-pastedeploy, python-routes, python-anyjson, python-babel, python-eventlet, python-greenlet, python-httplib2, python-requests, python-iso8601, python-jsonrpclib, python-jinja2, python-kombu, python-netaddr, python-sqlalchemy (>= 1.0~), python-sqlalchemy (<< 1.1), python-webob, python-heatclient, python-keystoneclient, alembic, python-six, python-stevedore, python-oslo.config, python-oslo.messaging-, python-oslo.rootwrap, python-novaclient
148 +Depends: python (>= 2.7), python (<< 2.8), python:any (>= 2.7.1-0ubuntu2), python-pbr, python-paste, python-pastedeploy, python-routes, python-anyjson, python-babel, python-eventlet, python-greenlet, python-httplib2, python-requests, python-iso8601, python-jsonrpclib, python-jinja2, python-kombu, python-netaddr, python-sqlalchemy (>= 1.0~), python-sqlalchemy (<< 1.1), python-webob, python-heatclient, python-keystoneclient, alembic, python-six, python-stevedore, python-oslo.config, python-oslo.messaging, python-oslo.rootwrap, python-novaclient
151 Description: OpenStack servicevm/device manager
154 echo "Patching deb..."
155 dpkg -b "$TMPDIR" "${MYDIR}/${SERVER}"
157 dpkg -i "${MYDIR}/${SERVER}"
160 # Function deploys Tacker-server (installs missing mandatory files: upstart, default)
161 function deployTackerServer () {
162 rm -rf /etc/default/tacker-server
163 cat > /etc/default/tacker-server <<EOFTD
165 PIDFILE=/var/run/tacker/tacker-server.pid
166 LOGFILE=/var/log/tacker/tacker-server.log
167 PATH="\${PATH:+\$PATH:}/usr/sbin:/sbin"
168 TMPDIR=/var/lib/tacker/tmp
170 rm -rf /etc/init/tacker.conf
171 cat > /etc/init/tacker.conf <<EOFSC
172 # tacker-server - Provides the Tacker servicevm/device manager service
173 description "Openstack Tacker Server"
174 author "Ferenc Cserepkei <ferenc.cserepkei@ericsson.com>"
176 start on runlevel [2345]
177 stop on runlevel [!2345]
181 limit nofile 65535 65535
186 # stop job from continuing if no config file found for daemon
187 [ ! -f /etc/default/tacker-server ] && { stop; exit 0; }
188 [ ! -f /etc/tacker/tacker.conf ] && { stop; exit 0; }
190 # source the config file
191 . /etc/default/tacker-server
193 # stop job from continuing if admin has not enabled service in
195 [ -z "\$ENABLED" ] && { stop; exit 0; }
197 mkdir -p /var/run/tacker
198 mkdir -p /var/log/tacker
199 echo "Starting tacker server"
203 echo "Stopping tacker server"
206 exec /usr/bin/python /usr/bin/tacker-server --log-file=/var/log/tacker/tacker-server.log -v -d --config-file=/etc/tacker/tacker.conf
210 # Function installs python-tackerclient from github
211 function deployTackerClient() {
212 if [[ -e "${MYDIR}/${CLIENT}" ]]; then
213 echo "$CLIENT exists."
218 dpkg --purge python-tackerclient
219 git clone -b 'SFC_refactor' https://github.com/trozet/python-tackerclient.git $CLIREPO
221 python setup.py --command-packages=stdeb.command bdist_deb
223 CLIENT=$(echo python-python-tackerclient_*_all.deb)
225 dpkg -i "${MYDIR}/${CLIENT}"
228 # Function removes the cloned git repositories
229 function remove_repo () {
230 if [[ -d "${MYDIR}/${1}" ]]; then
235 # Funcion copies and installs built artifact on all remaining cluster nodes
236 function populate_client() {
237 wget -O deb http://archive.ubuntu.com/ubuntu/pool/universe/s/sshpass/sshpass_1.05-1_amd64.deb &&\
241 clusternodes=$(sshpass -p "r00tme" ssh ${SSH_OPTIONS[@]} root@10.20.0.2 fuel node | cut -d '|' -f 5 | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" )
242 myaddr=$(ifconfig br-fw-admin | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p')
243 for anode in $clusternodes ; do
244 if [ "$anode" != "$myaddr" ] ; then
245 echo "Installing $CLIENT on $anode"
246 scp ${SSH_OPTIONS[@]} -i "${MYDIR}/.ssh/id_rsa" ${CLIENT} ${fadm}@${anode}:${CLIENT}
247 ssh ${SSH_OPTIONS[@]} -i "${MYDIR}/.ssh/id_rsa" ${fadm}@${anode} sudo dpkg -i ${CLIENT}
248 ssh ${SSH_OPTIONS[@]} -i "${MYDIR}/.ssh/id_rsa" ${fadm}@${anode} rm ${CLIENT}
253 # Function orchestrate the Tacker service
254 function orchestrate () {
255 rm -rf /etc/puppet/modules/tacker
256 pushd /etc/puppet/modules
257 git clone https://github.com/trozet/puppet-tacker.git tacker
258 rm -rf /etc/puppet/modules/tacker/.git
263 # Port(s) Protocol ServiceDetails Source
264 # 8805-8872 tcp,udp Unassigned IANA
267 auth_uri=$(crudini --get '/etc/heat/heat.conf' 'keystone_authtoken' 'auth_uri')
268 identity_uri=$(crudini --get '/etc/heat/heat.conf' 'keystone_authtoken' 'identity_uri')
269 int_addr=$(ifconfig br-mesh | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p')
270 odl_addr=$(hiera management_vip)
271 mgmt_addr=$(ifconfig br-mgmt | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p')
272 pub_addr=$(ifconfig br-ex-lnx | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p')
273 rabbit_host=$(crudini --get '/etc/heat/heat.conf' 'oslo_messaging_rabbit' 'rabbit_hosts'| cut -d ':' -f 1)
274 rabbit_password=$(crudini --get '/etc/heat/heat.conf' 'oslo_messaging_rabbit' 'rabbit_password')
275 sql_host=$(hiera database_vip)
276 database_connection="mysql://tacker:tacker@${sql_host}/tacker"
277 internal_url="http://${int_addr}:${bind_port}"
278 admin_url="http://${mgmt_addr}:${bind_port}"
279 public_url="http://${pub_addr}:${bind_port}"
280 heat_api_vip=$(crudini --get '/etc/heat/heat.conf' 'heat_api' 'bind_host')
281 allowed_hosts="[ '${sql_host}', '${HOSTNAME%%.domain.tld}', 'localhost', '127.0.0.1', '%' ]"
282 heat_uri="http://${heat_api_vip}:8004/v1"
284 service_tenant='services'
288 cat > configure_tacker.pp << EOF
289 class mysql::config {}
290 include mysql::config
291 class mysql::server {}
292 include mysql::server
295 package_ensure => 'absent',
296 client_package_ensure => 'absent',
297 bind_port => '${bind_port}',
298 keystone_password => '${myPassword}',
299 keystone_tenant => '${service_tenant}',
300 auth_uri => '${auth_uri}',
301 identity_uri => '${identity_uri}',
302 database_connection => '${database_connection}',
303 rabbit_host => '${rabbit_host}',
304 rabbit_password => '${rabbit_password}',
305 heat_uri => '${heat_uri}',
306 opendaylight_host => '${odl_addr}',
307 opendaylight_port => '${odl_port}',
310 class { 'tacker::db::mysql':
311 password => '${myPassword}',
312 allowed_hosts => ${allowed_hosts},
315 class { 'tacker::keystone::auth':
316 password => '${myPassword}',
317 tenant => '${service_tenant}',
318 admin_url => '${admin_url}',
319 internal_url => '${internal_url}',
320 public_url => '${public_url}',
321 region => '${myRegion}',
325 apt-get install -y mysql-client-5.5
326 cat > /usr/bin/tacker-manage <<EOFAKEMANAGE
329 chmod +x /usr/bin/tacker-manage
330 puppet apply configure_tacker.pp
332 cat > tackerc <<EOFRC
335 export OS_NO_CACHE='true'
336 export OS_TENANT_NAME='${service_tenant}'
337 export OS_PROJECT_NAME='${service_tenant}'
338 export OS_USERNAME='tacker'
339 export OS_PASSWORD='${myPassword}'
340 export OS_AUTH_URL='${auth_uri}'
341 export OS_DEFAULT_DOMAIN='default'
342 export OS_AUTH_STRATEGY='keystone'
343 export OS_REGION_NAME='${myRegion}'
344 export TACKER_ENDPOINT_TYPE='internalURL'
349 # Funcion copies and installs built environment settings on all remaining cluster nodes
350 function populate_rc() {
351 wget -O deb http://archive.ubuntu.com/ubuntu/pool/universe/s/sshpass/sshpass_1.05-1_amd64.deb &&\
355 clusternodes=$(sshpass -p "r00tme" ssh ${SSH_OPTIONS[@]} root@10.20.0.2 fuel node | cut -d '|' -f 5 | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" )
356 myaddr=$(ifconfig br-fw-admin | sed -n '/inet addr/s/.*addr.\([^ ]*\) .*/\1/p')
357 for anode in $clusternodes ; do
358 if [ "$anode" != "$myaddr" ] ; then
359 echo "Populating settings to $anode"
360 scp ${SSH_OPTIONS[@]} -i "${MYDIR}/.ssh/id_rsa" tackerc ${fadm}@${anode}:tackerc
376 git clone https://github.com/trozet/sfc-random.git
378 remove_repo "$MYREPO"
379 remove_repo "$DEPREPO"
380 remove_repo "$CLIREPO"
382 echo "Built: ${MYDIR}/${OUTPUT}"
383 echo "Built: ${MYDIR}/${CLIENT}"
384 echo "Built: ${MYDIR}/${JSONRPC}"
385 echo "tackerc - mandatory environmental parameters file created"