~matsubara/charms/trusty/mongodb/bug-1410847

« back to all changes in this revision

Viewing changes to hooks/hooks.py

  • Committer: Charles Butler
  • Date: 2014-07-08 18:53:07 UTC
  • mto: This revision was merged to the branch mainline in revision 50.
  • Revision ID: chuck@dasroot.net-20140708185307-aakhfrsvr2wwoxof
Adds charmhelpers, and refactors to green light deployments

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
    apt_update,
30
30
    apt_install
31
31
)
 
32
 
32
33
from charmhelpers.core.hookenv import (
33
 
    config
 
34
    config,
 
35
    unit_get,
 
36
    relation_get,
 
37
    relation_set,
 
38
    relations_for_id,
 
39
    relations_of_type,
 
40
    open_port,
 
41
    close_port,
 
42
)
 
43
 
 
44
from charmhelpers.core.hookenv import log as juju_log
 
45
 
 
46
from charmhelpers.core.host import (
 
47
    service,
34
48
)
35
49
 
36
50
 
47
61
# Supporting functions
48
62
###############################################################################
49
63
 
50
 
 
51
 
#------------------------------------------------------------------------------
52
 
# juju_log:  calls juju-log and records the message defined by the message
53
 
#            variable
54
 
#------------------------------------------------------------------------------
55
 
def juju_log(message=None):
56
 
    return (subprocess.call(['juju-log', str(message)]) == 0)
57
 
 
58
 
 
59
 
#------------------------------------------------------------------------------
60
 
# service:  Analogous to calling service on the command line to start/stop
61
 
#           and get status of a service/daemon.
62
 
#           Parameters:
63
 
#           service_name:    The name of the service to act on.
64
 
#           service_action:  The action (start, stop, status, etc.)
65
 
#           Returns: True if the command was successfully executed or False on
66
 
#                    error.
67
 
#------------------------------------------------------------------------------
68
 
def service(service_name=None, service_action=None):
69
 
    juju_log("service: %s, action: %s" % (service_name, service_action))
70
 
    if service_name is not None and service_action is not None:
71
 
        retVal = subprocess.call(
72
 
            ["service", service_name, service_action]) == 0
73
 
    else:
74
 
        retVal = False
75
 
    juju_log("service %s %s returns: %s" %
76
 
    (service_name, service_action, retVal))
77
 
    return(retVal)
78
 
 
79
 
 
80
 
#------------------------------------------------------------------------------
81
 
# unit_get:  Convenience function wrapping the juju command unit-get
82
 
#            Parameter:
83
 
#            setting_name:  The setting to get out of unit_get
84
 
#            Returns:  The requested information or None on error
85
 
#------------------------------------------------------------------------------
86
 
def unit_get(setting_name=None):
87
 
    juju_log("unit_get: %s" % setting_name)
88
 
    try:
89
 
        cmd_line = ['unit-get', '--format=json']
90
 
        if setting_name is not None:
91
 
            cmd_line.append(setting_name)
92
 
        unit_data = json.loads(subprocess.check_output(cmd_line))
93
 
    except Exception, e:
94
 
        subprocess.call(['juju-log', str(e)])
95
 
        unit_data = None
96
 
    finally:
97
 
        juju_log("unit_get %s returns: %s" % (setting_name, unit_data))
98
 
        return(unit_data)
99
 
 
100
 
 
101
 
#------------------------------------------------------------------------------
102
 
# config_get:  Returns a dictionary containing all of the config information
103
 
#              Optional parameter: scope
104
 
#              scope: limits the scope of the returned configuration to the
105
 
#                     desired config item.
106
 
#------------------------------------------------------------------------------
107
 
def config_get(scope=None):
108
 
    juju_log("config_get: %s" % scope)
109
 
    try:
110
 
        config_cmd_line = ['config-get']
111
 
        if scope is not None:
112
 
            config_cmd_line.append(scope)
113
 
        config_cmd_line.append('--format=json')
114
 
        config_data = json.loads(subprocess.check_output(config_cmd_line))
115
 
    except Exception, e:
116
 
        juju_log(str(e))
117
 
        config_data = None
118
 
    finally:
119
 
        juju_log("config_get: %s returns: %s" % (scope, config_data))
120
 
        return(config_data)
121
 
 
122
 
 
123
 
#------------------------------------------------------------------------------
124
 
# relation_get:  Returns a dictionary containing the relation information
125
 
#                Optional parameters: scope, relation_id
126
 
#                scope:        limits the scope of the returned data to the
127
 
#                              desired item.
128
 
#                unit_name:    limits the data ( and optionally the scope )
129
 
#                              to the specified unit
130
 
#                relation_id:  specify relation id for out of context usage.
131
 
#------------------------------------------------------------------------------
132
 
def relation_get(scope=None, unit_name=None, relation_id=None,
133
 
        wait_for=default_wait_for, max_tries=default_max_tries):
134
 
    juju_log("relation_get: scope: %s, unit_name: %s, relation_id: %s" %
135
 
    (scope, unit_name, relation_id))
136
 
    current_try = 0
137
 
    try:
138
 
        relation_cmd_line = ['relation-get', '--format=json']
139
 
        if relation_id is not None:
140
 
            relation_cmd_line.extend(('-r', relation_id))
141
 
        if scope is not None:
142
 
            relation_cmd_line.append(scope)
143
 
        else:
144
 
            relation_cmd_line.append('')
145
 
        if unit_name is not None:
146
 
            relation_cmd_line.append(unit_name)
147
 
        relation_data = json.loads(subprocess.check_output(relation_cmd_line))
148
 
 
149
 
#        while relation_data is None and current_try < max_tries:
150
 
#            time.sleep(wait_for)
151
 
#            relation_data = json.loads(subprocess.check_output(relation_cmd_line))
152
 
#            current_try += 1
153
 
 
154
 
    except Exception, e:
155
 
        juju_log(str(e))
156
 
        relation_data = None
157
 
    finally:
158
 
        juju_log("relation_get returns: %s" % relation_data)
159
 
        return(relation_data)
160
 
 
161
 
 
162
 
#------------------------------------------------------------------------------
163
 
# relation_set:  Convenience function wrapping the juju command relation-set
164
 
#                Parameters:
165
 
#                key_value_pairs: A dictionary containing the key/value pairs
166
 
#                                 to be set.
167
 
#                Optional Parameter:
168
 
#                relation_id:  The relation id to use
169
 
#                Returns: True on success or False on failure
170
 
#------------------------------------------------------------------------------
171
 
def relation_set(key_value_pairs=None, relation_id=None):
172
 
    juju_log("relation_set: kv: %s, relation_id: %s" %
173
 
    (key_value_pairs, relation_id))
174
 
    if key_value_pairs is None or not isinstance(key_value_pairs, dict):
175
 
        juju_log("relation_set: Invalid key_value_pais.")
176
 
        return(False)
177
 
    try:
178
 
        relation_cmd_line = ['relation-set', '--format=json']
179
 
        if relation_id is not None:
180
 
            relation_cmd_line.append('-r %s' % relation_id)
181
 
        for (key, value) in key_value_pairs.items():
182
 
            relation_cmd_line.append('%s=%s' % (key, value))
183
 
        retVal = (subprocess.call(relation_cmd_line) == 0)
184
 
    except Exception, e:
185
 
        juju_log(str(e))
186
 
        retVal = False
187
 
    finally:
188
 
        juju_log("relation_set returns: %s" % retVal)
189
 
        return(retVal)
190
 
 
191
 
 
192
 
def relation_list(relation_id=None, wait_for=default_wait_for,
193
 
        max_tries=default_max_tries):
194
 
    juju_log("relation_list: relation_id: %s" % relation_id)
195
 
    current_try = 0
196
 
    try:
197
 
        relation_cmd_line = ['relation-list', '--format=json']
198
 
        if relation_id is not None:
199
 
            relation_cmd_line.append('-r %s' % relation_id)
200
 
        relation_data = json.loads(subprocess.check_output(relation_cmd_line))
201
 
 
202
 
#        while relation_data is None and current_try < max_tries:
203
 
#            time.sleep(wait_for)
204
 
#            relation_data = json.loads(subprocess.check_output(relation_cmd_line))
205
 
#            current_try += 1
206
 
 
207
 
    except Exception, e:
208
 
        juju_log(str(e))
209
 
        relation_data = None
210
 
    finally:
211
 
        juju_log("relation_id %s returns: %s" % (relation_id, relation_data))
212
 
        return(relation_data)
213
 
 
214
 
 
215
 
#------------------------------------------------------------------------------
216
 
# open_port:  Convenience function to open a port in juju to
217
 
#             expose a service
218
 
#------------------------------------------------------------------------------
219
 
def open_port(port=None, protocol="TCP"):
220
 
    juju_log("open_port: port: %d protocol: %s" % (int(port), protocol))
221
 
    if port is None:
222
 
        retVal = False
223
 
    else:
224
 
        retVal = subprocess.call(['open-port', "%d/%s" %
225
 
        (int(port), protocol)]) == 0
226
 
    juju_log("open_port %d/%s returns: %s" % (int(port), protocol, retVal))
227
 
    return(retVal)
228
 
 
229
 
 
230
 
#------------------------------------------------------------------------------
231
 
# close_port:  Convenience function to close a port in juju to
232
 
#              unexpose a service
233
 
#------------------------------------------------------------------------------
234
 
def close_port(port=None, protocol="TCP"):
235
 
    juju_log("close_port: port: %d protocol: %s" % (int(port), protocol))
236
 
    if port is None:
237
 
        retVal = False
238
 
    else:
239
 
        retVal = subprocess.call(['close-port', "%d/%s" %
240
 
        (int(port), protocol)]) == 0
241
 
    juju_log("close_port %d/%s returns: %s" % (int(port), protocol, retVal))
242
 
    return(retVal)
243
 
 
244
 
 
245
64
def port_check(host=None, port=None, protocol='TCP'):
246
65
    if host is None or port is None:
247
66
        juju_log("port_check: host and port must be defined.")
643
462
 
644
463
 
645
464
def configsvr_status(wait_for=default_wait_for, max_tries=default_max_tries):
646
 
    config_data = config_get()
 
465
    config_data = config()
647
466
    current_try = 0
648
467
    while (process_check_pidfile('/var/run/mongodb/configsvr.pid') !=
649
468
    (None, None)) and not port_check(
671
490
        juju_log("disable_configsvr: port not defined.")
672
491
        return(False)
673
492
    try:
674
 
        config_server_port = config_get('config_server_port')
 
493
        config_server_port = config('config_server_port')
675
494
        pid = open('/var/run/mongodb/configsvr.pid').read()
676
495
        os.kill(int(pid), signal.SIGTERM)
677
496
        os.unlink('/var/run/mongodb/configsvr.pid')
733
552
 
734
553
 
735
554
def mongos_status(wait_for=default_wait_for, max_tries=default_max_tries):
736
 
    config_data = config_get()
 
555
    config_data = config()
737
556
    current_try = 0
738
557
    while (process_check_pidfile('/var/run/mongodb/mongos.pid') !=
739
558
    (None, None)) and not port_check(
825
644
 
826
645
def restart_mongod(wait_for=default_wait_for, max_tries=default_max_tries):
827
646
    my_hostname = unit_get('public-address')
828
 
    my_port = config_get('port')
 
647
    my_port = config('port')
829
648
    current_try = 0
830
649
 
831
 
    service('mongodb', 'stop')
 
650
    service('stop', 'mongodb')
832
651
    if os.path.exists('/var/lib/mongodb/mongod.lock'):
833
652
        os.remove('/var/lib/mongodb/mongod.lock')
834
653
 
835
 
    if not service('mongodb', 'start'):
 
654
    if not service('start', 'mongodb'):
836
655
        return False
837
656
 
838
 
    while (service('mongodb', 'status') and
 
657
    while (service('status', 'mongodb') and
839
658
           not port_check(my_hostname, my_port) and
840
659
           current_try < max_tries):
841
660
        juju_log(
845
664
        current_try += 1
846
665
 
847
666
    return(
848
 
        (service('mongodb', 'status') == port_check(my_hostname, my_port))
 
667
        (service('status', 'mongodb') == port_check(my_hostname, my_port))
849
668
         is True)
850
669
 
851
670
 
852
671
def backup_cronjob(disable=False):
853
672
    """Generate the cronjob to backup with mongodbump."""
854
673
    juju_log('Setting up cronjob')
855
 
    config_data = config_get()
 
674
    config_data = config()
856
675
    backupdir = config_data['backup_directory']
857
676
    bind_ip = config_data['bind_ip']
858
677
    cron_file = '/etc/cron.d/mongodb'
912
731
def config_changed():
913
732
    juju_log("Entering config_changed")
914
733
    print "Entering config_changed"
915
 
    config_data = config_get()
 
734
    config_data = config()
916
735
    print "config_data: ", config_data
917
736
    mongodb_config = open(default_mongodb_config).read()
918
737
 
1054
873
def stop_hook():
1055
874
    juju_log("stop_hook")
1056
875
    try:
1057
 
        retVal = service('mongodb', 'stop')
 
876
        retVal = service('stop', 'mongodb')
1058
877
        os.remove('/var/lib/mongodb/mongod.lock')
1059
878
        #FIXME Need to check if this is still needed
1060
879
    except Exception, e:
1068
887
def database_relation_joined():
1069
888
    juju_log("database_relation_joined")
1070
889
    my_hostname = unit_get('public-address')
1071
 
    my_port = config_get('port')
1072
 
    my_replset = config_get('replicaset')
 
890
    my_port = config('port')
 
891
    my_replset = config('replicaset')
1073
892
    juju_log("my_hostname: %s" % my_hostname)
1074
893
    juju_log("my_port: %s" % my_port)
1075
894
    juju_log("my_replset: %s" % my_replset)
1076
895
    return(relation_set(
1077
896
        {
1078
 
            'hostname': my_hostname,
 
897
            'hostnme': my_hostname,
1079
898
            'port': my_port,
1080
899
            'replset': my_replset,
1081
900
            'type': 'database',
1085
904
def replica_set_relation_joined():
1086
905
    juju_log("replica_set_relation_joined")
1087
906
    my_hostname = unit_get('public-address')
1088
 
    my_port = config_get('port')
1089
 
    my_replset = config_get('replicaset')
 
907
    my_port = config('port')
 
908
    my_replset = config('replicaset')
1090
909
    my_install_order = os.environ['JUJU_UNIT_NAME'].split('/')[1]
1091
910
    juju_log("my_hostname: %s" % my_hostname)
1092
911
    juju_log("my_port: %s" % my_port)
1093
912
    juju_log("my_replset: %s" % my_replset)
1094
913
    juju_log("my_install_order: %s" % my_install_order)
1095
 
    return(enable_replset(my_replset) ==
1096
 
    restart_mongod() ==
1097
 
    relation_set(
1098
 
        {
1099
 
            'hostname': my_hostname,
1100
 
            'port': my_port,
1101
 
            'replset': my_replset,
1102
 
            'install-order': my_install_order,
1103
 
            'type': 'replset',
1104
 
        }))
 
914
    enabled = enable_replset(my_replset)
 
915
    restarted = restart_mongod()
 
916
 
 
917
    relation_set(None, {
 
918
        'hostname': my_hostname,
 
919
        'port': my_port,
 
920
        'replset': my_replset,
 
921
        'install-order': my_install_order,
 
922
        'type': 'replset',
 
923
        })
 
924
 
 
925
    if enabled and restarted:
 
926
        return True
 
927
    return False
1105
928
 
1106
929
 
1107
930
def replica_set_relation_changed():
1108
931
    juju_log("replica_set_relation_changed")
1109
932
    my_hostname = unit_get('public-address')
1110
 
    my_port = config_get('port')
 
933
    my_port = config('port')
1111
934
    my_install_order = os.environ['JUJU_UNIT_NAME'].split('/')[1]
1112
 
    my_replicaset_master = config_get('replicaset_master')
 
935
    my_replicaset_master = config('replicaset_master')
1113
936
 
1114
937
    # If we are joining an existing replicaset cluster, just join and leave.
1115
938
    if my_replicaset_master != "auto":
1121
944
    master_install_order = my_install_order
1122
945
 
1123
946
    # Check the nodes in the relation to find the master
1124
 
    for member in relation_list():
1125
 
        juju_log("replica_set_relation_changed: member: %s" % member)
1126
 
        hostname = relation_get('hostname', member)
1127
 
        port = relation_get('port', member)
1128
 
        install_order = relation_get('install-order', member)
 
947
    for member in relations_of_type('replica-set'):
 
948
        juju_log("replica_set_relation_changed: member: %s" % member['__unit__'])
 
949
        hostname = relation_get('hostname', member['__unit__'])
 
950
        port = relation_get('port', member['__unit__'])
 
951
        install_order = relation_get('install-order', member['__unit__'])
1129
952
        juju_log("replica_set_relation_changed: install_order: %s" % install_order)
1130
953
        if install_order is None:
1131
954
            juju_log("replica_set_relation_changed: install_order is None.  relation is not ready")
1139
962
    init_replset("%s:%s" % (master_hostname, master_port))
1140
963
 
1141
964
    # Add the rest of the nodes to the replset
1142
 
    for member in relation_list():
1143
 
        hostname = relation_get('hostname', member)
1144
 
        port = relation_get('port', member)
 
965
    for member in relations_of_type('replica-set'):
 
966
        hostname = relation_get('hostname', member['__unit__'])
 
967
        port = relation_get('port', member['__unit__'])
1145
968
        if master_hostname != hostname:
1146
969
            if hostname == my_hostname:
1147
970
                subprocess.call(['mongo',
1156
979
        join_replset("%s:%s" % (master_hostname, master_port),
1157
980
            "%s:%s" % (my_hostname, my_port))
1158
981
 
 
982
    # should this always return true?
1159
983
    return(True)
1160
984
 
1161
985
 
1162
986
def configsvr_relation_joined():
1163
987
    juju_log("configsvr_relation_joined")
1164
988
    my_hostname = unit_get('public-address')
1165
 
    my_port = config_get('config_server_port')
 
989
    my_port = config('config_server_port')
1166
990
    my_install_order = os.environ['JUJU_UNIT_NAME'].split('/')[1]
1167
991
    return(relation_set(
1168
992
        {
1175
999
 
1176
1000
def configsvr_relation_changed():
1177
1001
    juju_log("configsvr_relation_changed")
1178
 
    config_data = config_get()
 
1002
    config_data = config()
1179
1003
    my_port = config_data['config_server_port']
1180
1004
    disable_configsvr(my_port)
1181
1005
    retVal = enable_configsvr(config_data)
1186
1010
def mongos_relation_joined():
1187
1011
    juju_log("mongos_relation_joined")
1188
1012
    my_hostname = unit_get('public-address')
1189
 
    my_port = config_get('mongos_port')
 
1013
    my_port = config('mongos_port')
1190
1014
    my_install_order = os.environ['JUJU_UNIT_NAME'].split('/')[1]
1191
1015
    return(relation_set(
1192
1016
        {
1199
1023
 
1200
1024
def mongos_relation_changed():
1201
1025
    juju_log("mongos_relation_changed")
1202
 
    config_data = config_get()
 
1026
    config_data = config()
1203
1027
    retVal = False
1204
 
    for member in relation_list():
 
1028
    for member in relation_for_id():
1205
1029
        hostname = relation_get('hostname', member)
1206
1030
        port = relation_get('port', member)
1207
1031
        rel_type = relation_get('type', member)
1226
1050
            if mongos_ready():
1227
1051
                mongos_host = "%s:%s" % (
1228
1052
                    unit_get('public-address'),
1229
 
                    config_get('mongos_port'))
 
1053
                    config('mongos_port'))
1230
1054
                shard_command1 = "sh.addShard(\"%s:%s\")" % (hostname, port)
1231
1055
                retVal1 = mongo_client(mongos_host, shard_command1)
1232
1056
                replicaset = relation_get('replset', member)
1244
1068
 
1245
1069
def mongos_relation_broken():
1246
1070
#    config_servers = load_config_servers(default_mongos_list)
1247
 
#    for member in relation_list():
 
1071
#    for member in relation_for_id():
1248
1072
#        hostname = relation_get('hostname', member)
1249
1073
#        port = relation_get('port', member)
1250
1074
#        if '%s:%s' % (hostname, port) in config_servers:
1277
1101
#
1278
1102
#------------------------------
1279
1103
def volume_get_volid_from_volume_map():
1280
 
    config_data = config_get()
 
1104
    config_data = config()
1281
1105
    volume_map = {}
1282
1106
    try:
1283
1107
        volume_map = yaml.load(config_data['volume-map'].strip())
1316
1140
# @returns  volid
1317
1141
#           None    config state is invalid - we should not serve
1318
1142
def volume_get_volume_id():
1319
 
    config_data = config_get()
 
1143
    config_data = config()
1320
1144
    ephemeral_storage = config_data['volume-ephemeral-storage']
1321
1145
    volid = volume_get_volid_from_volume_map()
1322
1146
    juju_unit_name = os.environ['JUJU_UNIT_NAME']
1367
1191
#     - manipulate /var/lib/mongodb/VERSION/CLUSTER symlink
1368
1192
#------------------------------------------------------------------------------
1369
1193
def config_changed_volume_apply():
1370
 
    config_data = config_get()
 
1194
    config_data = config()
1371
1195
    data_directory_path = config_data["dbpath"]
1372
1196
    assert(data_directory_path)
1373
1197
    volid = volume_get_volume_id()