Skip to content

Commit 428af5a

Browse files
committed
Add PostgreSQL support to devstack
This patch adds an interface for supporting multiple database backend types and implemnts support for PostgreSQL. It also adds a function, use_exclusive_service, which serves as a base for enabling a service that conflicts with other services. The use_database function uses it, and it might also be useful for selecting messaging backends. MySQL is still selected by default. Tested on Fedora 17 and Ubuntu 12.04 with MySQL and PostgreSQL. Implements blueprint postgresql-support Change-Id: I4b1373e25676fd9a9809fe70cb4a6450a2479174
1 parent 98b26ab commit 428af5a

File tree

14 files changed

+355
-112
lines changed

14 files changed

+355
-112
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ If the EC2 API is your cup-o-tea, you can create credentials and use euca2ools:
5757

5858
You can override environment variables used in `stack.sh` by creating file name `localrc`. It is likely that you will need to do this to tweak your networking configuration should you need to access your cloud from a different host.
5959

60+
# Database Backend
61+
62+
Multiple database backends are available. The available databases are defined in the lib/databases directory.
63+
To choose a database backend, add a line to your `localrc` like:
64+
65+
use_database postgresql
66+
67+
By default, the mysql database backend is used.
68+
6069
# RPC Backend
6170

6271
Multiple RPC backends are available. Currently, this

files/apts/postgresql

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python-psycopg2

files/rpms/postgresql

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python-psycopg2

functions

+15
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,21 @@ function upload_image() {
836836
fi
837837
}
838838

839+
# Toggle enable/disable_service for services that must run exclusive of each other
840+
# $1 The name of a variable containing a space-separated list of services
841+
# $2 The name of a variable in which to store the enabled service's name
842+
# $3 The name of the service to enable
843+
function use_exclusive_service {
844+
local options=${!1}
845+
local selection=$3
846+
out=$2
847+
[ -z $selection ] || [[ ! "$options" =~ "$selection" ]] && return 1
848+
for opt in $options;do
849+
[[ "$opt" = "$selection" ]] && enable_service $opt || disable_service $opt
850+
done
851+
eval "$out=$selection"
852+
return 0
853+
}
839854

840855
# Wrapper for ``yum`` to set proxy environment variables
841856
# Uses globals ``OFFLINE``, ``*_proxy`

lib/cinder

+5-4
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ function configure_cinder() {
112112
iniset $CINDER_CONF DEFAULT volume_group $VOLUME_GROUP
113113
iniset $CINDER_CONF DEFAULT volume_name_template ${VOLUME_NAME_PREFIX}%s
114114
iniset $CINDER_CONF DEFAULT iscsi_helper tgtadm
115-
iniset $CINDER_CONF DEFAULT sql_connection $BASE_SQL_CONN/cinder?charset=utf8
115+
local dburl
116+
database_connection_url dburl cinder
117+
iniset $CINDER_CONF DEFAULT sql_connection $dburl
116118
iniset $CINDER_CONF DEFAULT api_paste_config $CINDER_API_PASTE_INI
117119
iniset $CINDER_CONF DEFAULT root_helper "sudo ${CINDER_ROOTWRAP}"
118120
iniset $CINDER_CONF DEFAULT osapi_volume_extension cinder.api.openstack.volume.contrib.standard_extensions
@@ -141,10 +143,9 @@ function init_cinder() {
141143
# Force nova volumes off
142144
NOVA_ENABLED_APIS=$(echo $NOVA_ENABLED_APIS | sed "s/osapi_volume,//")
143145

144-
if is_service_enabled mysql; then
146+
if is_service_enabled $DATABASE_BACKENDS; then
145147
# (re)create cinder database
146-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS cinder;'
147-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE cinder;'
148+
recreate_database cinder utf8
148149

149150
# (re)create cinder database
150151
$CINDER_BIN_DIR/cinder-manage db sync

lib/database

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# lib/database
2+
# Interface for interacting with different database backends
3+
4+
# Dependencies:
5+
# DATABASE_BACKENDS variable must contain a list of available database backends
6+
# DATABASE_TYPE variable must be set
7+
8+
# Each database must implement four functions:
9+
# recreate_database_$DATABASE_TYPE
10+
# install_database_$DATABASE_TYPE
11+
# configure_database_$DATABASE_TYPE
12+
# database_connection_url_$DATABASE_TYPE
13+
#
14+
# and call register_database $DATABASE_TYPE
15+
16+
# Save trace setting
17+
XTRACE=$(set +o | grep xtrace)
18+
set +o xtrace
19+
20+
# Register a database backend
21+
# $1 The name of the database backend
22+
function register_database {
23+
[ -z "$DATABASE_BACKENDS" ] && DATABASE_BACKENDS=$1 || DATABASE_BACKENDS+=" $1"
24+
}
25+
26+
for f in $TOP_DIR/lib/databases/*; do source $f; done
27+
28+
# Set the database type based on the configuration
29+
function initialize_database_backends {
30+
for backend in $DATABASE_BACKENDS; do
31+
is_service_enabled $backend && DATABASE_TYPE=$backend
32+
done
33+
34+
[ -z "$DATABASE_TYPE" ] && return 1
35+
36+
# For backward-compatibility, read in the MYSQL_HOST/USER variables and use
37+
# them as the default values for the DATABASE_HOST/USER variables.
38+
MYSQL_HOST=${MYSQL_HOST:-localhost}
39+
MYSQL_USER=${MYSQL_USER:-root}
40+
41+
DATABASE_HOST=${DATABASE_HOST:-${MYSQL_HOST}}
42+
DATABASE_USER=${DATABASE_USER:-${MYSQL_USER}}
43+
44+
if [ -n "$MYSQL_PASSWORD" ]; then
45+
DATABASE_PASSWORD=$MYSQL_PASSWORD
46+
else
47+
read_password DATABASE_PASSWORD "ENTER A PASSWORD TO USE FOR THE DATABASE."
48+
fi
49+
50+
# We configure Nova, Horizon, Glance and Keystone to use MySQL as their
51+
# database server. While they share a single server, each has their own
52+
# database and tables.
53+
54+
# By default this script will install and configure MySQL. If you want to
55+
# use an existing server, you can pass in the user/password/host parameters.
56+
# You will need to send the same ``DATABASE_PASSWORD`` to every host if you are doing
57+
# a multi-node DevStack installation.
58+
59+
# NOTE: Don't specify ``/db`` in this string so we can use it for multiple services
60+
BASE_SQL_CONN=${BASE_SQL_CONN:-${DATABASE_TYPE}://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOST}
61+
62+
return 0
63+
}
64+
65+
# Set the database backend to use
66+
# $1 The name of the database backend to use (mysql, postgresql, ...)
67+
function use_database {
68+
use_exclusive_service DATABASE_BACKENDS DATABASE_TYPE $1 && return 0
69+
ret=$?
70+
echo "Invalid database '$1'"
71+
return $ret
72+
}
73+
74+
# Recreate a given database
75+
# $1 The name of the database
76+
# $2 The character set/encoding of the database
77+
function recreate_database {
78+
local db=$1
79+
local charset=$2
80+
recreate_database_$DATABASE_TYPE $db $charset
81+
}
82+
83+
# Install the database
84+
function install_database {
85+
install_database_$DATABASE_TYPE
86+
}
87+
88+
# Configure and start the database
89+
function configure_database {
90+
configure_database_$DATABASE_TYPE
91+
}
92+
93+
# Generate an SQLAlchemy connection URL and store it in a variable
94+
# $1 The variable name in which to store the connection URL
95+
# $2 The name of the database
96+
function database_connection_url {
97+
local var=$1
98+
local db=$2
99+
database_connection_url_$DATABASE_TYPE $var $db
100+
}
101+
102+
# Restore xtrace
103+
$XTRACE

lib/databases/mysql

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# lib/mysql
2+
# Functions to control the configuration and operation of the MySQL database backend
3+
4+
# Dependencies:
5+
# DATABASE_{HOST,USER,PASSWORD} must be defined
6+
7+
# Save trace setting
8+
XTRACE=$(set +o | grep xtrace)
9+
set +o xtrace
10+
11+
register_database mysql
12+
13+
function recreate_database_mysql {
14+
local db=$1
15+
local charset=$2
16+
mysql -u$DATABASE_USER -p$DATABASE_PASSWORD -e "DROP DATABASE IF EXISTS $db;"
17+
mysql -u$DATABASE_USER -p$DATABASE_PASSWORD -e "CREATE DATABASE $db CHARACTER SET $charset;"
18+
}
19+
20+
function configure_database_mysql {
21+
echo_summary "Configuring and starting MySQL"
22+
23+
if [[ "$os_PACKAGE" = "deb" ]]; then
24+
MY_CONF=/etc/mysql/my.cnf
25+
MYSQL=mysql
26+
else
27+
MY_CONF=/etc/my.cnf
28+
MYSQL=mysqld
29+
fi
30+
31+
# Start mysql-server
32+
if [[ "$os_PACKAGE" = "rpm" ]]; then
33+
# RPM doesn't start the service
34+
start_service $MYSQL
35+
# Set the root password - only works the first time
36+
sudo mysqladmin -u root password $DATABASE_PASSWORD || true
37+
fi
38+
# Update the DB to give user ‘$DATABASE_USER’@’%’ full control of the all databases:
39+
sudo mysql -uroot -p$DATABASE_PASSWORD -h127.0.0.1 -e "GRANT ALL PRIVILEGES ON *.* TO '$DATABASE_USER'@'%' identified by '$DATABASE_PASSWORD';"
40+
41+
# Now update ``my.cnf`` for some local needs and restart the mysql service
42+
43+
# Change ‘bind-address’ from localhost (127.0.0.1) to any (0.0.0.0)
44+
sudo sed -i '/^bind-address/s/127.0.0.1/0.0.0.0/g' $MY_CONF
45+
46+
# Set default db type to InnoDB
47+
if sudo grep -q "default-storage-engine" $MY_CONF; then
48+
# Change it
49+
sudo bash -c "source $TOP_DIR/functions; iniset $MY_CONF mysqld default-storage-engine InnoDB"
50+
else
51+
# Add it
52+
sudo sed -i -e "/^\[mysqld\]/ a \
53+
default-storage-engine = InnoDB" $MY_CONF
54+
fi
55+
56+
restart_service $MYSQL
57+
}
58+
59+
function install_database_mysql {
60+
if [[ "$os_PACKAGE" = "deb" ]]; then
61+
# Seed configuration with mysql password so that apt-get install doesn't
62+
# prompt us for a password upon install.
63+
cat <<MYSQL_PRESEED | sudo debconf-set-selections
64+
mysql-server-5.1 mysql-server/root_password password $DATABASE_PASSWORD
65+
mysql-server-5.1 mysql-server/root_password_again password $DATABASE_PASSWORD
66+
mysql-server-5.1 mysql-server/start_on_boot boolean true
67+
MYSQL_PRESEED
68+
fi
69+
70+
# while ``.my.cnf`` is not needed for OpenStack to function, it is useful
71+
# as it allows you to access the mysql databases via ``mysql nova`` instead
72+
# of having to specify the username/password each time.
73+
if [[ ! -e $HOME/.my.cnf ]]; then
74+
cat <<EOF >$HOME/.my.cnf
75+
[client]
76+
user=$DATABASE_USER
77+
password=$DATABASE_PASSWORD
78+
host=$DATABASE_HOST
79+
EOF
80+
chmod 0600 $HOME/.my.cnf
81+
fi
82+
# Install mysql-server
83+
install_package mysql-server
84+
}
85+
86+
function database_connection_url_mysql {
87+
local output=$1
88+
local db=$2
89+
eval "$output=$BASE_SQL_CONN/$db?charset=utf8"
90+
}
91+
92+
# Restore xtrace
93+
$XTRACE

lib/databases/postgresql

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# lib/postgresql
2+
# Functions to control the configuration and operation of the PostgreSQL database backend
3+
4+
# Dependencies:
5+
# DATABASE_{HOST,USER,PASSWORD} must be defined
6+
7+
# Save trace setting
8+
XTRACE=$(set +o | grep xtrace)
9+
set +o xtrace
10+
11+
register_database postgresql
12+
13+
function recreate_database_postgresql {
14+
local db=$1
15+
local charset=$2
16+
# Avoid unsightly error when calling dropdb when the database doesn't exist
17+
psql -h$DATABASE_HOST -U$DATABASE_USER -dtemplate1 -c "DROP DATABASE IF EXISTS $db"
18+
createdb -h $DATABASE_HOST -U$DATABASE_USER -l C -T template0 -E $charset $db
19+
}
20+
21+
function configure_database_postgresql {
22+
echo_summary "Configuring and starting PostgreSQL"
23+
if [[ "$os_PACKAGE" = "rpm" ]]; then
24+
PG_HBA=/var/lib/pgsql/data/pg_hba.conf
25+
PG_CONF=/var/lib/pgsql/data/postgresql.conf
26+
else
27+
PG_DIR=`find /etc/postgresql -name pg_hba.conf|xargs dirname`
28+
PG_HBA=$PG_DIR/pg_hba.conf
29+
PG_CONF=$PG_DIR/postgresql.conf
30+
fi
31+
sudo [ -e /var/lib/pgsql/data ] || sudo postgresql-setup initdb
32+
# Listen on all addresses
33+
sudo sed -i "/listen_addresses/s/.*/listen_addresses = '*'/" $PG_CONF
34+
# Do password auth from all IPv4 clients
35+
sudo sed -i "/^host/s/all\s\+127.0.0.1\/32\s\+ident/$DATABASE_USER\t0.0.0.0\/0\tpassword/" $PG_HBA
36+
# Do password auth for all IPv6 clients
37+
sudo sed -i "/^host/s/all\s\+::1\/128\s\+ident/$DATABASE_USER\t::0\/0\tpassword/" $PG_HBA
38+
start_service postgresql
39+
40+
# If creating the role fails, chances are it already existed. Try to alter it.
41+
sudo -u postgres -i psql -c "CREATE ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'" || \
42+
sudo -u postgres -i psql -c "ALTER ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'"
43+
}
44+
45+
function install_database_postgresql {
46+
echo_summary "Installing postgresql"
47+
PGPASS=$HOME/.pgpass
48+
if [[ ! -e $PGPASS ]]; then
49+
cat <<EOF > $PGPASS
50+
*:*:*:$DATABASE_USER:$DATABASE_PASSWORD
51+
EOF
52+
chmod 0600 $PGPASS
53+
else
54+
sed -i "s/:root:\w\+/:root:$DATABASE_PASSWORD/" $PGPASS
55+
fi
56+
if [[ "$os_PACKAGE" = "rpm" ]]; then
57+
install_package postgresql-server
58+
else
59+
install_package postgresql
60+
fi
61+
}
62+
63+
function database_connection_url_postgresql {
64+
local output=$1
65+
local db=$2
66+
eval "$output=$BASE_SQL_CONN/$db?client_encoding=utf8"
67+
}
68+
69+
# Restore xtrace
70+
$XTRACE

lib/glance

+5-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ function configure_glance() {
8181
cp $GLANCE_DIR/etc/glance-registry.conf $GLANCE_REGISTRY_CONF
8282
iniset $GLANCE_REGISTRY_CONF DEFAULT debug True
8383
inicomment $GLANCE_REGISTRY_CONF DEFAULT log_file
84-
iniset $GLANCE_REGISTRY_CONF DEFAULT sql_connection $BASE_SQL_CONN/glance?charset=utf8
84+
local dburl
85+
database_connection_url dburl glance
86+
iniset $GLANCE_REGISTRY_CONF DEFAULT sql_connection $dburl
8587
iniset $GLANCE_REGISTRY_CONF DEFAULT use_syslog $SYSLOG
8688
iniset $GLANCE_REGISTRY_CONF paste_deploy flavor keystone
8789
iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
@@ -95,7 +97,7 @@ function configure_glance() {
9597
cp $GLANCE_DIR/etc/glance-api.conf $GLANCE_API_CONF
9698
iniset $GLANCE_API_CONF DEFAULT debug True
9799
inicomment $GLANCE_API_CONF DEFAULT log_file
98-
iniset $GLANCE_API_CONF DEFAULT sql_connection $BASE_SQL_CONN/glance?charset=utf8
100+
iniset $GLANCE_API_CONF DEFAULT sql_connection $dburl
99101
iniset $GLANCE_API_CONF DEFAULT use_syslog $SYSLOG
100102
iniset $GLANCE_API_CONF DEFAULT filesystem_store_datadir $GLANCE_IMAGE_DIR/
101103
iniset $GLANCE_API_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
@@ -149,8 +151,7 @@ function init_glance() {
149151
mkdir -p $GLANCE_CACHE_DIR
150152

151153
# (re)create glance database
152-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS glance;'
153-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE glance CHARACTER SET utf8;'
154+
recreate_database glance utf8
154155

155156
$GLANCE_BIN_DIR/glance-manage db_sync
156157
}

lib/heat

+4-3
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ function configure_heat() {
120120
iniset $HEAT_ENGINE_CONF DEFAULT use_syslog $SYSLOG
121121
iniset $HEAT_ENGINE_CONF DEFAULT bind_host $HEAT_ENGINE_HOST
122122
iniset $HEAT_ENGINE_CONF DEFAULT bind_port $HEAT_ENGINE_PORT
123-
iniset $HEAT_ENGINE_CONF DEFAULT sql_connection $BASE_SQL_CONN/heat?charset=utf8
123+
local dburl
124+
database_connection_url dburl heat
125+
iniset $HEAT_ENGINE_CONF DEFAULT sql_connection $dburl
124126
iniset $HEAT_ENGINE_CONF DEFAULT auth_encryption_key `hexdump -n 16 -v -e '/1 "%02x"' /dev/random`
125127

126128
if is_service_enabled rabbit; then
@@ -185,8 +187,7 @@ function configure_heat() {
185187
function init_heat() {
186188

187189
# (re)create heat database
188-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS heat;'
189-
mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE heat CHARACTER SET utf8;'
190+
recreate_database heat utf8
190191

191192
$HEAT_DIR/bin/heat-db-setup $os_PACKAGE -r $MYSQL_PASSWORD
192193
$HEAT_DIR/tools/nova_create_flavors.sh

0 commit comments

Comments
 (0)