summaryrefslogtreecommitdiff
path: root/install.sh
blob: 8db3fefaccfa19e99c16ce251c4f84c9c28f6cae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#!/bin/bash -e

#Parameters to configure
SERVICE_USERNAME=ec2api
SERVICE_PASSWORD=ec2api
SERVICE_TENANT=service
# this domain name will be used for project and user
SERVICE_DOMAIN_NAME=Default
EC2API_PORT=8788
CONNECTION="mysql://ec2api:ec2api@127.0.0.1/ec2api?charset=utf8"
LOG_DIR=/var/log/ec2api
CONF_DIR=/etc/ec2api
NOVA_CONF=/etc/nova/nova.conf
CONF_FILE=$CONF_DIR/ec2api.conf
APIPASTE_FILE=$CONF_DIR/api-paste.ini

DATA_DIR=${DATA_DIR:-/var/lib/ec2api}
AUTH_CACHE_DIR=${AUTH_CACHE_DIR:-/var/cache/ec2api}

CACHE_BACKEND='oslo_cache.dict'

#Check for environment
if [[ -z "$OS_AUTH_URL" || -z "$OS_USERNAME" || -z "$OS_PASSWORD" ]]; then
    echo "Please set OS_AUTH_URL, OS_USERNAME, OS_PASSWORD"
    exit 1
fi
if [[ -z "$OS_TENANT_NAME" && -z "$OS_PROJECT_NAME" ]]; then
    echo "Please set OS_TENANT_NAME or OS_PROJECT_NAME"
    exit 1
fi


#### utilities functions merged from devstack to check required parameter is not empty
# Prints line number and "message" in error format
# err $LINENO "message"
function err() {
    local exitcode=$?
    errXTRACE=$(set +o | grep xtrace)
    set +o xtrace
    local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
    echo $msg 1>&2;
    $errXTRACE
    return $exitcode
}
# Prints backtrace info
# filename:lineno:function
function backtrace {
    local level=$1
    local deep=$((${#BASH_SOURCE[@]} - 1))
    echo "[Call Trace]"
    while [ $level -le $deep ]; do
        echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
        deep=$((deep - 1))
    done
}


# Prints line number and "message" then exits
# die $LINENO "message"
function die() {
    local exitcode=$?
    set +o xtrace
    local line=$1; shift
    if [ $exitcode == 0 ]; then
        exitcode=1
    fi
    backtrace 2
    err $line "$*"
    exit $exitcode
}


# Checks an environment variable is not set or has length 0 OR if the
# exit code is non-zero and prints "message" and exits
# NOTE: env-var is the variable name without a '$'
# die_if_not_set $LINENO env-var "message"
function die_if_not_set() {
    local exitcode=$?
    FXTRACE=$(set +o | grep xtrace)
    set +o xtrace
    local line=$1; shift
    local evar=$1; shift
    if ! is_set $evar || [ $exitcode != 0 ]; then
        die $line "$*"
    fi
    $FXTRACE
}

# Test if the named environment variable is set and not zero length
# is_set env-var
function is_set() {
    local var=\$"$1"
    eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
}

#######################################

get_data() {
    local match_column=$(($1 + 1))
    local regex="$2"
    local output_column=$(($3 + 1))
    shift 3

    output=$("$@" | \
           awk -F'|' \
               "! /^\+/ && \$${match_column} ~ \"^ *${regex} *\$\" \
                { print \$${output_column} }")

    echo "$output"
}

get_id () {
    get_data 1 id 2 "$@"
}

get_user() {
    local username=$1

    local user_id=$(openstack user show $username -f value -c id 2>/dev/null)

    if [ -n "$user_id" ]; then
        echo "Found existing $username user" >&2
        echo $user_id
    else
        echo "Creating $username user..." >&2
        openstack user create -f value -c id \
                              $username \
                              --password "$SERVICE_PASSWORD" \
                              --project $SERVICE_TENANT \
                              --email $username@example.com
    fi
}

add_role() {
    local user_id=$1
    local tenant=$2
    local role_id=$3
    local username=$4
    local domain=$5

    if [[ -n $domain ]]
    then
        domain_args="--project-domain $domain --user-domain $domain"
    fi

    # Gets user role id
    existing_role=$(openstack role assignment list -f value -c User \
        --role $role_id \
        --user $user_id \
        --project $tenant \
        $domain_args)
    if [ -n "$existing_role" ]
    then
        echo "User $username already has role $role_id" >&2
        return
    fi

    # Adds role to user
    openstack role add $role_id \
                       --user $user_id \
                       --project $tenant \
                       $domain_args
}


# Determines if the given option is present in the INI file
# ini_has_option config-file section option
function ini_has_option() {
    local file=$1
    local section=$2
    local option=$3
    local line
    line=$(sudo sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
    [ -n "$line" ]
}

# Set an option in an INI file
# iniset config-file section option value
function iniset() {
    local file=$1
    local section=$2
    local option=$3
    local value=$4
    if ! sudo grep -q "^\[$section\]" "$file"; then
        # Add section at the end
        sudo bash -c "echo -e \"\n[$section]\" >>\"$file\""
    fi
    if ! ini_has_option "$file" "$section" "$option"; then
        # Add it
        sudo sed -i -e "/^\[$section\]/ a\\
$option = $value
" "$file"
    else
        # Replace it
        sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file"
    fi
}

# Get an option from an INI file
# iniget config-file section option
function iniget() {
    local file=$1
    local section=$2
    local option=$3
    local line
    line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
    echo ${line#*=}
}

# Copy an option from Nova INI file or from environment if it's set
function copynovaopt() {
    local option_name=$1
    local option_group=$2
    local env_var
    local option
    env_var=${option_name^^}
    if [ ${!env_var+x} ]; then
        option=${!env_var}
    elif ini_has_option "$NOVA_CONF" $option_group $option_name; then
        option=$(iniget $NOVA_CONF $option_group $option_name)
    else
        return 0
    fi
    iniset $CONF_FILE $option_group $option_name $option
}

if [[ -n $(openstack catalog show network) ]]; then
    VPC_SUPPORT="True"
    DISABLE_EC2_CLASSIC="True"
else
    VPC_SUPPORT="False"
    DISABLE_EC2_CLASSIC="False"
fi
if [[ "$VPC_SUPPORT" == "True" && -z "$EXTERNAL_NETWORK" ]]; then
    declare -a newtron_output
    readarray -s 3 -t newtron_output < <(openstack network list --external)
    if ((${#newtron_output[@]} < 2)); then
        reason="No external network is declared in Neutron."
    elif ((${#newtron_output[@]} > 2)); then
        reason="More than one external networks are declared in Neutron."
    else
        EXTERNAL_NETWORK=$(echo $newtron_output | awk -F '|' '{ print $3 }')
    fi
    die_if_not_set $LINENO EXTERNAL_NETWORK "$reason. Please set EXTERNAL_NETWORK environment variable to the external network dedicated to EC2 elastic IP operations"
fi

#create keystone user with admin and service privileges
ADMIN_ROLE=$(openstack role show admin -c id -f value)
die_if_not_set $LINENO ADMIN_ROLE "Fail to get ADMIN_ROLE by 'openstack role show' "
SERVICE_ROLE=$(openstack role show service -c id -f value)
die_if_not_set $LINENO ADMIN_ROLE "Fail to get SERVICE_ROLE by 'openstack role show' "
SERVICE_TENANT_ID=$(openstack project show service -c id -f value)
die_if_not_set $LINENO SERVICE_TENANT_ID "Fail to get service tenant 'openstack project show' "

echo ADMIN_ROLE $ADMIN_ROLE
echo SERVICE_ROLE $SERVICE_ROLE
echo SERVICE_TENANT $SERVICE_TENANT

SERVICE_USERID=$(get_user $SERVICE_USERNAME)
die_if_not_set $LINENO SERVICE_USERID "Fail to get user for $SERVICE_USERNAME"
echo SERVICE_USERID $SERVICE_USERID
SERVICE_DOMAIN_NAME=${SERVICE_DOMAIN_NAME:-Default}
add_role $SERVICE_USERID $SERVICE_TENANT $ADMIN_ROLE $SERVICE_USERNAME
add_role $SERVICE_USERID $SERVICE_TENANT $SERVICE_ROLE $SERVICE_USERNAME $SERVICE_DOMAIN_NAME

#create log dir
echo Creating log dir
sudo install -d $LOG_DIR --owner=$USER

#copy conf files (do not override it)
echo Creating configs
sudo mkdir -p /etc/ec2api > /dev/null
if [ ! -s $CONF_FILE ]; then
    sudo touch $CONF_FILE
fi
if [ ! -s $APIPASTE_FILE ]; then
    sudo cp etc/ec2api/api-paste.ini $APIPASTE_FILE
fi


#update default config with some values
iniset $CONF_FILE DEFAULT ec2api_listen_port "$EC2API_PORT"
iniset $CONF_FILE DEFAULT ec2_port "$EC2API_PORT"
iniset $CONF_FILE DEFAULT api_paste_config $APIPASTE_FILE
iniset $CONF_FILE DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
iniset $CONF_FILE DEFAULT log_dir "$LOG_DIR"
iniset $CONF_FILE DEFAULT verbose True
iniset $CONF_FILE DEFAULT keystone_ec2_tokens_url "$OS_AUTH_URL/v3/ec2tokens"
iniset $CONF_FILE database connection "$CONNECTION"
iniset $CONF_FILE DEFAULT disable_ec2_classic "$DISABLE_EC2_CLASSIC"
iniset $CONF_FILE DEFAULT external_network "$EXTERNAL_NETWORK"
iniset $CONF_FILE oslo_concurrency lock_path "$EC2API_STATE_PATH"
iniset $CONF_FILE DEFAULT state_path "$DATA_DIR"

GROUP_AUTHTOKEN="keystone_authtoken"
iniset $CONF_FILE $GROUP_AUTHTOKEN signing_dir "$AUTH_CACHE_DIR"
iniset $CONF_FILE $GROUP_AUTHTOKEN www_authenticate_uri "$OS_AUTH_URL"
iniset $CONF_FILE $GROUP_AUTHTOKEN auth_url "$OS_AUTH_URL"
iniset $CONF_FILE $GROUP_AUTHTOKEN username $SERVICE_USERNAME
iniset $CONF_FILE $GROUP_AUTHTOKEN password $SERVICE_PASSWORD
iniset $CONF_FILE $GROUP_AUTHTOKEN project_name $SERVICE_TENANT
iniset $CONF_FILE $GROUP_AUTHTOKEN project_domain_name $SERVICE_DOMAIN_NAME
iniset $CONF_FILE $GROUP_AUTHTOKEN user_domain_name $SERVICE_DOMAIN_NAME
iniset $CONF_FILE $GROUP_AUTHTOKEN auth_type password

GROUP_CACHE="cache"
iniset $CONF_FILE $GROUP_CACHE enabled True
iniset $CONF_FILE $GROUP_CACHE backend "$CACHE_BACKEND"

if [[ -f "$NOVA_CONF" ]]; then
    # NOTE(ft): use swift instead internal s3 server if enabled
    if [[ -n $(openstack catalog show object-store 2>/dev/null) ]] &&
            [[ -n $(openstack catalog show s3 2>/dev/null) ]]; then
        s3_host="127.0.0.1"
        if ini_has_option "$NOVA_CONF" DEFAULT "s3_host"; then
            s3_host=$(iniget $NOVA_CONF DEFAULT $option_name)
        fi
        s3_port="3334"
        if ini_has_option "$NOVA_CONF" DEFAULT "s3_port"; then
            s3_port=$(iniget $NOVA_CONF DEFAULT $option_name)
        fi
        s3_proto="http"
        if ini_has_option "$NOVA_CONF" DEFAULT "s3_use_ssl"; then
            s3_use_ssl=$(iniget $NOVA_CONF DEFAULT $option_name)
            s3_use_ssl=`echo $s3_use_ssl | awk '{print toupper($0)}'`
            if [[ $s3_use_ssl == "TRUE" ]]; then
                s3_proto="https"
            fi
        fi
        iniset $CONF_FILE DEFAULT s3_url "$s3_proto://$s3_host:$s3_port"

    fi
fi

#init cache dir
echo Creating signing dir
sudo mkdir -p $AUTH_CACHE_DIR
sudo chown $USER $AUTH_CACHE_DIR
sudo rm -f $AUTH_CACHE_DIR/*

#init data dir
echo Creating data dir
sudo mkdir -p $DATA_DIR
sudo chown $USER $DATA_DIR
sudo rm -f $DATA_DIR/*

#install it
echo Installing package
if [[ -z "$VIRTUAL_ENV" ]]; then
  SUDO_PREFIX="sudo"
  if ! command -v pip >/dev/null; then
    sudo apt-get install python-pip
  fi
fi
$SUDO_PREFIX pip install -e ./
$SUDO_PREFIX rm -rf build ec2_api.egg-info

#recreate database
echo Setuping database
$SUDO_PREFIX tools/db/ec2api-db-setup deb