Preparing the databases for IBM Cloud Manager with OpenStack

Use the sample shell script to create a script for creating the required databases.

About this task

Complete the following steps to create a script that will create an external database for IBM® Cloud Manager with OpenStack.

Note: The following steps are only intended for a single DB2® instance, not an external DB2 with HADR.

Procedure

  1. Log in to the database server as a root user.
  2. Create a shell script with the following sample script and use create_dbs.sh as the script name. Ensure that the create_dbs.sh script has executable permission.
    #!/bin/bash
    
    SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}")
    SCRIPT_DIR=$(dirname $SCRIPT_PATH)
    DB2_INSTANCE_USER=${DB2_INSTANCE_USER:-db2inst1}
    DB2_INSTANCE_PWD=${DB2_INSTANCE_PWD:-openstack1}
    DB2_INSTANCE_PORT=${DB2_INSTANCE_PORT:-50000}
    
    OS_NOVA_DB_NAME=${OS_NOVA_DB_NAME:-nova}
    OS_NOVA_DB_USER=${OS_NOVA_DB_USER:-nova}
    OS_NOVA_DB_PWD=${OS_NOVA_DB_PWD:-nova}
    
    OS_CINDER_DB_NAME=${OS_CINDER_DB_NAME:-cinder}
    OS_CINDER_DB_USER=${OS_CINDER_DB_USER:-cinder}
    OS_CINDER_DB_PWD=${OS_CINDER_DB_PWD:-cinder}
    
    OS_HEAT_DB_NAME=${OS_HEAT_DB_NAME:-heat}
    OS_HEAT_DB_USER=${OS_HEAT_DB_USER:-heat}
    OS_HEAT_DB_PWD=${OS_HEAT_DB_PWD:-heat}
    
    OS_DASH_DB_NAME=${OS_DASH_DB_NAME:-horizon}
    OS_DASH_DB_USER=${OS_DASH_DB_USER:-horizon}
    OS_DASH_DB_PWD=${OS_DASH_DB_PWD:-horizon}
    
    OS_KEYSTONE_DB_NAME=${OS_KEYSTONE_DB_NAME:-keystone}
    OS_KEYSTONE_DB_USER=${OS_KEYSTONE_DB_USER:-keystone}
    OS_KEYSTONE_DB_PWD=${OS_KEYSTONE_DB_PWD:-keystone}
    
    OS_NEUTRON_DB_NAME=${OS_NEUTRON_DB_NAME:-neutron}
    OS_NEUTRON_DB_USER=${OS_NEUTRON_DB_USER:-neutron}
    OS_NEUTRON_DB_PWD=${OS_NEUTRON_DB_PWD:-neutron}
    
    OS_CEIL_DB_NAME=${OS_CEIL_DB_NAME:-ceilodb2}
    OS_CEIL_DB_USER=${OS_CEIL_DB_USER:-ceil}
    OS_CEIL_DB_PWD=${OS_CEIL_DB_PWD:-ceilometer}
    OS_CEIL_DB_NOSQLPORT=${OS_CEIL_DB_NOSQLPORT:-27017}
    
    OS_GLANCE_DB_NAME=${OS_GLANCE_DB_NAME:-glance}
    OS_GLANCE_DB_USER=${OS_GLANCE_DB_USER:-glance}
    OS_GLANCE_DB_PWD=${OS_GLANCE_DB_PWD:-glance}
    
    OS_IRONIC_DB_NAME=${OS_IRONIC_DB_NAME:-ironic}
    OS_IRONIC_DB_USER=${OS_IRONIC_DB_USER:-ironic}
    OS_IRONIC_DB_PWD=${OS_IRONIC_DB_PWD:-ironic}
    
    CREATE_DBS_LOG="/var/log/create_dbs_`date +%Y-%m-%d_%H-%M-%S`.log"
    # Variables
    declare -i region_idx=0
    db_nodes=""
    db_errors=""
    declare -A regions=()
    declare -i db_count=0
    declare -i db_index=0
    
    # Functions
    
    function update_status()
    {
        if [ $db_count -eq 0 ]; then
            return
        fi
        db_index=$(($db_index+1))
        echo_status
    }
    
    function echo_status()
    {
        echo -ne "\rCreating databases: $db_index/$db_count"
    }
    
    function adjust_user()
    {
        name=$1
        index=${2:-$region_idx}
        suffix=""
        if [ $index -gt 0 ]; then
            suffix="$index"
        fi
        extra=$((${#suffix} + ${#name} - 8))
        if [ $extra -gt 0 ]; then
            echo "${name:0:$((${#name} - $extra))}$suffix"
        else
            echo "$name$suffix"
        fi
    }
    
    function adjust_nosqlport()
    {
        nosqlport=$1
        index=${2:-$region_idx}
        echo $(($nosqlport + $index))
    }
    
    function create_user()
    {
        user=$1
        password=$2
        id -u $user || useradd -d /home/$user $user
        report_if_error "Failed to create user $user" || return $?
        echo -e "$password" | (passwd --stdin $user)
        report_if_error "Failed to change password for user $user"
    }
    
    function enable_nosql()
    {
        db_host=$(hostname -f)
        db_nosqlport=$(adjust_nosqlport ${OS_CEIL_DB_NOSQLPORT})
        db_user=$(adjust_user ${OS_CEIL_DB_USER})
        db_pwd=${OS_CEIL_DB_PWD}
        db_name=${OS_CEIL_DB_NAME}
        usermod -G `id -g $DB2_INSTANCE_USER` $db_user
        db2_dir=`db2ls | awk '{print $1}' | grep ^/`
        jdk_dir_name=`ls $db2_dir/java | grep jdk`
        java_home=$db2_dir/java/$jdk_dir_name
        json_log_path=/home/$DB2_INSTANCE_USER/json/logs
        db_port=$DB2_INSTANCE_PORT
        su - $DB2_INSTANCE_USER -c "mkdir -p $json_log_path"
        su - $DB2_INSTANCE_USER -c "export PATH=$PATH:$java_home/bin; cd $db2_dir/json/bin && ./db2nosql.sh -user $db_user -hostName $db_host -port $db_port -db $db_name -setup enable -password $db_pwd"
        su - $DB2_INSTANCE_USER -c "export JAVA_HOME=$java_home; cd $db2_dir/json/bin; ./wplistener.sh -shutdown -logPath $json_log_path -mongoPort $db_nosqlport -userid $db_user -password $db_pwd -dbName $db_name -noSQLHost $db_host </dev/null &> /dev/null"            
        su - $DB2_INSTANCE_USER -c "export JAVA_HOME=$java_home; cd $db2_dir/json/bin; echo $db_pwd | nohup ./wplistener.sh -start -logPath $json_log_path -mongoPort $db_nosqlport -userid $db_user -dbName $db_name < /dev/null &> /dev/null &" 
    }  
    
    function disable_nosql()
    {
        db_host=$(hostname -f)
        db_nosqlport=$(adjust_nosqlport ${OS_CEIL_DB_NOSQLPORT})
        db_user=$(adjust_user ${OS_CEIL_DB_USER})
        db_pwd=${OS_CEIL_DB_PWD}
        db_name=${OS_CEIL_DB_NAME}
        db2_dir=`db2ls | awk '{print $1}' | grep ^/`
        jdk_dir_name=`ls $db2_dir/java | grep jdk`
        java_home=$db2_dir/java/$jdk_dir_name
        json_log_path=/home/$DB2_INSTANCE_USER/json/logs
        db_port=$DB2_INSTANCE_PORT
        su - $DB2_INSTANCE_USER -c "mkdir -p $json_log_path"
        su - $DB2_INSTANCE_USER -c "export JAVA_HOME=$java_home; cd $db2_dir/json/bin; ./wplistener.sh -shutdown -logPath $json_log_path -mongoPort $db_nosqlport -userid $db_user -password $db_pwd -dbName $db_name -noSQLHost $db_host </dev/null &> /dev/null"
    }
    
    function db_exists()
    {
        db_name=$1
        su - $DB2_INSTANCE_USER -c "db2 LIST DATABASE DIRECTORY" | grep 'Database name' | cut -d= -f2 | tr -d [:blank:] | grep -i "^$db_name$" &> /dev/null
    }
    
    function test_db()
    {
        db_name=$1
        db_user=$(adjust_user $2)
        db_pass=$3
        (echo "set -e"
         echo "db2 CONNECT TO $db_name USER $db_user USING $db_pass"
         echo "db2 CONNECT RESET"
        ) | su - $DB2_INSTANCE_USER &>> $CREATE_DBS_LOG
        report_if_error "Failed to create database $db_name with user $db_user"
    }
    
    function update_db_nodes()
    {
        db_info=$1
        if [ -z "$db_nodes" ]; then
            db_nodes="{ $db_info }"
        else
            db_nodes="${db_nodes}\n{ $db_info }"
        fi
    }
    
    function fetch_db_info()
    {
        db_name=$1
        db_user=$(adjust_user $2)
        db_nosqlport=$3
        address=`hostname -f`
        db_info="Address: $address, Port: $DB2_INSTANCE_PORT, Name: $db_name, User: $db_user, Password: $db_pwd, Fqdn: $address"
        if [ -n "$db_nosqlport" ]; then
            db_info="$db_info, NoSqlPort: $(adjust_nosqlport ${OS_CEIL_DB_NOSQLPORT})"
        fi
        update_db_nodes "$db_info"
    }
    
    function create_db()
    {
        db_name=$1
        db_user=$(adjust_user $2)
        db_pwd=$3
        create_user $db_user $db_pwd  &>> $CREATE_DBS_LOG || return 1
        (
            echo "set -x"
            db_exists $db_name &>> $CREATE_DBS_LOG
            if [ $? != 0 ]; then
                echo db2 CREATE DATABASE $db_name AUTOMATIC STORAGE YES ON /home/$DB2_INSTANCE_USER DBPATH ON /home/$DB2_INSTANCE_USER USING CODESET UTF-8 TERRITORY US PAGESIZE 16384
            fi
            echo db2 CONNECT TO $db_name
            echo db2 GRANT DBADM ON DATABASE TO USER $db_user
            echo db2 CONNECT RESET
        ) | su - $DB2_INSTANCE_USER  &>> $CREATE_DBS_LOG
    }
    
    function create_db_nova()
    {
        create_db $OS_NOVA_DB_NAME $OS_NOVA_DB_USER $OS_NOVA_DB_PWD &&
        test_db $OS_NOVA_DB_NAME $OS_NOVA_DB_USER $OS_NOVA_DB_PWD &&
        fetch_db_info $OS_NOVA_DB_NAME $OS_NOVA_DB_USER
    }
    
    function create_db_cinder()
    {
        create_db $OS_CINDER_DB_NAME $OS_CINDER_DB_USER $OS_CINDER_DB_PWD &&
        test_db $OS_CINDER_DB_NAME $OS_CINDER_DB_USER $OS_CINDER_DB_PWD &&
        fetch_db_info $OS_CINDER_DB_NAME $OS_CINDER_DB_USER
    }
    
    function create_db_heat()
    {
        create_db $OS_HEAT_DB_NAME $OS_HEAT_DB_USER $OS_HEAT_DB_PWD &&
        test_db $OS_HEAT_DB_NAME $OS_HEAT_DB_USER $OS_HEAT_DB_PWD &&
        fetch_db_info $OS_HEAT_DB_NAME $OS_HEAT_DB_USER
    }
    
    function create_db_dash()
    {
        create_db $OS_DASH_DB_NAME $OS_DASH_DB_USER $OS_DASH_DB_PWD
        test_db $OS_DASH_DB_NAME $OS_DASH_DB_USER $OS_DASH_DB_PWD &&
        fetch_db_info $OS_DASH_DB_NAME $OS_DASH_DB_USER
    }
    
    function create_db_keystone()
    {
        create_db $OS_KEYSTONE_DB_NAME $OS_KEYSTONE_DB_USER $OS_KEYSTONE_DB_PWD &&
        test_db $OS_KEYSTONE_DB_NAME $OS_KEYSTONE_DB_USER $OS_KEYSTONE_DB_PWD &&
        fetch_db_info $OS_KEYSTONE_DB_NAME $OS_KEYSTONE_DB_USER
    }
    
    function create_db_neutron()
    {
        create_db $OS_NEUTRON_DB_NAME $OS_NEUTRON_DB_USER $OS_NEUTRON_DB_PWD &&
        test_db $OS_NEUTRON_DB_NAME $OS_NEUTRON_DB_USER $OS_NEUTRON_DB_PWD &&
        fetch_db_info $OS_NEUTRON_DB_NAME $OS_NEUTRON_DB_USER
    }
    
    function create_db_glance()
    {
        create_db $OS_GLANCE_DB_NAME $OS_GLANCE_DB_USER $OS_GLANCE_DB_PWD &&
        test_db $OS_GLANCE_DB_NAME $OS_GLANCE_DB_USER $OS_GLANCE_DB_PWD &&
        fetch_db_info $OS_GLANCE_DB_NAME $OS_GLANCE_DB_USER
    }
    
    function create_db_ceil()
    {
        create_db $OS_CEIL_DB_NAME $OS_CEIL_DB_USER $OS_CEIL_DB_PWD &&
        enable_nosql &>> $CREATE_DBS_LOG &&
        test_db $OS_CEIL_DB_NAME $OS_CEIL_DB_USER $OS_CEIL_DB_PWD &&
        fetch_db_info $OS_CEIL_DB_NAME $OS_CEIL_DB_USER $OS_CEIL_DB_NOSQLPORT
    }
    
    function create_db_ironic()
    {
        create_db $OS_IRONIC_DB_NAME $OS_IRONIC_DB_USER $OS_IRONIC_DB_PWD &&
        test_db $OS_IRONIC_DB_NAME $OS_IRONIC_DB_USER $OS_IRONIC_DB_PWD &&
        fetch_db_info $OS_IRONIC_DB_NAME $OS_IRONIC_DB_USER
    }
    
    function list_lines()
    {
        declare -i count=1
        while read line; do
            test -z "$line" && continue
            echo -e "\t${count}. $line";
            count=count+1;
        done
    }
    
    function report_if_error()
    {
        rt_code=$?
        if [ $rt_code -ne 0 ]; then
            db_error="$@\n"
            db_errors="${db_errors}${db_error}"
        fi
        return $rt_code
    }
    
    function show_db_nodes()
    {
        echo
        region_count=${#regions[@]}
        if [ ${region_count} -ne 0 ]; then
            for idx in ${!regions[@]}; do
                if [ $idx -eq 0 -a ${region_count} -eq 1 ]; then
                    echo -e "Region:"
                else
                    echo -e "Region $idx:"
                fi
                echo -e ${regions[$idx]} | list_lines
            done
        fi
    }
    
    function show_db_errors()
    {
        echo -e "\nError messages:"
        echo -e $db_errors | list_lines
    }
    
    function creating_begin()
    {
        db_nodes=""
        db_errors=""
        db_count=$1
        db_index=0
        echo_status
    }
    
    function creating_end()
    {
        if [ -z "$db_errors" ]; then
            show_db_nodes
        else
            show_db_errors
        fi
    }
    function create_single_region()
    {
        creating_begin 9
        create_region
        regions[0]=$db_nodes
        db_nodes=""
        creating_end
    }
    
    function create_multiple_region()
    {
        eval $1
        region=( ${region//,/ } )
        db_count=$((${#region[@]}*9))
        creating_begin $db_count
        for idx in ${region[*]}; do
            region_idx=$idx
            create_region
            regions[$region_idx]=$db_nodes
            db_nodes=""
        done
        creating_end
    }
    
    function create_region()
    {
        for n in nova cinder heat dash keystone neutron glance ceil ironic; do
            create_db_$n || break
            update_status
        done
    }
    
    [ "$0" != "${BASH_SOURCE[0]}" ] && return
    
    function show_help()
    {
        echo -e "Usage:"
        echo -e "\t./create_dbs.sh region\t- create databases for single region server"
        echo -e "\t./create_dbs.sh region=1,2,3,...\t- create databases for multiple region servers"
        echo -e ""
        echo -e "Notice:"
        echo -e "\tBefore creating database, please set environment variables correctly:"
        echo -e ""
        echo -e "Examples:"
        echo -e "\tCreate databases for one region server on this machine:"
        echo -e "\t./create_dbs.sh region"
        echo -e ""
        echo -e "\tCreate databases for multiple region servers on this machine:"
        echo -e "\t./create_dbs.sh region=1,2,3"
    }
    
    # main
    > $CREATE_DBS_LOG
    case "$1" in
         region)
             create_single_region
             ;;
         region=*)
             create_multiple_region "$1"
             ;;
         *)
             show_help
             ;;
    esac
  3. Modify the following environment variables before you run the create_dbs.sh script. The script uses the default environment variables to create the database, user, and schema against the specific IBM DB2 instance on the database server. The default values of the configuration are defined in the create_dbs.sh script, and can be overridden by exporting the system environment variables before you run the script.
    Note: The script assumes that the database, user, and schema do not exist before you run the script. You must check the IBM DB2 server to make sure that there is no conflict.
    Table 1.
    Environment variable Description Default value
    DB2_INSTANCE_USER Your IBM DB2 instance user name db2inst1
    DB2_INSTANCE_PWD Your IBM DB2 instance password openstack1
    DB2_INSTANCE_PORT Your IBM DB2 instance port 50000
    OS_NOVA_DB_NAME OpenStack Nova database name nova
    OS_NOVA_DB_USER OpenStack Nova database user nova
    OS_NOVA_DB_PWD OpenStack Nova database password nova
    OS_CINDER_DB_NAME OpenStack Cinder database name cinder
    OS_CINDER_DB_NAME OpenStack Cinder database name cinder
    OS_CINDER_DB_USER OpenStack Cinder database user cinder
    OS_CINDER_DB_PWD OpenStack Cinder database password cinder
    OS_HEAT_DB_NAME OpenStack Heat database name heat
    OS_HEAT_DB_USER OpenStack Heat database user heat
    OS_HEAT_DB_PWD OpenStack Heat database password heat
    OS_DASH_DB_NAME OpenStack Dashboard database name horizon
    OS_DASH_DB_USER OpenStack Dashboard database user horizon
    OS_DASH_DB_PWD OpenStack Dashboard database password horizon
    OS_KEYSTONE_DB_NAME OpenStack Keystone database name keystone
    OS_KEYSTONE_DB_USER OpenStack Keystone database user keystone
    OS_KEYSTONE_DB_PWD OpenStack Keystone database password keystone
    OS_NEUTRON_DB_NAME OpenStack Neutron database name neutron
    OS_NEUTRON_DB_USER OpenStack Neutron database user neutron
    OS_NEUTRON_DB_PWD OpenStack Neutron database password neutron
    OS_CEIL_DB_NAME OpenStack Ceilometer database name ceilodb2
    OS_CEIL_DB_USER OpenStack Ceilometer database user ceil
    OS_CEIL_DB_PWD OpenStack Ceilometer database password ceilometer
    OS_CEIL_DB_NOSQLPORT Mongo database port 27017
    OS_GLANCE_DB_NAME OpenStack Glance database name glance
    OS_GLANCE_DB_USER OpenStack Glance database user glance
    OS_GLANCE_DB_PWD OpenStack Glance database password glance
    Notes:
    • The database name length must be no more than 8 characters, for example, OPENSTAC and not OPENSTACK.
    • Database user names must be unique, and must be no more than 8 characters.
    • Set the firewall correctly to allow DB2 communication. The default port numbers are 50000 and 27017.
  4. Run one of the following commands to create the required databases:
    Table 2.
    Command Description
    ./create_dbs.sh region Creates the database for a single region server only.
    ./create_dbs.sh region=1,2,3 Creates the databases for three region servers.
    ./create_dbs.sh region=3 Adds a database for a third region server.
    Notes:
    • Ensure that your DB2 instance is started before running this script
    • If you create a database for multiple regions, the script uses the same database with a different user and schema in the database server. For example, the create_dbs.sh region command creates the nova user in the system and database. The create_dbs.sh region=1,2,3 command creates the nova1, nova2, and nova3 users in the system and database for each region.
    The following example shows the output of the create_dbs.sh region=4 command:
    [root@db2_server]# ./create_dbs_icm.sh region=4
    Creating databases: 9/9
    Region 4:
            1. { Address: external_db2.ibm.com, Port: 50000, Name: nova, User: nova4, Password: nova, Fqdn: external_db2.ibm.com }
            2. { Address: external_db2.ibm.com, Port: 50000, Name: cinder, User: cinder4, Password: cinder, Fqdn: external_db2.ibm.com }
            3. { Address: external_db2.ibm.com, Port: 50000, Name: heat, User: heat4, Password: heat, Fqdn: external_db2.ibm.com }
            4. { Address: external_db2.ibm.com, Port: 50000, Name: horizon, User: horizon4, Password: horizon, Fqdn: external_db2.ibm.com }
            5. { Address: external_db2.ibm.com, Port: 50000, Name: keystone, User: keyston4, Password: keystone, Fqdn: external_db2.ibm.com }
            6. { Address: external_db2.ibm.com, Port: 50000, Name: neutron, User: neutron4, Password: neutron, Fqdn: external_db2.ibm.com }
            7. { Address: external_db2.ibm.com, Port: 50000, Name: glance, User: glance4, Password: glance, Fqdn: external_db2.ibm.com }
            8. { Address: external_db2.ibm.com, Port: 50000, Name: ceilodb2, User: ceil4, Password: ceilometer, Fqdn: external_db2.ibm.com, NoSqlPort: 27017 }
            9. { Address: external_db2.ibm.com, Port: 50000, Name: ironic, User: ironic4, Password: ironic, Fqdn: external_db2.ibm.com }
  5. If not already enabled, enable server encryption by completing the following stes.
    Note: Enabling server encryption involves restarting the database server. The external database server might have databases that are used by other services, in addition to those that are used by IBM Cloud Manager with OpenStack. Before you restart the database server, coordinate with all interested parties to schedule the appropriate downtime.
    1. Run the following commands as the database instance owner:
      db2 update dbm cfg using authentication server_encrypt
      db2stop force
      db2start
      Note: If the database cannot be stopped, stop the applications that are locking the related database.
    2. After restarting the database, you must restart NoSQL. Log in as DB2 instance user (for example, db2inst1) by running the su - db2inst1 command. Then, create the logs directory and prepare the wplistener.properties file by running the following commands:
      mkdir -p ~/json/logs
              cat > ~/json/wplistener.properties
              # Adjust below variables according your environment
              # database name used by ceilometer 
              dbName=CEILODB2
              # mongo port used by ceilometer
              mongoPort=27017
              # Ceilometer database userid
              userid=ceilodb2
              # Ceilometer database password
              password=ceilodb2
              # Name of the Host running the noSQL process
              noSQLHost=localhost
              # Type Ctrl + D below to close the stream
               3. Restart NoSQL by running the following commands: 
              export JAVA_HOME=~/sqllib/java/jdk64
              cd ~/sqllib/json/bin
              # stop noSQL
              ./wplistener.sh -logPath ~/json/logs -propsFile ~/json/wplistener.properties -shutdown
              # start noSQL. Make sure the according database has been started
              nohup ./wplistener.sh -logPath ~/json/logs -propsFile ~/json/wplistener.properties \
              -start &> ~/json/logs/start.out &
    3. Each database owner who shares the database instance should validate the encryption to ensure the continued operation of their applications.