AWS EC2 and VPC API support in standalone service for OpenStack.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

install.sh 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #!/bin/bash -e
  2. #Parameters to configure
  3. SERVICE_USERNAME=ec2api
  4. SERVICE_PASSWORD=ec2api
  5. SERVICE_TENANT=service
  6. # this domain name will be used for project and user
  7. SERVICE_DOMAIN_NAME=Default
  8. EC2API_PORT=8788
  9. CONNECTION="mysql://ec2api:ec2api@127.0.0.1/ec2api?charset=utf8"
  10. LOG_DIR=/var/log/ec2api
  11. CONF_DIR=/etc/ec2api
  12. NOVA_CONF=/etc/nova/nova.conf
  13. CONF_FILE=$CONF_DIR/ec2api.conf
  14. APIPASTE_FILE=$CONF_DIR/api-paste.ini
  15. DATA_DIR=${DATA_DIR:-/var/lib/ec2api}
  16. AUTH_CACHE_DIR=${AUTH_CACHE_DIR:-/var/cache/ec2api}
  17. CACHE_BACKEND='oslo_cache.dict'
  18. #Check for environment
  19. if [[ -z "$OS_AUTH_URL" || -z "$OS_USERNAME" || -z "$OS_PASSWORD" ]]; then
  20. echo "Please set OS_AUTH_URL, OS_USERNAME, OS_PASSWORD"
  21. exit 1
  22. fi
  23. if [[ -z "$OS_TENANT_NAME" && -z "$OS_PROJECT_NAME" ]]; then
  24. echo "Please set OS_TENANT_NAME or OS_PROJECT_NAME"
  25. exit 1
  26. fi
  27. #### utilities functions merged from devstack to check required parameter is not empty
  28. # Prints line number and "message" in error format
  29. # err $LINENO "message"
  30. function err() {
  31. local exitcode=$?
  32. errXTRACE=$(set +o | grep xtrace)
  33. set +o xtrace
  34. local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
  35. echo $msg 1>&2;
  36. $errXTRACE
  37. return $exitcode
  38. }
  39. # Prints backtrace info
  40. # filename:lineno:function
  41. function backtrace {
  42. local level=$1
  43. local deep=$((${#BASH_SOURCE[@]} - 1))
  44. echo "[Call Trace]"
  45. while [ $level -le $deep ]; do
  46. echo "${BASH_SOURCE[$deep]}:${BASH_LINENO[$deep-1]}:${FUNCNAME[$deep-1]}"
  47. deep=$((deep - 1))
  48. done
  49. }
  50. # Prints line number and "message" then exits
  51. # die $LINENO "message"
  52. function die() {
  53. local exitcode=$?
  54. set +o xtrace
  55. local line=$1; shift
  56. if [ $exitcode == 0 ]; then
  57. exitcode=1
  58. fi
  59. backtrace 2
  60. err $line "$*"
  61. exit $exitcode
  62. }
  63. # Checks an environment variable is not set or has length 0 OR if the
  64. # exit code is non-zero and prints "message" and exits
  65. # NOTE: env-var is the variable name without a '$'
  66. # die_if_not_set $LINENO env-var "message"
  67. function die_if_not_set() {
  68. local exitcode=$?
  69. FXTRACE=$(set +o | grep xtrace)
  70. set +o xtrace
  71. local line=$1; shift
  72. local evar=$1; shift
  73. if ! is_set $evar || [ $exitcode != 0 ]; then
  74. die $line "$*"
  75. fi
  76. $FXTRACE
  77. }
  78. # Test if the named environment variable is set and not zero length
  79. # is_set env-var
  80. function is_set() {
  81. local var=\$"$1"
  82. eval "[ -n \"$var\" ]" # For ex.: sh -c "[ -n \"$var\" ]" would be better, but several exercises depends on this
  83. }
  84. #######################################
  85. get_data() {
  86. local match_column=$(($1 + 1))
  87. local regex="$2"
  88. local output_column=$(($3 + 1))
  89. shift 3
  90. output=$("$@" | \
  91. awk -F'|' \
  92. "! /^\+/ && \$${match_column} ~ \"^ *${regex} *\$\" \
  93. { print \$${output_column} }")
  94. echo "$output"
  95. }
  96. get_id () {
  97. get_data 1 id 2 "$@"
  98. }
  99. get_user() {
  100. local username=$1
  101. local user_id=$(openstack user show $username -f value -c id 2>/dev/null)
  102. if [ -n "$user_id" ]; then
  103. echo "Found existing $username user" >&2
  104. echo $user_id
  105. else
  106. echo "Creating $username user..." >&2
  107. openstack user create -f value -c id \
  108. $username \
  109. --password "$SERVICE_PASSWORD" \
  110. --project $SERVICE_TENANT \
  111. --email $username@example.com
  112. fi
  113. }
  114. add_role() {
  115. local user_id=$1
  116. local tenant=$2
  117. local role_id=$3
  118. local username=$4
  119. local domain=$5
  120. if [[ -n $domain ]]
  121. then
  122. domain_args="--project-domain $domain --user-domain $domain"
  123. fi
  124. # Gets user role id
  125. existing_role=$(openstack role assignment list -f value -c User \
  126. --role $role_id \
  127. --user $user_id \
  128. --project $tenant \
  129. $domain_args)
  130. if [ -n "$existing_role" ]
  131. then
  132. echo "User $username already has role $role_id" >&2
  133. return
  134. fi
  135. # Adds role to user
  136. openstack role add $role_id \
  137. --user $user_id \
  138. --project $tenant \
  139. $domain_args
  140. }
  141. # Determines if the given option is present in the INI file
  142. # ini_has_option config-file section option
  143. function ini_has_option() {
  144. local file=$1
  145. local section=$2
  146. local option=$3
  147. local line
  148. line=$(sudo sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
  149. [ -n "$line" ]
  150. }
  151. # Set an option in an INI file
  152. # iniset config-file section option value
  153. function iniset() {
  154. local file=$1
  155. local section=$2
  156. local option=$3
  157. local value=$4
  158. if ! sudo grep -q "^\[$section\]" "$file"; then
  159. # Add section at the end
  160. sudo bash -c "echo -e \"\n[$section]\" >>\"$file\""
  161. fi
  162. if ! ini_has_option "$file" "$section" "$option"; then
  163. # Add it
  164. sudo sed -i -e "/^\[$section\]/ a\\
  165. $option = $value
  166. " "$file"
  167. else
  168. # Replace it
  169. sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file"
  170. fi
  171. }
  172. # Get an option from an INI file
  173. # iniget config-file section option
  174. function iniget() {
  175. local file=$1
  176. local section=$2
  177. local option=$3
  178. local line
  179. line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
  180. echo ${line#*=}
  181. }
  182. # Copy an option from Nova INI file or from environment if it's set
  183. function copynovaopt() {
  184. local option_name=$1
  185. local option_group=$2
  186. local env_var
  187. local option
  188. env_var=${option_name^^}
  189. if [ ${!env_var+x} ]; then
  190. option=${!env_var}
  191. elif ini_has_option "$NOVA_CONF" $option_group $option_name; then
  192. option=$(iniget $NOVA_CONF $option_group $option_name)
  193. else
  194. return 0
  195. fi
  196. iniset $CONF_FILE $option_group $option_name $option
  197. }
  198. if [[ -n $(openstack catalog show network) ]]; then
  199. VPC_SUPPORT="True"
  200. DISABLE_EC2_CLASSIC="True"
  201. else
  202. VPC_SUPPORT="False"
  203. DISABLE_EC2_CLASSIC="False"
  204. fi
  205. if [[ "$VPC_SUPPORT" == "True" && -z "$EXTERNAL_NETWORK" ]]; then
  206. declare -a newtron_output
  207. readarray -s 3 -t newtron_output < <(openstack network list --external)
  208. if ((${#newtron_output[@]} < 2)); then
  209. reason="No external network is declared in Neutron."
  210. elif ((${#newtron_output[@]} > 2)); then
  211. reason="More than one external networks are declared in Neutron."
  212. else
  213. EXTERNAL_NETWORK=$(echo $newtron_output | awk -F '|' '{ print $3 }')
  214. fi
  215. die_if_not_set $LINENO EXTERNAL_NETWORK "$reason. Please set EXTERNAL_NETWORK environment variable to the external network dedicated to EC2 elastic IP operations"
  216. fi
  217. #create keystone user with admin and service privileges
  218. ADMIN_ROLE=$(openstack role show admin -c id -f value)
  219. die_if_not_set $LINENO ADMIN_ROLE "Fail to get ADMIN_ROLE by 'openstack role show' "
  220. SERVICE_ROLE=$(openstack role show service -c id -f value)
  221. die_if_not_set $LINENO ADMIN_ROLE "Fail to get SERVICE_ROLE by 'openstack role show' "
  222. SERVICE_TENANT_ID=$(openstack project show service -c id -f value)
  223. die_if_not_set $LINENO SERVICE_TENANT_ID "Fail to get service tenant 'openstack project show' "
  224. echo ADMIN_ROLE $ADMIN_ROLE
  225. echo SERVICE_ROLE $SERVICE_ROLE
  226. echo SERVICE_TENANT $SERVICE_TENANT
  227. SERVICE_USERID=$(get_user $SERVICE_USERNAME)
  228. die_if_not_set $LINENO SERVICE_USERID "Fail to get user for $SERVICE_USERNAME"
  229. echo SERVICE_USERID $SERVICE_USERID
  230. SERVICE_DOMAIN_NAME=${SERVICE_DOMAIN_NAME:-Default}
  231. add_role $SERVICE_USERID $SERVICE_TENANT $ADMIN_ROLE $SERVICE_USERNAME
  232. add_role $SERVICE_USERID $SERVICE_TENANT $SERVICE_ROLE $SERVICE_USERNAME $SERVICE_DOMAIN_NAME
  233. #create log dir
  234. echo Creating log dir
  235. sudo install -d $LOG_DIR --owner=$USER
  236. #copy conf files (do not override it)
  237. echo Creating configs
  238. sudo mkdir -p /etc/ec2api > /dev/null
  239. if [ ! -s $CONF_FILE ]; then
  240. sudo touch $CONF_FILE
  241. fi
  242. if [ ! -s $APIPASTE_FILE ]; then
  243. sudo cp etc/ec2api/api-paste.ini $APIPASTE_FILE
  244. fi
  245. #update default config with some values
  246. iniset $CONF_FILE DEFAULT ec2api_listen_port "$EC2API_PORT"
  247. iniset $CONF_FILE DEFAULT ec2_port "$EC2API_PORT"
  248. iniset $CONF_FILE DEFAULT api_paste_config $APIPASTE_FILE
  249. 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"
  250. iniset $CONF_FILE DEFAULT log_dir "$LOG_DIR"
  251. iniset $CONF_FILE DEFAULT verbose True
  252. iniset $CONF_FILE DEFAULT keystone_ec2_tokens_url "$OS_AUTH_URL/v3/ec2tokens"
  253. iniset $CONF_FILE database connection "$CONNECTION"
  254. iniset $CONF_FILE DEFAULT disable_ec2_classic "$DISABLE_EC2_CLASSIC"
  255. iniset $CONF_FILE DEFAULT external_network "$EXTERNAL_NETWORK"
  256. iniset $CONF_FILE oslo_concurrency lock_path "$EC2API_STATE_PATH"
  257. iniset $CONF_FILE DEFAULT state_path "$DATA_DIR"
  258. GROUP_AUTHTOKEN="keystone_authtoken"
  259. iniset $CONF_FILE $GROUP_AUTHTOKEN signing_dir "$AUTH_CACHE_DIR"
  260. iniset $CONF_FILE $GROUP_AUTHTOKEN www_authenticate_uri "$OS_AUTH_URL"
  261. iniset $CONF_FILE $GROUP_AUTHTOKEN auth_url "$OS_AUTH_URL"
  262. iniset $CONF_FILE $GROUP_AUTHTOKEN username $SERVICE_USERNAME
  263. iniset $CONF_FILE $GROUP_AUTHTOKEN password $SERVICE_PASSWORD
  264. iniset $CONF_FILE $GROUP_AUTHTOKEN project_name $SERVICE_TENANT
  265. iniset $CONF_FILE $GROUP_AUTHTOKEN project_domain_name $SERVICE_DOMAIN_NAME
  266. iniset $CONF_FILE $GROUP_AUTHTOKEN user_domain_name $SERVICE_DOMAIN_NAME
  267. iniset $CONF_FILE $GROUP_AUTHTOKEN auth_type password
  268. GROUP_CACHE="cache"
  269. iniset $CONF_FILE $GROUP_CACHE enabled True
  270. iniset $CONF_FILE $GROUP_CACHE backend "$CACHE_BACKEND"
  271. if [[ -f "$NOVA_CONF" ]]; then
  272. # NOTE(ft): use swift instead internal s3 server if enabled
  273. if [[ -n $(openstack catalog show object-store 2>/dev/null) ]] &&
  274. [[ -n $(openstack catalog show s3 2>/dev/null) ]]; then
  275. s3_host="127.0.0.1"
  276. if ini_has_option "$NOVA_CONF" DEFAULT "s3_host"; then
  277. s3_host=$(iniget $NOVA_CONF DEFAULT $option_name)
  278. fi
  279. s3_port="3334"
  280. if ini_has_option "$NOVA_CONF" DEFAULT "s3_port"; then
  281. s3_port=$(iniget $NOVA_CONF DEFAULT $option_name)
  282. fi
  283. s3_proto="http"
  284. if ini_has_option "$NOVA_CONF" DEFAULT "s3_use_ssl"; then
  285. s3_use_ssl=$(iniget $NOVA_CONF DEFAULT $option_name)
  286. s3_use_ssl=`echo $s3_use_ssl | awk '{print toupper($0)}'`
  287. if [[ $s3_use_ssl == "TRUE" ]]; then
  288. s3_proto="https"
  289. fi
  290. fi
  291. iniset $CONF_FILE DEFAULT s3_url "$s3_proto://$s3_host:$s3_port"
  292. fi
  293. fi
  294. #init cache dir
  295. echo Creating signing dir
  296. sudo mkdir -p $AUTH_CACHE_DIR
  297. sudo chown $USER $AUTH_CACHE_DIR
  298. sudo rm -f $AUTH_CACHE_DIR/*
  299. #init data dir
  300. echo Creating data dir
  301. sudo mkdir -p $DATA_DIR
  302. sudo chown $USER $DATA_DIR
  303. sudo rm -f $DATA_DIR/*
  304. #install it
  305. echo Installing package
  306. if [[ -z "$VIRTUAL_ENV" ]]; then
  307. SUDO_PREFIX="sudo"
  308. if ! command -v pip >/dev/null; then
  309. sudo apt-get install python-pip
  310. fi
  311. fi
  312. $SUDO_PREFIX pip install -e ./
  313. $SUDO_PREFIX rm -rf build ec2_api.egg-info
  314. #recreate database
  315. echo Setuping database
  316. $SUDO_PREFIX tools/db/ec2api-db-setup deb