#!/bin/bash

# go in a directory everybody can access
# (postgresql commands usually have a 'could not change to "$PWD"' error
# message if the postgres user cannot have access to $PWD...)
cd /

. /etc/openstackquickstartrc

. /usr/lib/openstack-quickstart/functions.sh

echo "Setting up OpenStack demo controller..."

grep -q bash.openstackrc /etc/bash.bashrc.local ||\
echo "export HOST_IP=$IP
. /etc/bash.openstackrc
setcreds admin $pw" >> /etc/bash.bashrc.local

install_packages patterns-OpenStack-controller patterns-OpenStack-clients patterns-OpenStack-network-node crudini psmisc

if [ "x$node_is_compute" = "xyes" ]; then
    install_packages patterns-OpenStack-compute-node
fi

if [ "x$with_tempest" = "xyes" ]; then
    install_packages openstack-ec2-api-s3 openstack-neutron-lbaas-agent \
        openstack-neutron-vpnaas openstack-neutron-fwaas \
        openstack-neutron-fwaas-test openstack-tempest-test \
        python-neutron-vpnaas-tempest-plugin
    if [ "x$with_manila" = "xyes" ]; then
        install_packages  openstack-manila-test
    fi
fi

if [ "x$with_manila" = "xyes" ]; then
    install_packages openstack-manila openstack-manila-api \
                     openstack-manila-scheduler openstack-manila-share \
                     openstack-manila-data python-manila python-manilaclient
fi

if [ "x$with_magnum" = "xyes" ]; then
    install_packages openstack-magnum openstack-magnum-api \
                     openstack-magnum-conductor python-magnum \
                     python-magnumclient
fi

if [ "x$with_barbican" = "xyes" ]; then
    install_packages openstack-barbican openstack-barbican-api\
		     openstack-barbican-keystone-listener \
		     openstack-barbican-worker openstack-barbican-retry \
		     python-barbican python-barbicanclient
fi

if [ "x$with_sahara" = "xyes" ]; then
    install_packages openstack-sahara openstack-sahara-api\
		     openstack-sahara-engine \
		     python-saharaclient
fi

if [ "x$with_designate" = "xyes" ]; then
    install_packages openstack-designate openstack-designate-api\
                     openstack-designate-central openstack-designate-producer \
                     openstack-designate-sink openstack-designate-worker \
                     python-designateclient
fi

if [ "x$with_gnocchi" = "xyes" ]; then
    install_packages openstack-gnocchi openstack-gnocchi-api \
                     openstack-gnocchi-metricd openstack-gnocchi-statsd \
                     python-gnocchiclient
fi

if [ "x$with_monasca" = "xyes" ]; then
    install_packages openstack-monasca-log-agent openstack-monasca-agent \
                     openstack-horizon-plugin-monasca-ui \
                     openstack-monasca-agent \
                     openstack-monasca-api \
                     openstack-monasca-log-agent \
                     openstack-monasca-log-api \
                     openstack-monasca-log-metrics \
                     openstack-monasca-log-persister \
                     openstack-monasca-log-transformer \
                     openstack-monasca-notification \
                     openstack-monasca-persister-java \
                     openstack-monasca-thresh \
                     monasca-installer \
                     elasticsearch \
                     influxdb \
                     kafka \
                     kibana \
                     mariadb \
                     storm-logviewer storm-nimbus storm-pacemaker storm-supervisor \
                     zookeeper-server
fi

if [ "$DB" = "postgresql" ] ; then
    if grep -q "SUSE Linux Enterprise Server 11" /etc/SuSE-release; then
        install_packages postgresql91-server python-psycopg2
    else
        install_packages postgresql-server python-psycopg2
    fi
fi

# configure NTP, because we need synchronized time between nodes
grep -q ntp.org /etc/ntp.conf || echo server pool.ntp.org >> /etc/ntp.conf

# configure tgt for cinder
if [ -f /etc/tgt/targets.conf ]; then
    grep -q "include /var/lib/cinder/volumes" /etc/tgt/targets.conf || {
        echo "include /var/lib/cinder/volumes/*" >> /etc/tgt/targets.conf
        start_and_enable_service tgtd
    }
fi

# Set up the database
if [ "$DB" = "postgresql" ] ; then
    DATADIR=/var/lib/pgsql/data
    # No database exists? Start and Stop to create the initial files
    if  [ ! -f $DATADIR/PG_VERSION ]; then
        start_and_enable_service $DB
        stop_and_disable_service $DB
    fi

    if [ "x$with_monasca" = "xyes" ]; then
        # Monasca needs MySQL either way
        start_and_enable_service mysql
    fi

    # increase max connections for multinode setup (this needs a restart)
    sed -i "s/^max_connections =.*/max_connections=1000/g" $DATADIR/postgresql.conf

    if ! grep -q ::/0 $DATADIR/pg_hba.conf ; then
        sed -i "s/^\(host .*\) ident\(.*\)/\1 md5 \2/" "$DATADIR/pg_hba.conf"
        sed -i "s/^\(local \)/local horizon all md5 sameuser\n\1/" "$DATADIR/pg_hba.conf"
        # allow remote connections:
        echo "listen_addresses = '*'" >> $DATADIR/postgresql.conf
        echo "host all all 0.0.0.0/0 md5  sameuser" >> $DATADIR/pg_hba.conf
        echo "host all all      ::/0 md5  sameuser" >> $DATADIR/pg_hba.conf
        if ! rpm -q postgresql | grep -q postgresql-8 ; then
            sed -i 's/\s*sameuser$//' $DATADIR/pg_hba.conf # adapt config syntax to postgresql-9
        fi
    fi
else
    echo | mysql -u root || pwquery=-p
    for DBNAME in nova cinder keystone glance horizon monasca neutron manila barbican sahara designate gnocchi; do
        echo "
        set global character_set_server=latin1;
        set session character_set_server=latin1;
        CREATE DATABASE IF NOT EXISTS $DBNAME;
        GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBNAME'@localhost IDENTIFIED BY '$mpw';
        GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBNAME'@'$(hostnamectl --static)' IDENTIFIED BY '$mpw';
        " | mysql -u root $pwquery
    done
fi


# start some initial services
for s in ntp ntpd $DB tgtd memcached
do
    start_and_enable_service $s
done

start_and_enable_service iscsid


# Set up the database
if [ "$DB" = "postgresql" ] ; then
    sudo -u postgres dropdb keystone || true # needed for keystone_data.sh
    for DBNAME in nova nova_api nova_cell0 cinder keystone glance horizon heat \
                       neutron manila magnum barbican sahara designate \
                       gnocchi ; do
        # use ALTER if CREATE fails: the role probably already exists
        # in that case
        sudo -u postgres psql -c "CREATE ROLE $DBNAME PASSWORD '$mpw' LOGIN;" || \
        sudo -u postgres psql -c "ALTER ROLE $DBNAME PASSWORD '$mpw' LOGIN;"
        sudo -u postgres createdb -O $DBNAME $DBNAME || true
    done
    sudo -u postgres createuser -s root || :

  # Monasca needs MySQL either way, so create a MySQL database for its use
  echo | mysql -u root || pwquery=-p
  echo "
  set global character_set_server=latin1;
  set session character_set_server=latin1;
  CREATE DATABASE IF NOT EXISTS monasca;
  GRANT ALL PRIVILEGES ON monasca.* TO 'monasca'@localhost IDENTIFIED BY '$mpw';
  GRANT ALL PRIVILEGES ON monasca.* TO 'monasca'@'$(hostnamectl --static)' IDENTIFIED BY '$mpw';
  " | mysql -u root $pwquery
fi

if [ "x$node_is_compute" = "xyes" ]; then
    setup_node_for_nova_compute
fi

# modprobe for snapshot support
modprobe dm_snapshot || :

disable_firewall_and_enable_forwarding

set -e

#-----------------------------------------
# setup OpenStack Dashboard (optional)
#-----------------------------------------


if [ "x$with_horizon" = "xyes" ]; then
    # configure dashboard/apache sample configuration from the package:
    install -m 644 /etc/apache2/conf.d/openstack-dashboard.conf{.sample,}
    a2enmod rewrite
    a2enmod ssl
    a2enmod wsgi
    a2enmod socache_shmcb
    a2enmod deflate

    DASHBOARD_LOCAL_SET=/srv/www/openstack-dashboard/openstack_dashboard/local/local_settings.py

    if ! grep -q "django.core.cache.backends.memcached.MemcachedCache" $DASHBOARD_LOCAL_SET ; then
        cat - >> $DASHBOARD_LOCAL_SET <<EOF
CACHES = {
    'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
    'LOCATION': '127.0.0.1:11211',
}
EOF
    fi

    if ! grep -q "^SESSION_ENGINE =" $DASHBOARD_LOCAL_SET ; then
        cat - >> $DASHBOARD_LOCAL_SET <<EOF
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
EOF
    fi

    if [ "$DB" = "postgresql" ] ; then
    cat >> $DASHBOARD_LOCAL_SET <<EODASHDB
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'HOST': '$IP',
        'NAME': 'horizon',
        'USER': 'horizon',
        'PASSWORD': '$mpw',
    }
}
EODASHDB
    fi

    sed -i -e "s/^DEBUG =.*/DEBUG = False/" $DASHBOARD_LOCAL_SET
    sed -i -e "s/^OPENSTACK_HOST = .*/OPENSTACK_HOST = \"$IP\"/" $DASHBOARD_LOCAL_SET

    if grep -q "^USE_SSL =" $DASHBOARD_LOCAL_SET; then
        sed -i -e "s/^USE_SSL =.*/USE_SSL = False/" $DASHBOARD_LOCAL_SET
    else
        echo "USE_SSL = False" >> $DASHBOARD_LOCAL_SET
    fi

    if grep -q "^ALLOWED_HOSTS =" $DASHBOARD_LOCAL_SET; then
        sed -i -e "s/^ALLOWED_HOSTS =.*/ALLOWED_HOSTS = ['*']/" $DASHBOARD_LOCAL_SET
    else
        echo "ALLOWED_HOSTS = ['*', ]" >> $DASHBOARD_LOCAL_SET
    fi

    # Use 'secure' session and CSRF cookies (bnc#753582):
    cat >> $DASHBOARD_LOCAL_SET <<EOSEC
# Use 'secure' cookies when we use SSL, see https://docs.djangoproject.com/en/1.4/topics/security/:
SESSION_COOKIE_SECURE = CSRF_COOKIE_SECURE = USE_SSL
EOSEC
    # sync dashboard DB "after" the database is created
    run_as wwwrun "cd /srv/www/openstack-dashboard; umask 0027; python -m 'manage' migrate --noinput"

    start_and_enable_service apache2
fi

#-----------------------------------------
# setup keystone client endpoint configuration
#-----------------------------------------

setup_keystone_authtoken /etc/glance/glance-api.conf.d/100-api.conf glance $ADMIN_PASSWORD
setup_keystone_authtoken /etc/glance/glance-registry.conf.d/100-registry.conf glance $ADMIN_PASSWORD
setup_keystone_authtoken /etc/neutron/neutron.conf.d/100-neutron.conf neutron $ADMIN_PASSWORD
setup_keystone_authtoken /etc/neutron/neutron.conf.d/100-neutron.conf nova $ADMIN_PASSWORD nova
setup_keystone_authtoken /etc/cinder/cinder.conf.d/100-cinder.conf cinder $ADMIN_PASSWORD
setup_keystone_authtoken /etc/heat/heat.conf.d/100-heat.conf heat $ADMIN_PASSWORD
setup_keystone_authtoken /etc/heat/heat.conf.d/100-heat.conf heat $ADMIN_PASSWORD trustee
setup_keystone_authtoken /etc/nova/nova.conf.d/100-nova.conf nova $ADMIN_PASSWORD
setup_keystone_authtoken /etc/nova/nova.conf.d/100-nova.conf neutron $ADMIN_PASSWORD neutron
setup_keystone_authtoken /etc/nova/nova.conf.d/100-nova.conf placement $ADMIN_PASSWORD placement

if [ "x$with_manila" = "xyes" ]; then
    setup_keystone_authtoken /etc/manila/manila.conf.d/100-manila.conf manila $ADMIN_PASSWORD
    setup_keystone_authtoken /etc/manila/manila.conf.d/100-manila.conf neutron $ADMIN_PASSWORD neutron
    setup_keystone_authtoken /etc/manila/manila.conf.d/100-manila.conf nova $ADMIN_PASSWORD nova
    setup_keystone_authtoken /etc/manila/manila.conf.d/100-manila.conf cinder $ADMIN_PASSWORD cinder
fi

if [ "x$with_magnum" = "xyes" ]; then
    setup_keystone_authtoken /etc/magnum/magnum.conf.d/100-magnum.conf magnum $ADMIN_PASSWORD
    setup_keystone_authtoken /etc/magnum/magnum.conf.d/100-magnum.conf magnum $ADMIN_PASSWORD keystone_auth
fi

if [ "x$with_barbican" = "xyes" ]; then
    setup_keystone_authtoken /etc/barbican/barbican.conf.d/100-barbican.conf barbican $ADMIN_PASSWORD
    crudini --set /etc/barbican/barbican.conf.d/100-barbican.conf keystone_authtoken auth_version 'v3.0'
fi

if [ "x$with_sahara" = "xyes" ]; then
    setup_keystone_authtoken /etc/sahara/sahara.conf.d/100-sahara.conf sahara $ADMIN_PASSWORD
fi

if [ "x$with_designate" = "xyes" ]; then
    setup_keystone_authtoken /etc/designate/designate.conf.d/100-designate.conf designate $ADMIN_PASSWORD
fi

if [ "x$with_gnocchi" = "xyes" ]; then
    setup_keystone_authtoken /etc/gnocchi/gnocchi.conf.d/100-gnocchi.conf gnocchi $ADMIN_PASSWORD
fi

#-----------------------------------------
## setup glance configuration
#-----------------------------------------
c_api=/etc/glance/glance-api.conf.d/100-api.conf
crudini --set $c_api DEFAULT workers "1"
crudini --set $c_api database connection "$DB://glance:$mpw@$IP/glance"
crudini --set $c_api glance_store filesystem_store_datadir /var/lib/glance/images/

c_reg=/etc/glance/glance-registry.conf.d/100-registry.conf
crudini --set $c_reg DEFAULT workers "1"
crudini --set $c_reg database connection "$DB://glance:$mpw@$IP/glance"

#-----------------------------------------
## setup nova configuration
#-----------------------------------------
FIXED_KEY=""
for i in $(seq 1 64); do
    FIXED_KEY+=$(printf "%x\n" $(($RANDOM % 16)))
done

c=/etc/nova/nova.conf.d/100-nova.conf
setup_messaging_client $c $IP $pw
crudini --set $c database connection "$DB://nova:$mpw@$IP/nova"
crudini --set $c api_database connection "$DB://nova_api:$mpw@$IP/nova_api"
crudini --set $c glance host $IP
crudini --set $c glance api_servers "http://$IP:9292"
crudini --set $c DEFAULT connection_type libvirt
crudini --set $c DEFAULT compute_driver libvirt.LibvirtDriver
crudini --set $c DEFAULT service_neutron_metadata_proxy True
crudini --set $c DEFAULT mkisofs_cmd /usr/bin/mkisofs
# deprecated
crudini --set $c DEFAULT use_neutron True
crudini --set $c vnc novncproxy_base_url "http://$IP:6080/vnc_auto.html"
crudini --set $c neutron default_floating_pool ext
crudini --set $c DEFAULT my_ip "$IP"
crudini --set $c DEFAULT osapi_compute_workers "1"
crudini --set $c DEFAULT ec2_workers "1"
crudini --set $c DEFAULT metadata_workers "1"
crudini --set $c conductor workers "1"
crudini --set $c placement os_region_name "RegionOne"

metadata_secret=$(echo $ADMIN_PASSWORD | md5sum | cut -d" " -f1)
crudini --set $c neutron service_metadata_proxy True
crudini --set $c neutron metadata_proxy_shared_secret $metadata_secret
crudini --set $c key_manager fixed_key "$FIXED_KEY"

# placement api
install -m 644 /etc/apache2/vhosts.d/nova-placement-api.conf{.sample,}

start_and_enable_service apache2
# may be needed if Horizon already started apache2
service apache2 restart


setup_nova_compute

extensions_path=$(ls -d /usr/lib*/python*/site-packages/extensions 2> /dev/null | head -n 1)
if [ -n "$extensions_path" ]; then
    crudini --set $c DEFAULT osapi_extensions_path "$extensions_path"
fi

#-----------------------------------------
## setup cinder configuration
#-----------------------------------------
c=/etc/cinder/cinder.conf.d/100-cinder.conf
crudini --set $c DEFAULT my_ip "$IP"
crudini --set $c DEFAULT osapi_volume_workers "1"
crudini --set $c database connection "$DB://cinder:${mpw}@${IP}/cinder"
crudini --set $c keymgr fixed_key "$FIXED_KEY"
# configure a cinder backend (LVM)
cinder_backend_name="backend-1"
crudini --set $c DEFAULT enabled_backends $cinder_backend_name
crudini --set $c $cinder_backend_name volume_driver "cinder.volume.drivers.lvm.LVMVolumeDriver"
crudini --set $c $cinder_backend_name volume_group "cinder-volumes"
crudini --set $c $cinder_backend_name lvm_type "thin"
crudini --set $c $cinder_backend_name iscsi_protocol "iscsi"


if [ "x$with_tempest" = "xyes" ]; then
    crudini --set $c DEFAULT volume_clear none
    crudini --set $c DEFAULT lvm_type thin
fi


#-----------------------------------------
## setup keystone configuration
#-----------------------------------------
c=/etc/keystone/keystone.conf.d/100-keystone.conf
crudini --set $c database connection $DB://keystone:$mpw@$IP/keystone
crudini --set $c DEFAULT admin_token "$SERVICE_TOKEN"
crudini --set $c DEFAULT public_workers 2
crudini --set $c DEFAULT admin_workers 2

# keystone needs now apache with wsgi (modified version
# https://github.com/openstack/keystone/blob/master/httpd/wsgi-keystone.conf )
cat <<EOF > /etc/apache2/vhosts.d/keystone.conf
Listen 5000
Listen 35357

<VirtualHost *:5000>
    WSGIDaemonProcess keystone-public processes=2 threads=1 user=keystone group=keystone display-name=%{GROUP}
    WSGIProcessGroup keystone-public
    WSGIScriptAlias / /usr/bin/keystone-wsgi-public
    WSGIApplicationGroup %{GLOBAL}
    WSGIPassAuthorization On
    LimitRequestBody 114688
    ErrorLogFormat "%{cu}t %M"
    ErrorLog /var/log/keystone/keystone.log
    CustomLog /var/log/keystone/keystone_access.log combined

    <Directory /usr/bin>
        Require all granted
    </Directory>
    Alias /identity /usr/bin/keystone-wsgi-public
    <Location /identity>
        SetHandler wsgi-script
        Options +ExecCGI

        WSGIProcessGroup keystone-public
        WSGIApplicationGroup %{GLOBAL}
        WSGIPassAuthorization On
    </Location>
</VirtualHost>

<VirtualHost *:35357>
    WSGIDaemonProcess keystone-admin processes=2 threads=1 user=keystone group=keystone display-name=%{GROUP}
    WSGIProcessGroup keystone-admin
    WSGIScriptAlias / /usr/bin/keystone-wsgi-admin
    WSGIApplicationGroup %{GLOBAL}
    WSGIPassAuthorization On
    LimitRequestBody 114688
    ErrorLogFormat "%{cu}t %M"
    ErrorLog /var/log/keystone/keystone.log
    CustomLog /var/log/keystone/keystone_access.log combined

    <Directory /usr/bin>
        Require all granted
    </Directory>
    Alias /identity_admin /usr/bin/keystone-wsgi-admin
    <Location /identity_admin>
        SetHandler wsgi-script
        Options +ExecCGI

        WSGIProcessGroup keystone-admin
        WSGIApplicationGroup %{GLOBAL}
        WSGIPassAuthorization On
    </Location>
</VirtualHost>
EOF

a2enmod wsgi
# apache needs a restart for the new vhost
stop_and_disable_service apache2
start_and_enable_service apache2

sleep 5

# migrate database for keystone (previously done in the keystone init script)
su keystone -s /bin/sh -c "keystone-manage db_sync"

keystone_data=/usr/lib/devstack/keystone_data.sh
ENABLED_SERVICES="g-api,g-reg,key,n-api,n-cpu,n-net,n-vol,c-api,n-sch,n-novnc,n-xvnc,q-svc,heat,m-api,mysql,rabbit"
if [ "x$with_horizon" = "xyes" ]; then
    ENABLED_SERVICES+=",horizon"
fi
if [ "x$with_tempest" = "xyes" ]; then
    ENABLED_SERVICES+=",tempest"
fi
if [ "x$with_magnum" = "xyes" ]; then
    ENABLED_SERVICES+=",magnum-api,magnum-cond"
fi
if [ "x$with_barbican" = "xyes" ]; then
    ENABLED_SERVICES+=",barbican-api,barbican-retry,barbican-keystone-listener,barbican-worker"
fi
if [ "x$with_sahara" = "xyes" ]; then
    ENABLED_SERVICES+=",sahara-api,sahara-engine"
fi
if [ "x$with_designate" = "xyes" ]; then
    ENABLED_SERVICES+=",designate-api,designate-central"
fi
if [ "x$with_gnocchi" = "xyes" ]; then
    ENABLED_SERVICES+=",gnocchi-api,gnocchi-statsd,gnocchi-metricd"
fi
if [ "x$with_monasca" = "xyes" ]; then
    ENABLED_SERVICES+=",monasca-api,monasca-log-api"
fi

SERVICE_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT

ADMIN_PASSWORD=$ADMIN_PASSWORD SERVICE_HOST=$SERVICE_HOST \
    SERVICE_ENDPOINT=$SERVICE_ENDPOINT DEVSTACK_DIR=/root \
    ENABLED_SERVICES=$ENABLED_SERVICES bash $keystone_data

. /etc/bash.bashrc.local

if which aa-complain >&/dev/null; then
    aa-complain /etc/apparmor.d/usr.sbin.libvirtd
fi
if [ -e /etc/init.d/boot.apparmor ]; then
    stop_and_disable_service boot.apparmor
fi

#-----------------------------------------
## setup neutron configuration
#-----------------------------------------
SERVICE_TENANT_ID=`get_service_tenant_id`

c=/etc/neutron/neutron.conf.d/100-neutron.conf
crudini --set $c database connection $DB://neutron:$mpw@$IP/neutron
crudini --set $c DEFAULT core_plugin neutron.plugins.ml2.plugin.Ml2Plugin
crudini --set $c DEFAULT service_plugins "neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"
crudini --set $c DEFAULT allow_overlapping_ips true
crudini --set $c DEFAULT notify_nova_on_port_status_change true
crudini --set $c DEFAULT notify_nova_on_port_data_changes true

c_lba=/etc/neutron/neutron-linuxbridge-agent.conf.d/100-linuxbrdige-agent.conf
crudini --set $c_lba linux_bridge physical_interface_mappings physnet1:$TENANT_ETH
crudini --set $c_lba securitygroup firewall_driver neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
crudini --set $c_lba vxlan enable_vxlan False

c_ml2=/etc/neutron/plugins/ml2/ml2_conf.ini
crudini --set $c_ml2 ml2 mechanism_drivers linuxbridge
crudini --set $c_ml2 ml2 tenant_network_types vlan
crudini --set $c_ml2 ml2 type_drivers local,flat,vlan
crudini --set $c_ml2 ml2_type_vlan network_vlan_ranges physnet1:$TENANT_VLAN_RANGE
crudini --set $c_ml2 securitygroup firewall_driver neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
crudini --set $c_ml2 securitygroup enable_ipset False

c_dhcpa=/etc/neutron/neutron-dhcp-agent.conf.d/100-dhcp-agent.conf
crudini --set $c_dhcpa DEFAULT dhcp_delete_namespaces True
crudini --set $c_dhcpa DEFAULT use_namespaces true
crudini --set $c_dhcpa DEFAULT interface_driver neutron.agent.linux.interface.BridgeInterfaceDriver

c_l3a=/etc/neutron/neutron-l3-agent.conf.d/100-l3-agent.conf
crudini --set $c_l3a DEFAULT use_namespaces true
crudini --set $c_l3a DEFAULT interface_driver neutron.agent.linux.interface.BridgeInterfaceDriver

crudini --set /etc/neutron/metadata_agent.ini DEFAULT metadata_proxy_shared_secret $metadata_secret

if [ "x$with_tempest" = "xyes" ]; then
    crudini --set $c DEFAULT service_plugins "neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2, neutron.services.l3_router.l3_router_plugin.L3RouterPlugin, neutron.services.vpn.plugin.VPNDriverPlugin, neutron.services.metering.metering_plugin.MeteringPlugin, neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin"
    # configure Neutron Lbaas v2 service
    crudini --set /etc/neutron/neutron_lbaas.conf service_providers service_provider "LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default"
    # configure Neutron FWaaS
    crudini --set /etc/neutron/fwaas_driver.ini service_providers service_provider "FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.IptablesFirewallDriver:default"
    crudini --set $c_l3a AGENT extensions "fwaas"
    crudini --set $c_l3a fwaas agent_version "v1"
    crudini --set $c_l3a fwaas driver "iptables"
    crudini --set $c_l3a fwaas enabled "True"
fi

# the default systemd socket activation only listens on the loopback interface
# which causes rabbitmq to try to start its own epmd
mkdir -p /etc/systemd/system/epmd.socket.d
cat <<EOF > /etc/systemd/system/epmd.socket.d/ports.conf
[Socket]
ListenStream=
ListenStream=[::]:4369
EOF
systemctl daemon-reload
systemctl restart epmd.socket epmd.service

# as workaround, we need to install rabbitmq-server-plugins to not get:
# {"init terminating in do_boot",{undef,[{rabbit_nodes,ensure_epmd,[],[]},{rabbit_cli,start_distribution,0,[{file,"src/rabbit_cli.erl...
install_packages rabbitmq-server-plugins

start_and_enable_service rabbitmq-server

sleep 2
if ! rabbitmqctl list_users|grep -q openstack; then
    rabbitmqctl add_user openstack $ADMIN_PASSWORD
    rabbitmqctl set_permissions openstack ".*" ".*" ".*"
fi

# Start Keystone and Neutron
for s in openstack-keystone \
    openstack-neutron openstack-neutron-linuxbridge-agent openstack-neutron-dhcp-agent \
    openstack-neutron-l3-agent openstack-neutron-metadata-agent
do
    start_and_enable_service $s
done

if [ "x$with_tempest" = "xyes" ]; then
    start_and_enable_service openstack-neutron-lbaasv2-agent
fi

### create subnets
## fixed
if ! openstack network show fixed; then
    openstack network create --project $SERVICE_TENANT_ID --share --provider-network-type vlan \
              --provider-segment $FIXED_VLAN --provider-physical-network physnet1 fixed
fi

if ! openstack subnet show fixed; then
    openstack subnet create --dns-nameserver 8.8.8.8 --dns-nameserver 8.8.4.4 --subnet-range $testnet --network fixed fixed
fi

if ! openstack router show public; then
    openstack router create --project $SERVICE_TENANT_ID public
    openstack router add subnet public fixed
fi

## floating/external
if ! openstack network show ext ; then
    if [ x$FLOATING_VLAN != x ]; then
        openstack network create --project $SERVICE_TENANT_ID --provider-network-type vlan \
                  --external --provider-segment $FLOATING_VLAN --provider-physical-network physnet1 ext
    else
        openstack network create --project $SERVICE_TENANT_ID --provider-network-type local --external ext
    fi
fi

if ! openstack subnet show ext; then
    ext_network_id=$(openstack network show ext -c id -f value)
    if [ x$FLOATING_VLAN != x ]; then
        openstack subnet create --project $SERVICE_TENANT_ID --no-dhcp --subnet-range $floatingnet --network ext ext
    else
        openstack subnet create --project $SERVICE_TENANT_ID --no-dhcp --subnet-range $floatingnet --network ext ext
    fi
fi
openstack router set --external-gateway ext public
# create four floatingip pools
for i in 1 2 3 4; do
    openstack floating ip create ext
done
### create routing configuration for external bridge
ext_bridge_name=`get_ext_bridge_name`
ext_bridge_ip=`get_ext_bridge_ip`/`get_ext_bridge_ip_prefix`
ext_bridge_cidr=`get_ext_bridge_cidr`

if [ x$FLOATING_VLAN = x ]; then
    setup_ext_bridge_on_boot $ext_bridge_name $ext_bridge_ip $ext_bridge_cidr
    systemctl restart wickedd
    ifup $ext_bridge_name
fi
#-----------------------------------------
## end neutron setup configuration
#---------------------------------------

# Start glance and nova
for s in openstack-glance-api openstack-glance-registry \
    openstack-nova-api openstack-nova-conductor openstack-nova-scheduler \
    openstack-nova-novncproxy openstack-nova-consoleauth
do
    start_and_enable_service $s
done

if [ "x$node_is_compute" = "xyes" ]; then
    start_and_enable_service openstack-nova-compute
fi

# migrate data directly
nova-manage db online_data_migrations

# do cell setup (mandatory since Ocata)
nova-manage cell_v2 simple_cell_setup --transport-url rabbit://openstack:$pw@$IP
nova-manage cell_v2 discover_hosts --verbose

### Figure out why this  restart is needed ??!
# 2018-08-30: without the compute node is not registered properly
for s in openstack-nova-conductor openstack-nova-scheduler; do
    systemctl restart $s
done

if [ "x$with_tempest" = "xyes" ]; then
    start_and_enable_service openstack-ec2-api-s3
fi

if [ "x$with_horizon" = "xyes" ]; then
    # Start nova related services
    start_and_enable_service openstack-nova-console
    start_and_enable_service openstack-nova-consoleauth
    start_and_enable_service openstack-nova-novncproxy
fi

#-----------------------------------------
## setup heat configuration
#-----------------------------------------
setup_messaging_client /etc/heat/heat.conf $IP $pw
c=/etc/heat/heat.conf.d/100-heat.conf
crudini --set $c database connection $DB://heat:$mpw@$IP/heat
crudini --set $c DEFAULT deferred_auth_method trusts
crudini --set $c DEFAULT num_engine_workers "1"
crudini --set $c heat_api workers "1"
crudini --set $c clients_keystone auth_uri "http://$IP:35357/"

HEAT_DOMAIN_ID=$(get_or_create_domain heat 'Owns users and projects created by heat')
get_or_create_user heat_domain_admin $ADMIN_PASSWORD $HEAT_DOMAIN_ID
get_or_add_user_domain_role admin heat_domain_admin $HEAT_DOMAIN_ID

crudini --set $c DEFAULT stack_user_domain_id $HEAT_DOMAIN_ID
crudini --set $c DEFAULT stack_domain_admin heat_domain_admin
crudini --set $c DEFAULT stack_domain_admin_password $ADMIN_PASSWORD

for s in openstack-heat-engine openstack-heat-api-cfn openstack-heat-api; do
    start_and_enable_service $s
done

#-----------------------------------------
## setup loopback LVM configuration
#-----------------------------------------

openstack_loopback_lvm=/usr/sbin/openstack-loopback-lvm
$openstack_loopback_lvm
if [ "$?" -ne "0" ]; then
    # setup failed, so do not use
    for s in api scheduler volume ; do
        insserv -r openstack-cinder-$s
    done
else
    grep -q openstack-loopback-lvm /etc/init.d/boot.local || echo $openstack_loopback_lvm >> /etc/init.d/boot.local
    chmod +x /etc/init.d/boot.local

    # SLE11 and other old distros need boot.lvm enabled
    if [ -z "$(type -p systemctl)" ]; then
        insserv boot.lvm
        /etc/init.d/boot.lvm start
    fi
    start_and_enable_service openstack-cinder-api
    sleep 1
    for s in scheduler volume ; do
        start_and_enable_service openstack-cinder-$s
    done
fi

setcreds admin $pw
security_group_id_admin=`openstack security group list --project admin -f value -c ID`
security_group_id_demo=`openstack security group list --project demo -f value -c ID`
for sec_group_id in $security_group_id_admin $security_group_id_demo; do
    openstack security group rule create --protocol icmp $sec_group_id
    openstack security group rule create --protocol tcp --dst-port 22:22 --remote-ip 0.0.0.0/0 $sec_group_id
    openstack security group rule create --protocol tcp --dst-port 1:65535 --remote-ip 0.0.0.0/0 $sec_group_id
    openstack security group rule create --protocol udp --dst-port 1:65535 --remote-ip 0.0.0.0/0 $sec_group_id
done

#-----------------------------------------
# setup OpenStack Manila
#-----------------------------------------
if [ "x$with_manila" = "xyes" ]; then
    # nfsserver is needed for the lvm driver
    install_packages nfs-kernel-server nfs-client nfs-utils
    start_and_enable_service nfsserver

    c="/etc/manila/manila.conf.d/100-manila.conf"
    setup_messaging_client $c $IP $pw
    crudini --set $c DEFAULT my_ip "$IP"
    crudini --set $c DEFAULT default_share_type "default"
    crudini --set $c database connection "$DB://manila:${mpw}@${IP}/manila"
    crudini --set $c identity uri $KEYSTONE_PUBLIC_ENDPOINT
    crudini --set $c DEFAULT share_volume_fstype ext3

    # create and enable a manila backend
    crudini --set $c DEFAULT enabled_share_backends backend-0
    crudini --set $c backend-0 share_driver manila.share.drivers.lvm.LVMShareDriver
    crudini --set $c backend-0 share_backend_name default
    crudini --set $c backend-0 driver_handles_share_servers false
    crudini --set $c backend-0 lvm_share_volume_group manila-shares
    crudini --set $c backend-0 lvm_share_export_ip $IP

    start_and_enable_service openstack-manila-api
    start_and_enable_service openstack-manila-scheduler
    start_and_enable_service openstack-manila-share
    start_and_enable_service openstack-manila-data
    # retry a bit until manila-api is ready
    for i in {1..5}; do manila type-create default false && break || sleep 1; done
fi

#-----------------------------------------
# setup OpenStack Magnum
#-----------------------------------------
if [ "x$with_magnum" = "xyes" ]; then
    c="/etc/magnum/magnum.conf.d/100-magnum.conf"
    setup_messaging_client $c $IP $pw

    trustee_domain_id=$(get_or_create_domain magnum 'Owns users and projects created by magnum')
    trustee_domain_admin_id=$(get_or_create_user trustee_domain_admin $ADMIN_PASSWORD $trustee_domain_id)
    openstack --os-auth-url $KEYSTONE_PUBLIC_ENDPOINT_V3 \
              --os-identity-api-version 3 role add \
              --user $trustee_domain_admin_id --domain $trustee_domain_id \
              admin
    crudini --set $c trust trustee_domain_id $trustee_domain_id
    crudini --set $c trust trustee_domain_admin_id $trustee_domain_admin_id
    crudini --set $c trust trustee_domain_admin_password $ADMIN_PASSWORD
    crudini --set $c database connection "$DB://magnum:${mpw}@${IP}/magnum"
    crudini --set $c cinder_client region_name RegionOne
    crudini --set $c api host $IP
    crudini --set $c certificates cert_manager_type local
    crudini --set $c certificates storage_path /var/lib/magnum/certificates/

    start_and_enable_service openstack-magnum-api
    start_and_enable_service openstack-magnum-conductor
fi

#-----------------------------------------
# setup OpenStack Barbican
#-----------------------------------------
if [ "x$with_barbican" = "xyes" ]; then
    c="/etc/barbican/barbican.conf.d/100-barbican.conf"
    setup_messaging_client $c $IP $pw

    a2enmod rewrite
    a2enmod wsgi

    crudini --set $c database connection "$DB://barbican:${mpw}@${IP}/barbican"
    crudini --set $c DEFAULT host_href http://${IP}:9311

    cp /etc/apache2/vhosts.d/barbican-api.conf.sample /etc/apache2/vhosts.d/barbican-api.conf

    start_and_enable_service apache2

    # may be needed if Horizon already started apache2
    service apache2 restart

    start_and_enable_service openstack-barbican-keystone-listener
    start_and_enable_service openstack-barbican-retry
    start_and_enable_service openstack-barbican-worker
fi

#-----------------------------------------
# setup OpenStack Sahara
#-----------------------------------------
if [ "x$with_sahara" = "xyes" ]; then
    c="/etc/sahara/sahara.conf.d/100-sahara.conf"
    setup_messaging_client $c $IP $pw

    crudini --set $c database connection "$DB://sahara:${mpw}@${IP}/sahara"

    #TODO(toabctl): configure and start services
    #start_and_enable_service openstack-sahara-api
    #start_and_enable_service openstack-sahara-engine
fi

#-----------------------------------------
# setup OpenStack Designate
#-----------------------------------------
if [ "x$with_designate" = "xyes" ]; then
    c="/etc/designate/designate.conf.d/100-designate.conf"
    setup_messaging_client $c $IP $pw

    crudini --set $c database connection "$DB://designate:${mpw}@${IP}/designate"

    #TODO(toabctl): configure and start services
    #start_and_enable_service openstack-designate-api
fi

#-----------------------------------------
# setup OpenStack Gnocchi
#-----------------------------------------
if [ "x$with_gnocchi" = "xyes" ]; then
    c="/etc/gnocchi/gnocchi.conf.d/100-gnocchi.conf"
    setup_messaging_client $c $IP $pw

    crudini --set $c database connection "$DB://gnocchi:${mpw}@${IP}/gnocchi"

    #TODO(toabctl): configure and start services
    #start_and_enable_service openstack-gnocchi-statsd
fi

#-----------------------------------------
# setup Monasca
#-----------------------------------------

if [ "x$with_monasca" = "xyes" ]; then
    # setup ssh for ansible/monasca-installer
    ssh_key=~/.ssh/id_rsa
    rm -f $ssh_key
    ssh-keygen -b 2048 -t rsa -f $ssh_key -q -N ""
    cat $ssh_key.pub >> ~/.ssh/authorized_keys

    # configure ansible
    cat <<EOF >> ~/.ansible.cfg
[defaults]
host_key_checking = False
EOF

    # configure monasca-installer credentials
    cred_file=/opt/monasca-installer/credentials.yml
    for cred_name in influxdb_mon_api_password \
                     influxdb_mon_persister_password \
                     database_notification_password \
                     database_monapi_password database_thresh_password \
                     keystone_monasca_operator_password \
                     keystone_monasca_agent_password \
                     keystone_admin_agent_password \
                     keystone_admin_password \
                     database_grafana_password; do
        sed -i 's!^'"$cred_name"':$!'"$cred_name"': '"$ADMIN_PASSWORD"'!' $cred_file
    done

    ### configure monasca-installer group vars
    sed -i 's!useast!RegionOne!' /opt/monasca-installer/group_vars/monasca_log_api_group
    sed -i 's!useast!RegionOne!' /opt/monasca-installer/group_vars/monasca_api_group

    # configure monasca-installer host definitions
    cat <<EOF >> /opt/monasca-installer/monasca-hosts
localhost                        ansible_connection=local
monasca-node                     ansible_ssh_host=$IP ansible_ssh_user=root
keystone-node                    ansible_ssh_host=$IP ansible_ssh_user=root
log-transformer-node             ansible_ssh_host=$IP ansible_ssh_user=root
log-persister-node               ansible_ssh_host=$IP ansible_ssh_user=root
kibana-node                      ansible_ssh_host=$IP ansible_ssh_user=root
elasticsearch-node               ansible_ssh_host=$IP ansible_ssh_user=root
memcached-node                   ansible_ssh_host=$IP ansible_ssh_user=root
kafka-node                       ansible_ssh_host=$IP ansible_ssh_user=root
zookeeper-node                   ansible_ssh_host=$IP ansible_ssh_user=root
monasca-api-node                 ansible_ssh_host=$IP ansible_ssh_user=root
monasca-log-api-node             ansible_ssh_host=$IP ansible_ssh_user=root
monasca-notification-node        ansible_ssh_host=$IP ansible_ssh_user=root
monasca-persister-node           ansible_ssh_host=$IP ansible_ssh_user=root
monasca-log-metrics-node         ansible_ssh_host=$IP ansible_ssh_user=root
storm-nimbus-node                ansible_ssh_host=$IP ansible_ssh_user=root
storm-supervisor-node            ansible_ssh_host=$IP ansible_ssh_user=root
monasca-thresh-node              ansible_ssh_host=$IP ansible_ssh_user=root
mariadb-node                     ansible_ssh_host=$IP ansible_ssh_user=root
elasticsearch-curator-node       ansible_ssh_host=$IP ansible_ssh_user=root
influxdb-node                    ansible_ssh_host=$IP ansible_ssh_user=root

[openstack_group]
keystone-node

[memcached_group]
memcached-node

[kafka_group]
kafka-node

[zookeeper_group]
zookeeper-node

[monasca_group]
monasca-node

[monasca_api_group]
monasca-api-node database_node_for_api=monasca-node influxdb_node_for_api=influxdb-node

[monasca_notification_group]
monasca-notification-node database_node_for_notification=monasca-node

[monasca_persister_group]
monasca-persister-node influxdb_node_for_persister=influxdb-node

[monasca_log_api_group]
monasca-log-api-node

[monasca_log_metrics_group]
monasca-log-metrics-node

[monasca_log_persister_group]
log-persister-node

[monasca_log_transformer_group]
log-transformer-node

[elasticsearch_group]
elasticsearch-node

[kibana_group]
kibana-node es_node_for_kibana=elasticsearch-node

[storm_nimbus_group]
storm-nimbus-node

[storm_supervisor_group]
storm-supervisor-node

[monasca_thresh_group]
monasca-thresh-node database_node_for_thresh=monasca-node

[mariadb_group]
mariadb-node

[elasticsearch_curator_group]
elasticsearch-curator-node

[influxdb_group]
influxdb-node

################################################################################
# Group inheritance
################################################################################

[elkstack_group:children]
elasticsearch_group
kibana_group
monasca_log_persister_group
monasca_log_transformer_group
monasca_log_metrics_group
elasticsearch_curator_group

[storm_group:children]
storm_nimbus_group
storm_supervisor_group

[all_group:children]
openstack_group
monasca_group

[monasca_group:children]
elkstack_group
memcached_group
kafka_group
zookeeper_group
monasca_log_api_group
monasca_api_group
monasca_notification_group
monasca_persister_group
storm_group
monasca_thresh_group
mariadb_group
influxdb_group
EOF

    # prerequisite services
    start_and_enable_service zookeeper
    start_and_enable_service kafka

    start_and_enable_service storm-supervisor
    start_and_enable_service storm-pacemaker
    start_and_enable_service storm-nimbus

    start_and_enable_service influxdb
    start_and_enable_service mysql
    start_and_enable_service elasticsearch
    start_and_enable_service kibana

    # Influxdb database
    echo 'create database mon' | influx

    # Keystone users, projects and roles
    get_or_create_project monasca

    get_or_create_user monasca-operator $pw
    get_or_create_user monasca-agent $pw
    get_or_create_user monasca-admin-agent $pw

    get_or_create_role monasca-user
    get_or_create_role monasca-agent
    get_or_create_role monasca-operator

    # Roles for monasca-operator user
    get_or_add_user_project_role monasca-user monasca-operator monasca
    get_or_add_user_project_role admin monasca-operator monasca

    # Roles for monasca-agent user
    get_or_add_user_project_role monasca-agent monasca-agent monasca

    # Monasca roles in admin project
    get_or_add_user_project_role monasca-user admin admin
    get_or_add_user_project_role monasca-agent monasca-admin-agent admin


    # finally run monasca-installer
    (
        cd /opt/monasca-installer
        ansible-playbook -i monasca-hosts monasca.yml
    )

    # do the agent setup
    monasca-setup \
        -u "admin" \
        -p "$pw" \
        --skip_enable \
        --log_dir "/var/log/monasca-agent/" \
        --project_name admin \
        --user "monasca-agent" \
        --keystone_url "http://$IP:5000/v3/" \
        --monasca_url "http://$IP:8070/v3.0/"

    start_and_enable_service  openstack-monasca-agent
fi

#-----------------------------------------
# setup tempest configuration
#-----------------------------------------

if [ "x$with_tempest" = "xyes" -a -e /etc/tempest/tempest.conf ]; then
    crudini --set /etc/tempest/tempest.conf auth allow_tenant_isolation false
    crudini --set /etc/tempest/tempest.conf auth use_dynamic_credentials True
    crudini --set /etc/tempest/tempest.conf auth tempest_roles Member
    crudini --set /etc/tempest/tempest.conf auth admin_domain_name Default
    crudini --set /etc/tempest/tempest.conf auth admin_tenant_name admin
    crudini --set /etc/tempest/tempest.conf auth admin_password $pw
    crudini --set /etc/tempest/tempest.conf auth admin_username admin
    crudini --set /etc/tempest/tempest.conf identity uri $KEYSTONE_PUBLIC_ENDPOINT
    crudini --set /etc/tempest/tempest.conf identity uri_v3 $KEYSTONE_PUBLIC_ENDPOINT_V3
    crudini --set /etc/tempest/tempest.conf identity auth_version v3
    crudini --set /etc/tempest/tempest.conf identity username demo
    crudini --set /etc/tempest/tempest.conf identity tenant_name demo
    crudini --set /etc/tempest/tempest.conf identity alt_password $pw
    crudini --set /etc/tempest/tempest.conf identity password $pw
    crudini --set /etc/tempest/tempest.conf compute-feature-enabled change_password False
    crudini --set /etc/tempest/tempest.conf compute-feature-enabled live_migration False
    crudini --set /etc/tempest/tempest.conf compute-feature-enabled vnc_console true
    crudini --set /etc/tempest/tempest.conf compute-feature-enabled resize true
    crudini --set /etc/tempest/tempest.conf compute fixed_network_name fixed
    crudini --set /etc/tempest/tempest.conf compute network_for_ssh ext
    crudini --set /etc/tempest/tempest.conf compute-admin username admin
    crudini --set /etc/tempest/tempest.conf compute-admin tenant_name admin
    crudini --set /etc/tempest/tempest.conf compute-admin password $pw
    crudini --set /etc/tempest/tempest.conf orchestration stack_owner_role _member_
    crudini --set /etc/tempest/tempest.conf network public_network_id $ext_network_id
    crudini --set /etc/tempest/tempest.conf service_available neutron True
    crudini --set /etc/tempest/tempest.conf service_available swift False
    crudini --set /etc/tempest/tempest.conf service_available ceilometer False
    crudini --set /etc/tempest/tempest.conf service_available heat True
    crudini --set /etc/tempest/tempest.conf service_available manila True
    crudini --set /etc/tempest/tempest.conf stress max_instances 1
    crudini --set /etc/tempest/tempest.conf service_available horizon $with_horizon
    crudini --set /etc/tempest/tempest.conf volume-feature-enabled backup false
    crudini --set /etc/tempest/tempest.conf image-feature-enabled deactivate_image true
    # manila share config
    if [ "x$with_manila" = "xyes" ]; then
        crudini --set /etc/tempest/tempest.conf service_available manila True
        crudini --set /etc/tempest/tempest.conf share run_manage_unmanage_snapshot_tests False
        crudini --set /etc/tempest/tempest.conf share run_manage_unmanage_tests False
        crudini --set /etc/tempest/tempest.conf share run_consistency_group_tests False
        crudini --set /etc/tempest/tempest.conf share enable_user_rules_for_protocols cifs
        crudini --set /etc/tempest/tempest.conf share enable_ip_rules_for_protocols nfs
        crudini --set /etc/tempest/tempest.conf share run_shrink_tests False
        crudini --set /etc/tempest/tempest.conf share multitenancy_enabled False
        crudini --set /etc/tempest/tempest.conf share run_replication_tests False
        crudini --set /etc/tempest/tempest.conf share suppress_errors_in_cleanup True
        crudini --set /etc/tempest/tempest.conf share share_creation_retry_number 2
        crudini --set /etc/tempest/tempest.conf share backend_names backend-0
        crudini --set /etc/tempest/tempest.conf share run_migration_tests True
        crudini --set /etc/tempest/tempest.conf share multi_backend False
    else
        crudini --set /etc/tempest/tempest.conf service_available manila False
    fi
fi
