Merge lp:~wesmason/charms/precise/mongodb/add-storage-subordinate-support into lp:charms/mongodb

Proposed by Wes Mason
Status: Merged
Merged at revision: 49
Proposed branch: lp:~wesmason/charms/precise/mongodb/add-storage-subordinate-support
Merge into: lp:charms/mongodb
Diff against target: 206 lines (+98/-4)
4 files modified
README.md (+18/-2)
config.yaml (+4/-1)
hooks/hooks.py (+72/-1)
metadata.yaml (+4/-0)
To merge this branch: bzr merge lp:~wesmason/charms/precise/mongodb/add-storage-subordinate-support
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Review via email: mp+223539@code.launchpad.net

Description of the change

This adds support for the storage subordinate as a way to automatically handle attaching/mounting volumes from both OpenStack and AWS EBS, by using the data- relation hooks to setup a /srv/juju/mongodb-data mount which is then used by the existing volume management code to symlink in place and rsync any existing MongoDB data over, similar to the way the postgres charm works with the subordinate.

We need this internally to support automated Mongo-on-persistent-volume deploys with juju-deployer.

To post a comment you must log in.
Revision history for this message
Wes Mason (wesmason) wrote :

Bug 1206468 is related to this.

Revision history for this message
Stuart Bishop (stub) wrote :

This all seems good to me.

The charm could be tidied up with support of charmhelpers, eg. using @hooks.hook instead of the if/then statement to invoke the correct hook handler. But that is unrelated to this branch, which is nicely contained and doesn't want the scope creep.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.md'
2--- README.md 2014-02-19 15:47:55 +0000
3+++ README.md 2014-06-18 11:23:00 +0000
4@@ -164,10 +164,26 @@
5 - `run sh.status()`
6 You should see your the hosts for your shards in the status output.
7
8+### Use the storage subordinate to store mongodb data on a permanent OpenStack or Amazon EBS volume
9+
10+The [storage](http://manage.jujucharms.com/charms/precise/storage) subordinate and [block-storage-broker](http://manage.jujucharms.com/charms/precise/block-storage-broker) service can automatically handle attaching the volume and mounting it to the unit before MongoDB is setup to use it.
11+
12+For example if you've created the volumes `vol-id-00001` and `vol-id-00002` and want to attach them to your 2 mongo units, with your OpenStack or AWS credentials in a `credential.yaml` file:
13+
14+ juju deploy block-storage-broker --config credentials.yaml
15+ juju deploy storage
16+ juju add-relation block-storage-broker storage
17+ juju set storage provider=block-storage-broker
18+ juju set volume_map="{mongodb/0: vol-id-00001, mongodb/1: vol-id-00002}"
19+ juju add-relation storage mongodb
20+
21+
22+### Use a permanent Openstack volume to store mongodb data. (DEPRECATED)
23+
24+**Note**: Although these steps will still work they are now deprecated, you should use the storage subordinate above instead.
25+
26 To deploy mongodb using permanent volume on Openstack, the permanent volume should be attached to the mongodb unit just after the deployment, then the configuration should be updated like follows.
27
28-### Use a permanent Openstack volume to store mongodb data.
29-
30 juju set mongodb volume-dev-regexp="/dev/vdc" volume-map='{"mongodb/0": "vol-id-00000000000000"}' volume-ephemeral-storage=false
31
32 ### Backups
33
34=== modified file 'config.yaml'
35--- config.yaml 2014-04-11 21:00:49 +0000
36+++ config.yaml 2014-06-18 11:23:00 +0000
37@@ -168,7 +168,7 @@
38 type: int
39 description: "Number of backups to keep. Keeps one week's worth by default."
40 #------------------------------------------------------------------------
41- # Volume management
42+ # Legacy volume management (DEPRECATED)
43 # volume-map, volume-dev_regexp are only used
44 # if volume-ephemeral-storage == False
45 #------------------------------------------------------------------------
46@@ -176,6 +176,7 @@
47 type: boolean
48 default: true
49 description: >
50+ Deprecated, use the storage subordinate.
51 If false, a configure-error state will be raised if
52 volume-map[$JUJU_UNIT_NAME] is not set (see "volume-map"
53 below) - see "volume-map" below.
54@@ -187,6 +188,7 @@
55 type: string
56 default: ""
57 description: >
58+ Deprecated, use the storage subordinate.
59 YAML map as e.g. "{ mongodb/0: vol-0000010, mongodb/1: vol-0000016 }".
60 Service units will raise a "configure-error" condition if no volume-map
61 value is set for it - it expects a human to set it properly to resolve it.
62@@ -194,6 +196,7 @@
63 type: string
64 default: "/dev/vd[b-z]"
65 description: >
66+ Deprecated, use the storage subordinate.
67 Block device for attached volumes as seen by the VM, will be "scanned"
68 for an unused device when "volume-map" is valid for the unit.
69 source:
70
71=== added symlink 'hooks/data-relation-changed'
72=== target is u'hooks.py'
73=== added symlink 'hooks/data-relation-departed'
74=== target is u'hooks.py'
75=== added symlink 'hooks/data-relation-joined'
76=== target is u'hooks.py'
77=== modified file 'hooks/hooks.py'
78--- hooks/hooks.py 2014-04-11 21:00:49 +0000
79+++ hooks/hooks.py 2014-06-18 11:23:00 +0000
80@@ -212,6 +212,20 @@
81 return(relation_data)
82
83
84+def relation_ids(relation_name=None):
85+ juju_log("relation_ids: relation_name: %s" % relation_name)
86+ try:
87+ relation_cmd_line = ['relation-ids', '--format=json']
88+ if relation_name is not None:
89+ relation_cmd_line.append(relation_name)
90+ relation_data = json.loads(subprocess.check_output(relation_cmd_line))
91+ except Exception, e:
92+ juju_log(str(e))
93+ relation_data = None
94+ finally:
95+ juju_log("relation_ids %s returns: %s" % (relation_name, relation_data))
96+ return(relation_data)
97+
98 #------------------------------------------------------------------------------
99 # open_port: Convenience function to open a port in juju to
100 # expose a service
101@@ -930,7 +944,7 @@
102 "'volume-ephemeral-storage' and 'volume-map'")
103 sys.exit(1)
104 if volume_is_permanent(volid):
105- ## config_changed_volume_apply will stop the service if it founds
106+ ## config_changed_volume_apply will stop the service if it finds
107 ## it necessary, ie: new volume setup
108 if config_changed_volume_apply():
109 start_hook()
110@@ -1159,6 +1173,30 @@
111 return(True)
112
113
114+def data_relation_joined():
115+ juju_log("data_relation_joined")
116+
117+ return(relation_set(
118+ {
119+ 'mountpoint': '/srv/juju/mongodb-data'
120+ }))
121+
122+
123+def data_relation_changed():
124+ juju_log("data_relation_changed")
125+
126+ if volume_get_id_for_storage_subordinate() is None:
127+ juju_log("mountpoint from storage subordinate not ready, let's wait")
128+ return(True)
129+
130+ return(config_changed())
131+
132+
133+def data_relation_departed():
134+ juju_log("data_relation_departed")
135+ return(config_changed())
136+
137+
138 def configsvr_relation_joined():
139 juju_log("configsvr_relation_joined")
140 my_hostname = unit_get('public-address')
141@@ -1312,10 +1350,37 @@
142 return None
143
144
145+#------------------------------
146+# Returns a stub volume id based on the mountpoint from the storage
147+# subordinate relation, if present.
148+#
149+# @return volid eg vol-000012345
150+#------------------------------
151+def volume_get_id_for_storage_subordinate():
152+ # storage charm is a subordinate so we should only ever have one
153+ # relation_id for the data relation
154+ ids = relation_ids('data')
155+ if len(ids) > 0:
156+ mountpoint = relation_get('mountpoint',
157+ os.environ['JUJU_UNIT_NAME'],
158+ ids[0])
159+
160+ juju_log('mountpoint: %s' % (mountpoint,))
161+ if mountpoint and os.path.exists(mountpoint):
162+ return mountpoint.split('/')[-1]
163+
164+
165+
166 # Do we have a valid storage state?
167 # @returns volid
168 # None config state is invalid - we should not serve
169 def volume_get_volume_id():
170+
171+
172+ volid = volume_get_id_for_storage_subordinate()
173+ if volid:
174+ return volid
175+
176 config_data = config_get()
177 ephemeral_storage = config_data['volume-ephemeral-storage']
178 volid = volume_get_volid_from_volume_map()
179@@ -1520,6 +1585,12 @@
180 retVal = mongos_relation_changed()
181 elif hook_name == "mongos-relation-broken":
182 retVal = mongos_relation_broken()
183+ elif hook_name == "data-relation-joined":
184+ retVal = data_relation_joined()
185+ elif hook_name == "data-relation-changed":
186+ retVal = data_relation_changed()
187+ elif hook_name == "data-relation-departed":
188+ retVal = data_relation_departed()
189 else:
190 print "Unknown hook"
191 retVal = False
192
193=== modified file 'metadata.yaml'
194--- metadata.yaml 2014-01-09 20:41:59 +0000
195+++ metadata.yaml 2014-06-18 11:23:00 +0000
196@@ -22,6 +22,10 @@
197 interface: mongodb
198 configsvr:
199 interface: shard
200+ data:
201+ interface: block-storage
202+ scope: container
203+ optional: true
204 requires:
205 mongos-cfg:
206 interface: shard

Subscribers

People subscribed via source and target branches