~gandelman-a/charms/precise/nova-cloud-controller/vmw

« back to all changes in this revision

Viewing changes to hooks/lib/openstack-common

  • Committer: James Page
  • Date: 2013-06-03 16:47:15 UTC
  • mfrom: (48.1.26 nova-cloud-controller)
  • Revision ID: james.page@canonical.com-20130603164715-pxj02ata0swcz51a
* Updated for Grizzly.

* Highly-available API services via the hacluster subordinate.

* SSH Key management for compute nodes, to facilitate live migration.

* Various bug fixes and cleanup.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
function service_ctl {
22
22
  # control a specific service, or all (as defined by $SERVICES)
 
23
  # service restarts will only occur depending on global $CONFIG_CHANGED,
 
24
  # which should be updated in charm's set_or_update().
 
25
  local config_changed=${CONFIG_CHANGED:-True}
23
26
  if [[ $1 == "all" ]] ; then
24
27
    ctl="$SERVICES"
25
28
  else
37
40
      "stop")
38
41
        service_ctl_status $i && service $i stop || return 0 ;;
39
42
      "restart")
40
 
        service_ctl_status $i && service $i restart || service $i start ;;
 
43
        if [[ "$config_changed" == "True" ]] ; then
 
44
          service_ctl_status $i && service $i restart || service $i start
 
45
        fi
 
46
        ;;
41
47
    esac
42
48
    if [[ $? != 0 ]] ; then
43
49
      juju-log "$CHARM: service_ctl ERROR - Service $i failed to $action"
44
50
    fi
45
51
  done
 
52
  # all configs should have been reloaded on restart of all services, reset
 
53
  # flag if its being used.
 
54
  if [[ "$action" == "restart" ]] && [[ -n "$CONFIG_CHANGED" ]] &&
 
55
     [[ "$ctl" == "all" ]]; then
 
56
    CONFIG_CHANGED="False"
 
57
  fi
46
58
}
47
59
 
48
60
function configure_install_source {
70
82
      # gpg key id tagged to end of url folloed by a |
71
83
      url=$(echo $src | cut -d'|' -f1)
72
84
      key=$(echo $src | cut -d'|' -f2)
73
 
      if [[ -n "$key" ]] ; then
74
 
        juju-log "$CHARM: Importing repository key: $key"
75
 
        apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$key" || \
76
 
          juju-log "$CHARM WARN: Could not import key from keyserver: $key"
77
 
      else
78
 
        juju-log "$CHARM No repository key specified"
79
 
        url="$src"
80
 
      fi
81
 
      echo $url > /etc/apt/sources.list.d/juju_deb.list
 
85
      juju-log "$CHARM: Importing repository key: $key"
 
86
      apt-key adv --keyserver keyserver.ubuntu.com --recv-keys "$key" || \
 
87
        juju-log "$CHARM WARN: Could not import key from keyserver: $key"
 
88
    else
 
89
      juju-log "$CHARM No repository key specified."
 
90
      url="$src"
82
91
    fi
 
92
    echo "$url" > /etc/apt/sources.list.d/juju_deb.list
83
93
    return 0
84
94
  fi
85
95
 
86
96
  # Cloud Archive
87
97
  if [[ "${src:0:6}" == "cloud:" ]] ; then
88
 
    local archive_key="5EDB1B62EC4926EA"
89
 
    local rel=$(echo $src | cut -d: -f2)
90
 
    local u_rel=$(echo $rel | cut -d- -f1)
91
 
    local ca_rel=$(echo $rel | cut -d- -f2)
 
98
 
 
99
    # current os releases supported by the UCA.
 
100
    local cloud_archive_versions="folsom grizzly"
 
101
 
 
102
    local ca_rel=$(echo $src | cut -d: -f2)
 
103
    local u_rel=$(echo $ca_rel | cut -d- -f1)
 
104
    local os_rel=$(echo $ca_rel | cut -d- -f2 | cut -d/ -f1)
92
105
 
93
106
    [[ "$u_rel" != "$DISTRIB_CODENAME" ]] &&
94
107
      error_out "Cannot install from Cloud Archive pocket $src " \
95
108
                "on this Ubuntu version ($DISTRIB_CODENAME)!"
96
109
 
97
 
    if [[ "$ca_rel" == "folsom/staging" ]] ; then
98
 
      # cloud archive staging is just a regular PPA.
99
 
      add-apt-repository -y ppa:ubuntu-cloud-archive/folsom-staging
 
110
    valid_release=""
 
111
    for rel in $cloud_archive_versions ; do
 
112
      if [[ "$os_rel" == "$rel" ]] ; then
 
113
        valid_release=1
 
114
        juju-log "Installing OpenStack ($os_rel) from the Ubuntu Cloud Archive."
 
115
      fi
 
116
    done
 
117
    if [[ -z "$valid_release" ]] ; then
 
118
      error_out "OpenStack release ($os_rel) not supported by "\
 
119
                "the Ubuntu Cloud Archive."
 
120
    fi
 
121
 
 
122
    # CA staging repos are standard PPAs.
 
123
    if echo $ca_rel | grep -q "staging" ; then
 
124
      add-apt-repository -y ppa:ubuntu-cloud-archive/${os_rel}-staging
100
125
      return 0
101
126
    fi
102
127
 
 
128
    # the others are LP-external deb repos.
103
129
    case "$ca_rel" in
104
 
      "folsom"|"folsom/updates") pocket="precise-updates/folsom" ;;
105
 
      "folsom/proposed") pocket="precise-proposed/folsom" ;;
 
130
      "$u_rel-$os_rel"|"$u_rel-$os_rel/updates") pocket="$u_rel-updates/$os_rel" ;;
 
131
      "$u_rel-$os_rel/proposed") pocket="$u_rel-proposed/$os_rel" ;;
 
132
      "$u_rel-$os_rel"|"$os_rel/updates") pocket="$u_rel-updates/$os_rel" ;;
 
133
      "$u_rel-$os_rel/proposed") pocket="$u_rel-proposed/$os_rel" ;;
106
134
      *) error_out "Invalid Cloud Archive repo specified: $src"
107
135
    esac
108
136
 
 
137
    apt-get -y install ubuntu-cloud-keyring
109
138
    entry="deb http://ubuntu-cloud.archive.canonical.com/ubuntu $pocket main"
110
139
    echo "$entry" \
111
140
      >/etc/apt/sources.list.d/ubuntu-cloud-archive-$DISTRIB_CODENAME.list
112
 
    apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys $archive_key
113
141
    return 0
114
142
  fi
115
143
 
142
170
      case "$ca_rel" in
143
171
        "folsom"|"folsom/updates"|"folsom/proposed"|"folsom/staging")
144
172
          codename="folsom" ;;
145
 
        "grizzly"|"grizzly/updates"|"grizzly/proposed"|"grizzy/staging")
146
 
          codename="grizly" ;;
 
173
        "grizzly"|"grizzly/updates"|"grizzly/proposed"|"grizzly/staging")
 
174
          codename="grizzly" ;;
147
175
      esac
148
176
    fi
149
177
  fi
150
178
 
151
179
  # have a guess based on the deb string provided
152
 
  if [[ "${rel:0:3}" == "deb" ]]; then
153
 
    CODENAMES="diablo essex folsom grizzly"
 
180
  if [[ "${rel:0:3}" == "deb" ]] || \
 
181
     [[ "${rel:0:3}" == "ppa" ]] ; then
 
182
    CODENAMES="diablo essex folsom grizzly havana"
154
183
    for cname in $CODENAMES; do
155
184
      if echo $rel | grep -q $cname; then
156
185
        codename=$cname
161
190
}
162
191
 
163
192
get_os_codename_package() {
164
 
  local pkg_vers=$(dpkg -l | grep "$1" | awk '{ print $3 }')
 
193
  local pkg_vers=$(dpkg -l | grep "$1" | awk '{ print $3 }') || echo "none"
 
194
  pkg_vers=$(echo $pkg_vers | cut -d: -f2) # epochs
165
195
  case "${pkg_vers:0:6}" in
166
196
    "2011.2") echo "diablo" ;;
167
197
    "2012.1") echo "essex" ;;
168
198
    "2012.2") echo "folsom" ;;
169
199
    "2013.1") echo "grizzly" ;;
 
200
    "2013.2") echo "havana" ;;
170
201
  esac
171
202
}
172
203
 
175
206
    "diablo") echo "2011.2" ;;
176
207
    "essex") echo "2012.1" ;;
177
208
    "folsom") echo "2012.2" ;;
178
 
    "grizzly") echo "2012.3" ;;
 
209
    "grizzly") echo "2013.1" ;;
 
210
    "havana") echo "2013.2" ;;
179
211
  esac
180
212
}
181
213
 
200
232
    pass
201
233
"
202
234
}
 
235
 
 
236
# Common storage routines used by cinder, nova-volume and swift-storage.
 
237
clean_storage() {
 
238
  # if configured to overwrite existing storage, we unmount the block-dev
 
239
  # if mounted and clear any previous pv signatures
 
240
  local block_dev="$1"
 
241
  juju-log "Cleaining storage '$block_dev'"
 
242
  if grep -q "^$block_dev" /proc/mounts ; then
 
243
    mp=$(grep "^$block_dev" /proc/mounts   | awk '{ print $2 }')
 
244
    juju-log "Unmounting $block_dev from $mp"
 
245
    umount "$mp" || error_out "ERROR: Could not unmount storage from $mp"
 
246
  fi
 
247
  if pvdisplay "$block_dev" >/dev/null 2>&1 ; then
 
248
    juju-log "Removing existing LVM PV signatures from $block_dev"
 
249
 
 
250
    # deactivate any volgroups that may be built on this dev
 
251
    vg=$(pvdisplay $block_dev | grep "VG Name" | awk '{ print $3 }')
 
252
    if [[ -n "$vg" ]] ; then
 
253
      juju-log "Deactivating existing volume group: $vg"
 
254
      vgchange -an "$vg" ||
 
255
        error_out "ERROR: Could not deactivate volgroup $vg.  Is it in use?"
 
256
    fi
 
257
    echo "yes" | pvremove -ff "$block_dev" ||
 
258
      error_out "Could not pvremove $block_dev"
 
259
  else
 
260
    juju-log "Zapping disk of all GPT and MBR structures"
 
261
    sgdisk --zap-all $block_dev ||
 
262
      error_out "Unable to zap $block_dev"
 
263
  fi
 
264
}
 
265
 
 
266
function get_block_device() {
 
267
  # given a string, return full path to the block device for that
 
268
  # if input is not a block device, find a loopback device
 
269
  local input="$1"
 
270
 
 
271
  case "$input" in
 
272
    /dev/*) [[ ! -b "$input" ]] && error_out "$input does not exist."
 
273
            echo "$input"; return 0;;
 
274
    /*) :;;
 
275
    *)  [[ ! -b "/dev/$input" ]] && error_out "/dev/$input does not exist."
 
276
        echo "/dev/$input"; return 0;;
 
277
  esac
 
278
 
 
279
  # this represents a file
 
280
  # support "/path/to/file|5G"
 
281
  local fpath size oifs="$IFS"
 
282
  if [ "${input#*|}" != "${input}" ]; then
 
283
    size=${input##*|}
 
284
    fpath=${input%|*}
 
285
  else
 
286
    fpath=${input}
 
287
    size=5G
 
288
  fi
 
289
 
 
290
  ## loop devices are not namespaced.  This is bad for containers.
 
291
  ## it means that the output of 'losetup' may have the given $fpath
 
292
  ## in it, but that may not represent this containers $fpath, but
 
293
  ## another containers.  To address that, we really need to
 
294
  ## allow some uniq container-id to be expanded within path.
 
295
  ## TODO: find a unique container-id that will be consistent for
 
296
  ##       this container throughout its lifetime and expand it
 
297
  ##       in the fpath.
 
298
  # fpath=${fpath//%{id}/$THAT_ID}
 
299
 
 
300
  local found=""
 
301
  # parse through 'losetup -a' output, looking for this file
 
302
  # output is expected to look like:
 
303
  #   /dev/loop0: [0807]:961814 (/tmp/my.img)
 
304
  found=$(losetup -a |
 
305
    awk 'BEGIN { found=0; }
 
306
         $3 == f { sub(/:$/,"",$1); print $1; found=found+1; }
 
307
         END { if( found == 0 || found == 1 ) { exit(0); }; exit(1); }' \
 
308
         f="($fpath)")
 
309
 
 
310
  if [ $? -ne 0 ]; then
 
311
    echo "multiple devices found for $fpath: $found" 1>&2
 
312
    return 1;
 
313
  fi
 
314
 
 
315
  [ -n "$found" -a -b "$found" ] && { echo "$found"; return 1; }
 
316
 
 
317
  if [ -n "$found" ]; then
 
318
    echo "confused, $found is not a block device for $fpath";
 
319
    return 1;
 
320
  fi
 
321
 
 
322
  # no existing device was found, create one
 
323
  mkdir -p "${fpath%/*}"
 
324
  truncate --size "$size" "$fpath" ||
 
325
    { echo "failed to create $fpath of size $size"; return 1; }
 
326
 
 
327
  found=$(losetup --find --show "$fpath") ||
 
328
    { echo "failed to setup loop device for $fpath" 1>&2; return 1; }
 
329
 
 
330
  echo "$found"
 
331
  return 0
 
332
}
 
333
 
 
334
HAPROXY_CFG=/etc/haproxy/haproxy.cfg
 
335
HAPROXY_DEFAULT=/etc/default/haproxy
 
336
##########################################################################
 
337
# Description: Configures HAProxy services for Openstack API's
 
338
# Parameters:
 
339
#   Space delimited list of service:port:mode combinations for which
 
340
#   haproxy service configuration should be generated for.  The function
 
341
#   assumes the name of the peer relation is 'cluster' and that every
 
342
#   service unit in the peer relation is running the same services.
 
343
#
 
344
#   Services that do not specify :mode in parameter will default to http.
 
345
#
 
346
# Example
 
347
#   configure_haproxy cinder_api:8776:8756:tcp nova_api:8774:8764:http
 
348
##########################################################################
 
349
configure_haproxy() {
 
350
  local address=`unit-get private-address`
 
351
  local name=${JUJU_UNIT_NAME////-}
 
352
  cat > $HAPROXY_CFG << EOF
 
353
global
 
354
  log 127.0.0.1 local0
 
355
  log 127.0.0.1 local1 notice
 
356
  maxconn 20000
 
357
  user haproxy
 
358
  group haproxy
 
359
  spread-checks 0
 
360
 
 
361
defaults
 
362
  log global
 
363
  mode http
 
364
  option httplog
 
365
  option dontlognull
 
366
  retries 3
 
367
  timeout queue 1000
 
368
  timeout connect 1000
 
369
  timeout client 30000
 
370
  timeout server 30000
 
371
 
 
372
listen stats :8888
 
373
  mode http
 
374
  stats enable
 
375
  stats hide-version
 
376
  stats realm Haproxy\ Statistics
 
377
  stats uri /
 
378
  stats auth admin:password
 
379
 
 
380
EOF
 
381
  for service in $@; do
 
382
    local service_name=$(echo $service | cut -d : -f 1)
 
383
    local haproxy_listen_port=$(echo $service | cut -d : -f 2)
 
384
    local api_listen_port=$(echo $service | cut -d : -f 3)
 
385
    local mode=$(echo $service | cut -d : -f 4)
 
386
    [[ -z "$mode" ]] && mode="http"
 
387
    juju-log "Adding haproxy configuration entry for $service "\
 
388
             "($haproxy_listen_port -> $api_listen_port)"
 
389
    cat >> $HAPROXY_CFG << EOF
 
390
listen $service_name 0.0.0.0:$haproxy_listen_port
 
391
  balance roundrobin
 
392
  mode $mode
 
393
  option ${mode}log
 
394
  server $name $address:$api_listen_port check
 
395
EOF
 
396
    local r_id=""
 
397
    local unit=""
 
398
    for r_id in `relation-ids cluster`; do
 
399
      for unit in `relation-list -r $r_id`; do
 
400
        local unit_name=${unit////-}
 
401
        local unit_address=`relation-get -r $r_id private-address $unit`
 
402
        if [ -n "$unit_address" ]; then
 
403
          echo "  server $unit_name $unit_address:$api_listen_port check" \
 
404
            >> $HAPROXY_CFG
 
405
        fi
 
406
      done
 
407
    done
 
408
  done
 
409
  echo "ENABLED=1" > $HAPROXY_DEFAULT
 
410
  service haproxy restart
 
411
}
 
412
 
 
413
##########################################################################
 
414
# Description: Query HA interface to determine is cluster is configured
 
415
# Returns: 0 if configured, 1 if not configured
 
416
##########################################################################
 
417
is_clustered() {
 
418
  local r_id=""
 
419
  local unit=""
 
420
  for r_id in $(relation-ids ha); do
 
421
    if [ -n "$r_id" ]; then
 
422
      for unit in $(relation-list -r $r_id); do
 
423
         clustered=$(relation-get -r $r_id clustered $unit)
 
424
         if [ -n "$clustered" ]; then
 
425
           juju-log "Unit is haclustered"
 
426
           return 0
 
427
         fi
 
428
      done
 
429
    fi
 
430
  done
 
431
  juju-log "Unit is not haclustered"
 
432
  return 1
 
433
}
 
434
 
 
435
##########################################################################
 
436
# Description: Return a list of all peers in cluster relations
 
437
##########################################################################
 
438
peer_units() {
 
439
  local peers=""
 
440
  local r_id=""
 
441
  for r_id in $(relation-ids cluster); do
 
442
    peers="$peers $(relation-list -r $r_id)"
 
443
  done
 
444
  echo $peers
 
445
}
 
446
 
 
447
##########################################################################
 
448
# Description: Determines whether the current unit is the oldest of all
 
449
#              its peers - supports partial leader election
 
450
# Returns: 0 if oldest, 1 if not
 
451
##########################################################################
 
452
oldest_peer() {
 
453
  peers=$1
 
454
  local l_unit_no=$(echo $JUJU_UNIT_NAME | cut -d / -f 2)
 
455
  for peer in $peers; do
 
456
    echo "Comparing $JUJU_UNIT_NAME with peers: $peers"
 
457
    local r_unit_no=$(echo $peer | cut -d / -f 2)
 
458
    if (($r_unit_no<$l_unit_no)); then
 
459
        juju-log "Not oldest peer; deferring"
 
460
        return 1
 
461
    fi
 
462
  done
 
463
  juju-log "Oldest peer; might take charge?"
 
464
  return 0
 
465
}
 
466
 
 
467
##########################################################################
 
468
# Description: Determines whether the current service units is the
 
469
#              leader within a) a cluster of its peers or b) across a
 
470
#              set of unclustered peers.
 
471
# Parameters: CRM resource to check ownership of if clustered
 
472
# Returns: 0 if leader, 1 if not
 
473
##########################################################################
 
474
eligible_leader() {
 
475
  if is_clustered; then
 
476
    if ! is_leader $1; then
 
477
      juju-log 'Deferring action to CRM leader'
 
478
      return 1
 
479
    fi
 
480
  else
 
481
    peers=$(peer_units)
 
482
    if [ -n "$peers" ] && ! oldest_peer "$peers"; then
 
483
      juju-log 'Deferring action to oldest service unit.'
 
484
      return 1
 
485
    fi
 
486
  fi
 
487
  return 0
 
488
}
 
489
 
 
490
##########################################################################
 
491
# Description: Query Cluster peer interface to see if peered
 
492
# Returns: 0 if peered, 1 if not peered
 
493
##########################################################################
 
494
is_peered() {
 
495
  local r_id=$(relation-ids cluster)
 
496
  if [ -n "$r_id" ]; then
 
497
    if [ -n "$(relation-list -r $r_id)" ]; then
 
498
      juju-log "Unit peered"
 
499
      return 0
 
500
    fi
 
501
  fi
 
502
  juju-log "Unit not peered"
 
503
  return 1
 
504
}
 
505
 
 
506
##########################################################################
 
507
# Description: Determines whether host is owner of clustered services
 
508
# Parameters: Name of CRM resource to check ownership of
 
509
# Returns: 0 if leader, 1 if not leader
 
510
##########################################################################
 
511
is_leader() {
 
512
  hostname=`hostname`
 
513
  if [ -x /usr/sbin/crm ]; then
 
514
    if crm resource show $1 | grep -q $hostname; then
 
515
      juju-log "$hostname is cluster leader."
 
516
      return 0
 
517
    fi
 
518
  fi
 
519
  juju-log "$hostname is not cluster leader."
 
520
  return 1
 
521
}
 
522
 
 
523
##########################################################################
 
524
# Description: Determines whether enough data has been provided in
 
525
# configuration or relation data to configure HTTPS.
 
526
# Parameters:  None
 
527
# Returns: 0 if HTTPS can be configured, 1 if not.
 
528
##########################################################################
 
529
https() {
 
530
  local r_id=""
 
531
  if [[ -n "$(config-get ssl_cert)" ]] &&
 
532
     [[ -n "$(config-get ssl_key)" ]] ; then
 
533
    return 0
 
534
  fi
 
535
  for r_id in $(relation-ids identity-service) ; do
 
536
    for unit in $(relation-list -r $r_id) ; do
 
537
      if [[ "$(relation-get -r $r_id https_keystone $unit)" == "True" ]] &&
 
538
         [[ -n "$(relation-get -r $r_id ssl_cert $unit)" ]] &&
 
539
         [[ -n "$(relation-get -r $r_id ssl_key $unit)" ]] &&
 
540
         [[ -n "$(relation-get -r $r_id ca_cert $unit)" ]] ; then
 
541
          return 0
 
542
      fi
 
543
    done
 
544
  done
 
545
  return 1
 
546
}
 
547
 
 
548
##########################################################################
 
549
# Description: For a given number of port mappings, configures apache2
 
550
# HTTPs local reverse proxying using certficates and keys provided in
 
551
# either configuration data (preferred) or relation data.  Assumes ports
 
552
# are not in use (calling charm should ensure that).
 
553
# Parameters:  Variable number of proxy port mappings as
 
554
# $internal:$external.
 
555
# Returns: 0 if reverse proxy(s) have been configured, 0 if not.
 
556
##########################################################################
 
557
enable_https() {
 
558
  local port_maps="$@"
 
559
  local http_restart=""
 
560
  juju-log "Enabling HTTPS for port mappings: $port_maps."
 
561
 
 
562
  # allow overriding of keystone provided certs with those set manually
 
563
  # in config.
 
564
  local cert=$(config-get ssl_cert)
 
565
  local key=$(config-get ssl_key)
 
566
  local ca_cert=""
 
567
  if [[ -z "$cert" ]] || [[ -z "$key" ]] ; then
 
568
    juju-log "Inspecting identity-service relations for SSL certificate."
 
569
    local r_id=""
 
570
    cert=""
 
571
    key=""
 
572
    ca_cert=""
 
573
    for r_id in $(relation-ids identity-service) ; do
 
574
      for unit in $(relation-list -r $r_id) ; do
 
575
        [[ -z "$cert" ]] && cert="$(relation-get -r $r_id ssl_cert $unit)"
 
576
        [[ -z "$key" ]] && key="$(relation-get -r $r_id ssl_key $unit)"
 
577
        [[ -z "$ca_cert" ]] && ca_cert="$(relation-get -r $r_id ca_cert $unit)"
 
578
      done
 
579
    done
 
580
    [[ -n "$cert" ]] && cert=$(echo $cert | base64 -di)
 
581
    [[ -n "$key" ]] && key=$(echo $key | base64 -di)
 
582
    [[ -n "$ca_cert" ]] && ca_cert=$(echo $ca_cert | base64 -di)
 
583
  else
 
584
    juju-log "Using SSL certificate provided in service config."
 
585
  fi
 
586
 
 
587
  [[ -z "$cert" ]] || [[ -z "$key" ]] &&
 
588
    juju-log "Expected but could not find SSL certificate data, not "\
 
589
             "configuring HTTPS!" && return 1
 
590
 
 
591
  apt-get -y install apache2
 
592
  a2enmod ssl proxy proxy_http | grep -v "To activate the new configuration" &&
 
593
    http_restart=1
 
594
 
 
595
  mkdir -p /etc/apache2/ssl/$CHARM
 
596
  echo "$cert" >/etc/apache2/ssl/$CHARM/cert
 
597
  echo "$key" >/etc/apache2/ssl/$CHARM/key
 
598
  if [[ -n "$ca_cert" ]] ; then
 
599
    juju-log "Installing Keystone supplied CA cert."
 
600
    echo "$ca_cert" >/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt
 
601
    update-ca-certificates --fresh
 
602
 
 
603
    # XXX TODO: Find a better way of exporting this?
 
604
    if [[ "$CHARM" == "nova-cloud-controller" ]] ; then
 
605
      [[ -e /var/www/keystone_juju_ca_cert.crt ]] &&
 
606
        rm -rf /var/www/keystone_juju_ca_cert.crt
 
607
      ln -s  /usr/local/share/ca-certificates/keystone_juju_ca_cert.crt \
 
608
             /var/www/keystone_juju_ca_cert.crt
 
609
    fi
 
610
 
 
611
  fi
 
612
  for port_map in $port_maps ; do
 
613
    local ext_port=$(echo $port_map | cut -d: -f1)
 
614
    local int_port=$(echo $port_map | cut -d: -f2)
 
615
    juju-log "Creating apache2 reverse proxy vhost for $port_map."
 
616
    cat >/etc/apache2/sites-available/${CHARM}_${ext_port} <<END
 
617
Listen $ext_port
 
618
NameVirtualHost *:$ext_port
 
619
<VirtualHost *:$ext_port>
 
620
    ServerName $(unit-get private-address)
 
621
    SSLEngine on
 
622
    SSLCertificateFile /etc/apache2/ssl/$CHARM/cert
 
623
    SSLCertificateKeyFile /etc/apache2/ssl/$CHARM/key
 
624
    ProxyPass / http://localhost:$int_port/
 
625
    ProxyPassReverse / http://localhost:$int_port/
 
626
    ProxyPreserveHost on
 
627
</VirtualHost>
 
628
<Proxy *>
 
629
    Order deny,allow
 
630
    Allow from all
 
631
</Proxy>
 
632
<Location />
 
633
    Order allow,deny
 
634
    Allow from all
 
635
</Location>
 
636
END
 
637
    a2ensite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
 
638
      http_restart=1
 
639
  done
 
640
  if [[ -n "$http_restart" ]] ; then
 
641
    service apache2 restart
 
642
  fi
 
643
}
 
644
 
 
645
##########################################################################
 
646
# Description: Ensure HTTPS reverse proxying is disabled for given port
 
647
# mappings.
 
648
# Parameters:  Variable number of proxy port mappings as
 
649
# $internal:$external.
 
650
# Returns: 0 if reverse proxy is not active for all portmaps, 1 on error.
 
651
##########################################################################
 
652
disable_https() {
 
653
  local port_maps="$@"
 
654
  local http_restart=""
 
655
  juju-log "Ensuring HTTPS disabled for $port_maps."
 
656
  ( [[ ! -d /etc/apache2 ]] || [[ ! -d /etc/apache2/ssl/$CHARM ]] ) && return 0
 
657
  for port_map in $port_maps ; do
 
658
    local ext_port=$(echo $port_map | cut -d: -f1)
 
659
    local int_port=$(echo $port_map | cut -d: -f2)
 
660
    if [[ -e /etc/apache2/sites-available/${CHARM}_${ext_port} ]] ; then
 
661
      juju-log "Disabling HTTPS reverse proxy for $CHARM $port_map."
 
662
      a2dissite ${CHARM}_${ext_port} | grep -v "To activate the new configuration" &&
 
663
        http_restart=1
 
664
    fi
 
665
  done
 
666
  if [[ -n "$http_restart" ]] ; then
 
667
    service apache2 restart
 
668
  fi
 
669
}
 
670
 
 
671
 
 
672
##########################################################################
 
673
# Description: Ensures HTTPS is either enabled or disabled for given port
 
674
# mapping.
 
675
# Parameters:  Variable number of proxy port mappings as
 
676
# $internal:$external.
 
677
# Returns: 0 if HTTPS reverse proxy is in place, 1 if it is not.
 
678
##########################################################################
 
679
setup_https() {
 
680
  # configure https via apache reverse proxying either
 
681
  # using certs provided by config or keystone.
 
682
  [[ -z "$CHARM" ]] &&
 
683
    error_out "setup_https(): CHARM not set."
 
684
  if ! https ; then
 
685
    disable_https $@
 
686
  else
 
687
    enable_https $@
 
688
  fi
 
689
}
 
690
 
 
691
##########################################################################
 
692
# Description: Determine correct API server listening port based on
 
693
# existence of HTTPS reverse proxy and/or haproxy.
 
694
# Paremeters: The standard public port for given service.
 
695
# Returns: The correct listening port for API service.
 
696
##########################################################################
 
697
determine_api_port() {
 
698
  local public_port="$1"
 
699
  local i=0
 
700
  ( [[ -n "$(peer_units)" ]] || is_clustered >/dev/null 2>&1 ) && i=$[$i + 1]
 
701
  https >/dev/null 2>&1 && i=$[$i + 1]
 
702
  echo $[$public_port - $[$i * 10]]
 
703
}
 
704
 
 
705
##########################################################################
 
706
# Description: Determine correct proxy listening port based on public IP +
 
707
# existence of HTTPS reverse proxy.
 
708
# Paremeters: The standard public port for given service.
 
709
# Returns: The correct listening port for haproxy service public address.
 
710
##########################################################################
 
711
determine_haproxy_port() {
 
712
  local public_port="$1"
 
713
  local i=0
 
714
  https >/dev/null 2>&1 && i=$[$i + 1]
 
715
  echo $[$public_port - $[$i * 10]]
 
716
}
 
717
 
 
718
##########################################################################
 
719
# Description: Print the value for a given config option in an OpenStack
 
720
# .ini style configuration file.
 
721
# Parameters: File path, option to retrieve, optional
 
722
# section name (default=DEFAULT)
 
723
# Returns: Prints value if set, prints nothing otherwise.
 
724
##########################################################################
 
725
local_config_get() {
 
726
  # return config values set in openstack .ini config files.
 
727
  # default placeholders starting (eg, %AUTH_HOST%) treated as
 
728
  # unset values.
 
729
  local file="$1"
 
730
  local option="$2"
 
731
  local section="$3"
 
732
  [[ -z "$section" ]] && section="DEFAULT"
 
733
  python -c "
 
734
import ConfigParser
 
735
config = ConfigParser.RawConfigParser()
 
736
config.read('$file')
 
737
try:
 
738
  value = config.get('$section', '$option')
 
739
except:
 
740
  print ''
 
741
  exit(0)
 
742
if value.startswith('%'): exit(0)
 
743
print value
 
744
"
 
745
}
 
746
 
 
747
##########################################################################
 
748
# Description: Creates an rc file exporting environment variables to a
 
749
# script_path local to the charm's installed directory.
 
750
# Any charm scripts run outside the juju hook environment can source this
 
751
# scriptrc to obtain updated config information necessary to perform health
 
752
# checks or service changes
 
753
#
 
754
# Parameters:
 
755
#   An array of '=' delimited  ENV_VAR:value combinations to export.
 
756
#   If optional script_path key is not provided in the array, script_path
 
757
#     defaults to scripts/scriptrc
 
758
##########################################################################
 
759
function save_script_rc {
 
760
  if [ ! -n "$JUJU_UNIT_NAME" ]; then
 
761
     echo "Error: Missing JUJU_UNIT_NAME environment variable"
 
762
     exit 1
 
763
  fi
 
764
  # our default unit_path
 
765
  unit_path="$CHARM_DIR/scripts/scriptrc"
 
766
  echo $unit_path
 
767
  tmp_rc="/tmp/${JUJU_UNIT_NAME/\//-}rc"
 
768
 
 
769
  echo "#!/bin/bash" > $tmp_rc
 
770
  for env_var in "${@}"
 
771
  do
 
772
    if `echo $env_var | grep -q script_path`; then
 
773
       # well then we need to reset the new unit-local script path
 
774
       unit_path="$CHARM_DIR/${env_var/script_path=/}"
 
775
    else
 
776
       echo "export $env_var" >> $tmp_rc
 
777
    fi
 
778
  done
 
779
  chmod 755 $tmp_rc
 
780
  mv $tmp_rc $unit_path
 
781
}