~jjo/charms/precise/cassandra/merge-reworked-leader-election

« back to all changes in this revision

Viewing changes to hooks/cassandra-common

  • Committer: David Ames
  • Date: 2013-10-24 22:00:11 UTC
  • mfrom: (28.1.1 cassandra-store-jjo)
  • Revision ID: david.ames@canonical.com-20131024220011-iycrvsj97s1tkne9
[jjo, r=dames] merge Canonical IS cassandra charm fixes and features:
- [jjo,r=dames] Allow partial config-change by implementing units-to-update
- [jjo,r=dames] Implement simpleauth (base64 encoded passwd and auth file contents), and extra-jvm-opts
- [dames,r=mthaddon] Handle end point snitch, num_tokens/intial_toekn and partitioner
- [ev,r=dames,r=gnouy] Don't restart Cassandra when config-changed fires unless we've committed some /etc/cassandra

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
# vim: set tabstop=2 expandtab:
3
3
 
4
4
. ./scripts/volume-common.sh
 
5
ETC_CASSANDRA="${ETC_CASSANDRA:-/etc/cassandra}"
 
6
CASSANDRA_ENV="${ETC_CASSANDRA}/cassandra-env.sh"
 
7
CASSANDRA_YML="${ETC_CASSANDRA}/cassandra.yaml"
 
8
CASSANDRA_ACCESS="${ETC_CASSANDRA}/access.properties"
 
9
CASSANDRA_PASSWD="${ETC_CASSANDRA}/passwd.properties"
 
10
CASSANDRA_RACKDC="${ETC_CASSANDRA}/cassandra-rackdc.properties"
 
11
CASSANDRA_TOPOLOGY="${ETC_CASSANDRA}/cassandra-topology.properties"
 
12
CASSANDRA_USER="cassandra"
 
13
CASSANDRA_GROUP="cassandra"
5
14
 
6
15
set -e
7
16
 
29
38
bzr_ci () {
30
39
  local msg=${FUNCNAME[1]}
31
40
  test -n "$1" && msg="$1"
32
 
  bzr st /etc/cassandra|egrep -q '^modified|added' || return 1
33
 
  bzr ci -m "[$(date "+%Y-%m-%d %H:%M:%S")] ${JUJU_UNIT_NAME}: ${msg} auto-commit" /etc/cassandra || return 1
 
41
  bzr st ${ETC_CASSANDRA}|egrep -q '^modified|added' || return 1
 
42
  bzr ci -m "[$(date "+%Y-%m-%d %H:%M:%S")] ${JUJU_UNIT_NAME}: ${msg} auto-commit" ${ETC_CASSANDRA} || return 1
34
43
  return 0
35
44
}
36
45
 
70
79
 
71
80
# Update the cassandra environment with the appropriate JMX port
72
81
configure_jmx_port () {
 
82
  check_units_to_update || return 0
73
83
  juju-log "Configuring JMX port"
74
84
  JMX_PORT=$(config-get jmx-port)
75
85
  test -n "${JMX_PORT}" || return 1
76
86
  test ${JMX_PORT} -gt 0 -a ${JMX_PORT} -lt 65535 || return 1
77
 
  sed -i -e "s/^JMX_PORT=.*/JMX_PORT=\"${JMX_PORT}\"/" /etc/cassandra/cassandra-env.sh
 
87
  sed -i -e "s/^JMX_PORT=.*/JMX_PORT=\"${JMX_PORT}\"/" ${CASSANDRA_ENV}
78
88
  # Open port ready for expose
79
89
  open-port ${JMX_PORT}/TCP
80
90
}
108
118
}
109
119
 
110
120
srv_root_get() {
111
 
  sed -r -n 's,commitlog_directory: *([^ ]+)/commitlog.*,\1,p' /etc/cassandra/cassandra.yaml
 
121
  sed -r -n 's,commitlog_directory: *([^ ]+)/commitlog.*,\1,p' ${CASSANDRA_YML}
112
122
}
113
123
srv_root_from_volid() {
114
124
  local volid=${1?missing volid}
124
134
  sed -i -r -e $'/data_file_directories:/{\nN;s|- /.*|- '"${srv_root}/data"'|}' \
125
135
         -e "s|^(commitlog_directory):.*|\1: ${srv_root}/commitlog|" \
126
136
         -e "s|^(saved_caches_directory):.*|\1: ${srv_root}/savedcache_dir|" \
127
 
         /etc/cassandra/cassandra.yaml
 
137
         ${CASSANDRA_YML}
128
138
  test -d "${srv_root}" || {
129
139
    mkdir -p "${srv_root}"
130
 
    chown -R cassandra:cassandra "${srv_root}"
 
140
    chown -R ${CASSANDRA_USER}:${CASSANDRA_GROUP} "${srv_root}"
131
141
  }
132
142
}
133
143
disable_cassandra_start() {
170
180
 
171
181
# Construct the cassandra.yaml file from the appropriate information above
172
182
configure_cassandra () {
 
183
  check_units_to_update || return 0
173
184
  juju-log "Configuring Cassandra"
174
185
  local LISTEN_ADDRESS=$(get_private_ip)
175
186
  local CLUSTER_PORT=$(config-get cluster-port)
183
194
  local NUM_TOKENS=$(config-get num-tokens)
184
195
  local SEED_ADDRESSES=$(get_seed_nodes)
185
196
  local INITIAL_TOKEN=$(get_initial_token)
 
197
  local PARTITIONER=$(config-get partitioner)
 
198
  local ENDPOINT_SNITCH=$(config-get endpoint_snitch)
 
199
  local DATACENTER=$(config-get datacenter)
 
200
  local RACK=$(config-get rack)
 
201
  local DC_SUFFIX=$(config-get dc_suffix)
 
202
  local PREFER_LOCAL=$(config-get prefer_local | tr '[:upper:]' '[:lower:]')
186
203
  # This needs to 'detect' whether its running in ec2
187
204
  # and use the ec2Snitch instead if it is - or we could
188
205
  # specify this as a configuration parameter
189
206
  # non-trivial sed to edit data_file_directories (has its value in the line following it)
190
207
  sed -i -r -e "s/^cluster_name:.*/cluster_name: \'${CLUSTER_NAME}\'/" \
191
 
         -e "s/^(initial_token):.*/\1: ${INITIAL_TOKEN}/" \
192
208
         -e "s/(- seeds):.*/\1: \"${SEED_ADDRESSES}\"/" \
193
209
         -e "s/^(storage_port):.*/\1: ${CLUSTER_PORT}/" \
194
210
         -e "s/^(listen_address):.*/\1: ${LISTEN_ADDRESS}/" \
195
211
         -e "s/^(rpc_address):.*/\1: ${LISTEN_ADDRESS}/" \
196
212
         -e "s/^(rpc_port):.*/\1: ${CLIENT_PORT}/" \
197
213
         -e "s/^(compaction_throughput_mb_per_sec):.*/\1: ${COMPACTION_THROUGHPUT}/" \
198
 
         /etc/cassandra/cassandra.yaml
 
214
         -e "s/^(partitioner):.*/\1: ${PARTITIONER}/" \
 
215
         -e "s/^(endpoint_snitch):.*/\1: ${ENDPOINT_SNITCH}/" \
 
216
         ${CASSANDRA_YML}
199
217
 
200
 
  if [ -n "$NUM_TOKENS" ]; then
 
218
  ## Number of tokens or initial token
 
219
  if [ $NUM_TOKENS -eq 0 ] && [ -n "$INITIAL_TOKEN" ]; then
 
220
      sed -i -r -e "s/^(# )?(num_tokens):.*/#\2: ${NUM_TOKENS}/" \
 
221
         -e "s/^(# )?(initial_token):.*/\2: ${INITIAL_TOKEN}/" \
 
222
         ${CASSANDRA_YML}
 
223
  elif [ $NUM_TOKENS -gt 0 ] && [ -z "$INITIAL_TOKEN" ]; then 
201
224
      sed -i -r -e "s/^(# )?(num_tokens):.*/\2: ${NUM_TOKENS}/" \
202
 
         /etc/cassandra/cassandra.yaml
 
225
         -e "s/^(# )?(initial_token):.*/# \2: ${INITIAL_TOKEN}/" \
 
226
         ${CASSANDRA_YML}
 
227
  else
 
228
        juju-log "ERROR: cannot specify num_tokens and initial_token"
 
229
        exit 1
 
230
  fi
 
231
 
 
232
  ## Enpoint Snitch configuration
 
233
  # XXX Handle more endpoint snitch options
 
234
  if [[ "$ENDPOINT_SNITCH" =~ .*SimpleSnitch ]]; then
 
235
    rm -f ${CASSANDRA_RACKDC} ${CASSANDRA_TOPOLOGY}
 
236
  elif [[ "$ENDPOINT_SNITCH" =~ .*GossipingPropertyFileSnitch ]]; then
 
237
    rm -f ${CASSANDRA_TOPOLOGY}
 
238
    (
 
239
        echo "dc=${DATACENTER}"
 
240
        echo "rack=${RACK}"
 
241
        if [ -n "$DC_SUFFIX" ]; then
 
242
          echo "dc_suffix=${DC_SUFFIX}"
 
243
        fi
 
244
        if [ "$PREFER_LOCAL" = "true" ]; then
 
245
          echo "prefer_local=true"
 
246
        fi
 
247
    ) > ${CASSANDRA_RACKDC}
 
248
  else
 
249
    rm -f ${CASSANDRA_RACKDC}
203
250
  fi
204
251
 
205
252
  ## Storage configuration
233
280
 
234
281
  # Default cassandra-env.sh for some cassandra 1.0.x specifies -Xss128k
235
282
  # while 160k min is required
236
 
  sed -i -e "s/-Xss128k/-Xss256k/" /etc/cassandra/cassandra-env.sh
 
283
  sed -i -e "s/-Xss128k/-Xss256k/" ${CASSANDRA_ENV}
237
284
  # Configure memory settings as specified in configuration
238
285
  if [ "$AUTO_MEMORY" = "False" ]; then
239
286
    juju-log "Configuring Manual Memory Setttings"
240
287
    sed -i -e "s/^[#]MAX_HEAP_SIZE=.*/MAX_HEAP_SIZE=\"${HEAP_SIZE}\"/" \
241
 
           -e "s/^[#]HEAP_NEWSIZE=.*/HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" /etc/cassandra/cassandra-env.sh
 
288
           -e "s/^[#]HEAP_NEWSIZE=.*/HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" ${CASSANDRA_ENV}
242
289
  else
243
290
    sed -i -e "s/^[#]MAX_HEAP_SIZE=.*/#MAX_HEAP_SIZE=\"${HEAP_SIZE}\"/" \
244
 
           -e "s/^[#]HEAP_NEWSIZE=.*/#HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" /etc/cassandra/cassandra-env.sh
 
291
           -e "s/^[#]HEAP_NEWSIZE=.*/#HEAP_NEWSIZE=\"${NEW_GEN_SIZE}\"/" ${CASSANDRA_ENV}
245
292
  fi 
 
293
  local use_simpleauth=$(config-get use-simpleauth)
 
294
  if [[ ${use_simpleauth} == True ]];then
 
295
      local auth_opts
 
296
      install -o ${CASSANDRA_USER} -m 600 /dev/null ${CASSANDRA_PASSWD}
 
297
      config-get auth-passwd64|base64 -d > ${CASSANDRA_PASSWD}
 
298
      config-get auth-access64|base64 -d > ${CASSANDRA_ACCESS}
 
299
      auth_opts="-Dpasswd.properties=${CASSANDRA_PASSWD} -Daccess.properties=${CASSANDRA_ACCESS}"
 
300
      add_JVM_OPTS_line "Daccess.properties" "$auth_opts"
 
301
      replace_YAML_key authenticator org.apache.cassandra.auth.SimpleAuthenticator
 
302
  else
 
303
      rm -f ${CASSANDRA_PASSWD} ${CASSANDRA_ACCESS}
 
304
      del_JVM_OPTS_line "Daccess.properties"
 
305
      replace_YAML_key authenticator org.apache.cassandra.auth.AllowAllAuthenticator
 
306
  fi
 
307
  local extra_jvm_opts=$(config-get extra-jvm-opts)
 
308
  if [[ ${extra_jvm_opts} != "" ]];then
 
309
      add_JVM_OPTS_line "JUJU_extra-jvm-opts" "$extra_jvm_opts"
 
310
  else
 
311
      del_JVM_OPTS_line "JUJU_extra-jvm-opts"
 
312
  fi
 
313
}
 
314
 
 
315
# Remove JVM_OPTS line by regex
 
316
del_JVM_OPTS_line() {
 
317
  local regex="${1?}"
 
318
  juju-log "Deleting from JVM_OPTS: key=${regex}"
 
319
  sed -ri "\!^JVM_OPTS=.*${regex}!d" ${CASSANDRA_ENV} || true
 
320
}
 
321
 
 
322
# Add JVM_OPTS line, use regex remove it before, if already present
 
323
add_JVM_OPTS_line() {
 
324
  local regex="${1?}" line="${2?}"
 
325
  del_JVM_OPTS_line "${regex}"
 
326
  juju-log "Adding to JVM_OPTS: ${line} (key=${regex})"
 
327
  echo "JVM_OPTS=\"\$JVM_OPTS ${line}\" ## ${regex} " >> ${CASSANDRA_ENV}
 
328
}
 
329
 
 
330
# Replace an *existent* YAML key: value
 
331
# Note that key will be treated as a regex
 
332
replace_YAML_key() {
 
333
  local key="${1?}" value="${2?}"
 
334
  juju-log "Replacing YAML: key=${key} value=${value}"
 
335
  sed -ri -e "s!^(${key}): .*!\1: ${value}!" ${CASSANDRA_YML}
246
336
}
247
337
 
248
338
# Service Control Commands
277
367
  IP=`get_private_ip`
278
368
  if [ -z "${seeds}" ] && am_i_the_leader; then
279
369
    juju-log "Configuring myself locally as a seed node"
280
 
    sed -i -e "s/\- seeds:.*/\- seeds: \"${IP}\"/" /etc/cassandra/cassandra.yaml
 
370
    sed -i -e "s/\- seeds:.*/\- seeds: \"${IP}\"/" ${CASSANDRA_YML}
281
371
  else
282
372
    juju-log "Setting seeds node to be ${seeds}"
283
 
    sed -i -e "s/\- seeds:.*/\- seeds: \"${seeds}\"/" /etc/cassandra/cassandra.yaml
 
373
    sed -i -e "s/\- seeds:.*/\- seeds: \"${seeds}\"/" ${CASSANDRA_YML}
284
374
  fi
285
375
  juju-log "$JUJU_REMOTE_UNIT modified its settings or departed"
286
376
  bzr_ci || :
374
464
  fi
375
465
}
376
466
 
377
 
# Actual processing
378
 
COMMAND=${0##*/}
 
467
# Check if units-to-update comma separated list contains my number, or "all",
 
468
# returns 0 if this unit should be updated
 
469
check_units_to_update() {
 
470
  local unit
 
471
  local units_to_update=$(config-get units-to-update)
 
472
  local unitnum=${JUJU_UNIT_NAME##*/}
 
473
  [[ $units_to_update == "all" ]] && return 0
 
474
  (
 
475
    OLDIFS="$IFS"
 
476
    IFS=" ,"
 
477
    for unit in ${units_to_update}; do
 
478
      if [[ $unit == $unitnum ]];then
 
479
        juju-log "check_units_to_update: \"${unitnum}\" in \"${units_to_update}\", updating."
 
480
        exit 0
 
481
      fi
 
482
    done
 
483
    juju-log "check_units_to_update: \"${unitnum}\" not in \"${units_to_update}\", skipping."
 
484
    exit 1
 
485
  )
 
486
  return $?
 
487
}
379
488
 
 
489
hook_main() {
 
490
local COMMAND="$1"
380
491
export BZR_HOME=/root
381
 
 
382
492
case $COMMAND in
383
493
  install)
384
494
    run_exec_d_hooks "pre-install"
386
496
    [[ -d /usr/share/cassandra ]] || install_cassandra
387
497
    # Initialize /etc/cassandra bzr
388
498
    bzr whoami "${JUJU_UNIT_NAME} <juju@${HOSTNAME}>"
389
 
    test -d /etc/cassandra/.bzr || bzr init /etc/cassandra && bzr add /etc/cassandra
390
 
    bzr_ci "main:${COMMAND}" /etc/cassandra || :
 
499
    test -d ${ETC_CASSANDRA}/.bzr || bzr init ${ETC_CASSANDRA} && bzr add ${ETC_CASSANDRA}
 
500
    bzr_ci "main:${COMMAND}" ${ETC_CASSANDRA} || :
391
501
    # Update the cassandra environment with the appropriate JMX port
392
502
    configure_jmx_port 
393
503
    bzr_ci || :
412
522
    update_nagios_checks
413
523
    ;;
414
524
  upgrade-charm)
 
525
    check_units_to_update || exit 0
415
526
    juju-log "Updating this charm - currently no-op"
416
527
    ;;
417
528
  stop)
443
554
    update_nagios_checks
444
555
    ;;
445
556
  *)
446
 
    juju-log "Command not recognised"
 
557
    juju-log "Command not recognised: $COMMAND"
447
558
    ;;
448
559
esac
449
 
 
 
560
}
 
561
# Actual processing, if not unittesting
 
562
test -n "$CASSANDRA_TESTING" || hook_main ${0##*/}