Merge lp:~adalbas/ibmcharms/gpfs-config into lp:ibmcharms
- gpfs-config
- Merge into devel
Proposed by
Adalberto Medeiros
Status: | Merged |
---|---|
Merged at revision: | 27 |
Proposed branch: | lp:~adalbas/ibmcharms/gpfs-config |
Merge into: | lp:ibmcharms |
Diff against target: |
482 lines (+167/-64) 10 files modified
charms/trusty/gpfs/README.md (+5/-1) charms/trusty/gpfs/config.yaml (+6/-0) charms/trusty/gpfs/hooks/common-relation-changed (+5/-3) charms/trusty/gpfs/hooks/common-relation-joined (+6/-3) charms/trusty/gpfs/hooks/config-changed (+35/-2) charms/trusty/gpfs/hooks/gpfshooklib.py (+90/-12) charms/trusty/gpfs/hooks/install (+18/-42) charms/trusty/gpfs/hooks/start (+1/-0) charms/trusty/gpfs/hooks/stop (+1/-0) charms/trusty/gpfs/tests/10-deploy (+0/-1) |
To merge this branch: | bzr merge lp:~adalbas/ibmcharms/gpfs-config |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Chase-Salerno | Approve | ||
Review via email: mp+251319@code.launchpad.net |
Commit message
Description of the change
Add install to gpfshooklib.py
Add config-changed. Installation is done here if gpfs_url was not set before.
Add unit test. Still not fully tested
To post a comment you must log in.
- 27. By Adalberto Medeiros
-
Changes on installation for config-changed
- 28. By Adalberto Medeiros
-
Merge with dnsfixes
- 29. By Adalberto Medeiros
-
Fix pep8
- 30. By Adalberto Medeiros
-
merge tests
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'charms/trusty/gpfs/README.md' |
2 | --- charms/trusty/gpfs/README.md 2015-01-27 12:40:23 +0000 |
3 | +++ charms/trusty/gpfs/README.md 2015-03-09 15:35:58 +0000 |
4 | @@ -30,13 +30,17 @@ |
5 | Configure config.yaml with the repository url |
6 | |
7 | gpfs_url: "http://<server-name>/debs/gpfs4.1" |
8 | - **Packages.gz should be on the same directory as the packages. The install hook will add Linux/x86_64 to the URL |
9 | + **Packages.gz should be on the same directory as the packages. The install hook will add Linux/x86_64 to the URL** |
10 | |
11 | +You can also set gpfs_url with "juju set" after deploy the charm |
12 | ## Deploy |
13 | |
14 | juju deploy gpfs gpfs-manager |
15 | juju deploy gpfs gpfs-client |
16 | |
17 | + # If gpfs_url is not set |
18 | + juju set gpfs-manager gpfs_url="http://<server-name>/debs/gpfs4.1" |
19 | + |
20 | juju add relation gpfs-manager:manager gpfs-client:client |
21 | |
22 | # Configuration |
23 | |
24 | === modified file 'charms/trusty/gpfs/config.yaml' |
25 | --- charms/trusty/gpfs/config.yaml 2015-01-27 12:19:54 +0000 |
26 | +++ charms/trusty/gpfs/config.yaml 2015-03-09 15:35:58 +0000 |
27 | @@ -11,3 +11,9 @@ |
28 | type: string |
29 | default: "4.1" |
30 | description: "Version of GPFS" |
31 | + quorum: |
32 | + type: string |
33 | + default: "quorum" |
34 | + description: > |
35 | + Designation for nodes. Values can be quorum, |
36 | + non-quorum or empty string (this assumes non-quorum) |
37 | |
38 | === modified file 'charms/trusty/gpfs/hooks/common-relation-changed' |
39 | --- charms/trusty/gpfs/hooks/common-relation-changed 2015-03-03 17:57:57 +0000 |
40 | +++ charms/trusty/gpfs/hooks/common-relation-changed 2015-03-09 15:35:58 +0000 |
41 | @@ -24,13 +24,15 @@ |
42 | rlhn = hookenv.relation_get(attribute='lhostname', unit=runit, rid=relid) |
43 | llhn = socket.getfqdn() |
44 | if not rlhn is None: |
45 | - gpfshooklib.chk_dns(rlhn,rip) |
46 | + gpfshooklib.chk_dns(rlhn, rip) |
47 | |
48 | if hookname == "client-relation-changed": |
49 | # Save the keypair from the manager |
50 | log("Copying keys to client") |
51 | - pubkey = hookenv.relation_get(attribute='pubkey', unit=runit, rid=relid) |
52 | - privkey = hookenv.relation_get(attribute='privkey', unit=runit, rid=relid) |
53 | + pubkey = hookenv.relation_get(attribute='pubkey', unit=runit, |
54 | + rid=relid) |
55 | + privkey = hookenv.relation_get(attribute='privkey', unit=runit, |
56 | + rid=relid) |
57 | gpfshooklib.set_ssh_key(pubkey, private=False) |
58 | gpfshooklib.set_ssh_key(privkey, private=True) |
59 | if hookname == "manager-relation-changed" and not rlhn is None: |
60 | |
61 | === modified file 'charms/trusty/gpfs/hooks/common-relation-joined' |
62 | --- charms/trusty/gpfs/hooks/common-relation-joined 2015-03-03 17:57:57 +0000 |
63 | +++ charms/trusty/gpfs/hooks/common-relation-joined 2015-03-09 15:35:58 +0000 |
64 | @@ -12,6 +12,7 @@ |
65 | ) |
66 | |
67 | log = hookenv.log |
68 | +config = hookenv.config() |
69 | |
70 | |
71 | def main(): |
72 | @@ -34,11 +35,13 @@ |
73 | }) |
74 | if hookname == "client-relation-joined": |
75 | # Set the node designation values and hostname |
76 | + quorum = gpfshooklib.validate_quorum(config.get('quorum')) |
77 | hookenv.relation_set(hookenv.relation_id(), { |
78 | - 'quorum': 'quorum', |
79 | + 'hostname': socket.gethostname(), |
80 | + 'quorum': quorum, |
81 | 'client': 'client' |
82 | - }) |
83 | - |
84 | + }) |
85 | + |
86 | # Configure sshd to allow root ssh |
87 | # Avoid the host key confirmation (all relation-joined) |
88 | gpfshooklib.configure_ssh() |
89 | |
90 | === modified file 'charms/trusty/gpfs/hooks/config-changed' |
91 | --- charms/trusty/gpfs/hooks/config-changed 2015-01-21 19:48:09 +0000 |
92 | +++ charms/trusty/gpfs/hooks/config-changed 2015-03-09 15:35:58 +0000 |
93 | @@ -9,8 +9,7 @@ |
94 | hookenv, |
95 | host, |
96 | ) |
97 | - |
98 | -#from start import start |
99 | +import gpfshooklib |
100 | |
101 | hooks = hookenv.Hooks() |
102 | log = hookenv.log |
103 | @@ -22,15 +21,49 @@ |
104 | def config_changed(): |
105 | config = hookenv.config() |
106 | |
107 | + install_bool = False |
108 | for key in config: |
109 | if config.changed(key): |
110 | log("config['{}'] changed from {} to {}".format( |
111 | key, config.previous(key), config[key])) |
112 | + if key in ['gpfs_url', 'version', 'update']: |
113 | + install_bool = True |
114 | + |
115 | + # If installation configuration has changed, reinstall gpfs |
116 | + log("Installation: %s" % install_bool) |
117 | + gpfs_url = config['gpfs_url'] |
118 | + version = config['version'] |
119 | + update = config['update'] |
120 | + |
121 | + # exit if there is no source |
122 | + gpfshooklib.check_empty_source(gpfs_url) |
123 | + # If source changed, install packages from new source |
124 | + if install_bool: |
125 | + install_gpfs(gpfs_url, version, update) |
126 | + |
127 | + # if quorum changed, change node designation |
128 | + if config.changed('quorum'): |
129 | + unit = hookenv.local_unit() |
130 | + quorum = config.get('quorum') |
131 | + change_node_designation(unit, quorum) |
132 | |
133 | config.save() |
134 | #start.start() |
135 | |
136 | |
137 | +def install_gpfs(gpfs_url, version, update): |
138 | + # install gpfs |
139 | + |
140 | + gpfshooklib.gpfs_install(gpfs_url, version) |
141 | + gpfshooklib.gpfs_install_updates(gpfs_url, version, update) |
142 | + gpfshooklib.build_modules() |
143 | + |
144 | + |
145 | +def change_node_designation(unit, quorum='quorum'): |
146 | + # TODO, change unit designation to quorum or non-quorum |
147 | + pass |
148 | + |
149 | + |
150 | if __name__ == "__main__": |
151 | # execute a hook based on the name the program is called by |
152 | hooks.execute(sys.argv) |
153 | |
154 | === modified file 'charms/trusty/gpfs/hooks/gpfshooklib.py' |
155 | --- charms/trusty/gpfs/hooks/gpfshooklib.py 2015-03-03 17:57:57 +0000 |
156 | +++ charms/trusty/gpfs/hooks/gpfshooklib.py 2015-03-09 15:35:58 +0000 |
157 | @@ -7,24 +7,75 @@ |
158 | import tempfile |
159 | import socket |
160 | from shlex import split |
161 | +import subprocess |
162 | from subprocess import ( |
163 | call, |
164 | check_call, |
165 | - check_output |
166 | + check_output, |
167 | + Popen, |
168 | + CalledProcessError |
169 | ) |
170 | |
171 | sys.path.insert(0, os.path.join(os.environ['CHARM_DIR'], 'lib')) |
172 | |
173 | +from charmhelpers import fetch |
174 | from charmhelpers.core import ( |
175 | hookenv, |
176 | ) |
177 | log = hookenv.log |
178 | |
179 | +GPFS_PATH = '/Linux/x86_64' |
180 | + |
181 | + |
182 | def add_to_path(p, new): |
183 | return p if new in p.split(':') else p + ':' + new |
184 | |
185 | os.environ['PATH'] = add_to_path(os.environ['PATH'], '/usr/lpp/mmfs/bin') |
186 | |
187 | + |
188 | +## installation methods ## |
189 | +def _get_source(url, source_dir=""): |
190 | + return "deb %s%s ./" % (url, source_dir) |
191 | + |
192 | + |
193 | +def check_empty_source(gpfs_url): |
194 | + # Check if there is a repository to install from |
195 | + # TODO: check if packages are already installed |
196 | + if not gpfs_url: |
197 | + log("No GPFS source available. Use juju set gpfs gpfs_url=<url> " |
198 | + "to install packages. See README for more info.", log.ERROR) |
199 | + sys.exit(0) |
200 | + |
201 | + |
202 | +def gpfs_install(url, version): |
203 | + # install main gpfs packages |
204 | + gpfs_source = _get_source(url, source_dir=GPFS_PATH) |
205 | + log('Gpfs source' + gpfs_source) |
206 | + |
207 | + # Add gpfs source and update apt |
208 | + fetch.add_source(gpfs_source) |
209 | + try: |
210 | + fetch.apt_update(fatal=True) |
211 | + # Install gpfs packages |
212 | + fetch.apt_install("gpfs*", options=["--allow-unauthenticated"], |
213 | + fatal=True) |
214 | + except CalledProcessError: |
215 | + #TODO: verify source was configured correctly |
216 | + raise |
217 | + |
218 | + |
219 | +def gpfs_install_updates(url, version, update=True): |
220 | + # install update packages (patches), if given |
221 | + if update: |
222 | + log('Applying patches') |
223 | + source_dir = '/gpfs' + version + '_patches' + GPFS_PATH |
224 | + patch_source = _get_source(url, source_dir=source_dir) |
225 | + fetch.add_source(patch_source) |
226 | + fetch.apt_update(fatal=True) |
227 | + fetch.apt_install("gpfs*", options=["--allow-unauthenticated"], |
228 | + fatal=True) |
229 | + |
230 | + |
231 | ## ssh key methods ## |
232 | def create_ssh_keys(): |
233 | # Generate ssh keys if needed |
234 | @@ -34,7 +85,8 @@ |
235 | # Ensure permissions are good |
236 | os.chmod('/root/.ssh/id_rsa.pub', 0600) |
237 | os.chmod('/root/.ssh/id_rsa', 0600) |
238 | - |
239 | + |
240 | + |
241 | def get_ssh_keys(): |
242 | # get public and private ssh keys |
243 | with open("/root/.ssh/id_rsa.pub", "r") as idfile: |
244 | @@ -48,9 +100,10 @@ |
245 | idfile.close() |
246 | return [privkey, pubkey] |
247 | |
248 | + |
249 | def set_ssh_key(key, private=False): |
250 | if key: |
251 | - if private == False: |
252 | + if private is False: |
253 | f = open("/root/.ssh/id_rsa.pub", "w") |
254 | f.write(key) |
255 | f.close() |
256 | @@ -65,6 +118,7 @@ |
257 | f.close() |
258 | os.chmod('/root/.ssh/id_rsa', 0600) |
259 | |
260 | + |
261 | def configure_ssh(): |
262 | # Configure sshd_config file to allow root |
263 | sshconf = open("/etc/ssh/sshd_config", 'r') |
264 | @@ -91,53 +145,78 @@ |
265 | idfile.write("StrictHostKeyChecking no\n") |
266 | idfile.close() |
267 | |
268 | + |
269 | +## Other utility methods## |
270 | +def validate_quorum(quorum): |
271 | + valid_values = ['', 'quorum', 'non-quorum'] |
272 | + return quorum if quorum in valid_values else '' |
273 | + |
274 | + |
275 | ## cluster management methods ## |
276 | +def build_modules(): |
277 | +# build binary gpfs modules after installation |
278 | + try: |
279 | + check_call(["mmbuildgpl"]) |
280 | + except CalledProcessError: |
281 | + log('mmbuildgpl was not executed', level=hookenv.WARNING) |
282 | + except OSError: |
283 | + log('mmbuildgpl not found/installed') |
284 | + |
285 | |
286 | def start(): |
287 | # Only manager can start/stop cluster |
288 | if is_manager(): |
289 | log(check_output(split('mmstartup -a'))) |
290 | |
291 | + |
292 | def stop(): |
293 | # stop the server |
294 | if is_manager(): |
295 | check_output(split('mmshutdown -a')) |
296 | |
297 | + |
298 | def node_exists(nodename): |
299 | # Check if node has already been added to cluster |
300 | lscluster = check_output('mmlscluster') |
301 | node = re.search('^.*\d+.*%s.*\n' % nodename, lscluster, re.M) |
302 | return False if node is None else True |
303 | |
304 | + |
305 | def add_node(nodename, m_designation='client', q_designation='nonquorum'): |
306 | # add new node to the cluster |
307 | if cluster_exists() and not node_exists(nodename): |
308 | - log(check_output(split('mmaddnode -N %s:%s-%s' % \ |
309 | - (nodename, m_designation, q_designation)))) |
310 | + log(check_output(split('mmaddnode -N %s:%s-%s' % |
311 | + (nodename, m_designation, q_designation)))) |
312 | else: |
313 | log('Node %s could not be added. Manager not defined' % nodename) |
314 | - |
315 | + |
316 | + |
317 | def apply_license(nodename): |
318 | check_output(split('mmchlicense server --accept -N %s' % nodename)) |
319 | |
320 | + |
321 | def set_manager_file(): |
322 | # define a file that indicates the node is a manager |
323 | - open("/var/mmfs/.manager","a").close() |
324 | + open("/var/mmfs/.manager", "a").close() |
325 | + |
326 | |
327 | def is_manager(): |
328 | # check if the node is a manager |
329 | if os.path.exists("/var/mmfs/.manager"): |
330 | return True |
331 | |
332 | + |
333 | def cluster_exists(): |
334 | # Check if cluster is already defined |
335 | return True if call('mmlscluster') == 0 else False |
336 | - |
337 | + |
338 | + |
339 | def create_cluster(hostname): |
340 | # create the cluster for the hostname, manager only |
341 | if is_manager() and not cluster_exists(): |
342 | - log(check_output(split('mmcrcluster -N %s:quorum-manager' % \ |
343 | - hostname + ' -r /usr/bin/ssh -R /usr/bin/scp'))) |
344 | + log(check_output(split('mmcrcluster -N %s:quorum-manager' % |
345 | + hostname + ' -r /usr/bin/ssh -R /usr/bin/scp'))) |
346 | + |
347 | |
348 | def chk_dns(hostname, ip): |
349 | try: |
350 | @@ -145,6 +224,5 @@ |
351 | except: |
352 | log("Hostname not resolving, adding to /etc/hosts") |
353 | with open("/etc/hosts", "a") as hostfile: |
354 | - hostfile.write("%s %s\n" % (ip, hostname) ) |
355 | + hostfile.write("%s %s\n" % (ip, hostname)) |
356 | hostfile.close() |
357 | - |
358 | |
359 | === modified file 'charms/trusty/gpfs/hooks/install' |
360 | --- charms/trusty/gpfs/hooks/install 2015-02-09 11:42:31 +0000 |
361 | +++ charms/trusty/gpfs/hooks/install 2015-03-09 15:35:58 +0000 |
362 | @@ -11,66 +11,42 @@ |
363 | hookenv, |
364 | ) |
365 | |
366 | +import gpfshooklib |
367 | + |
368 | hooks = hookenv.Hooks() |
369 | log = hookenv.log |
370 | config = hookenv.config() |
371 | |
372 | -SERVICE = 'gpfs' |
373 | - |
374 | +# development packages needed to build kernel modules for GPFS cluster |
375 | PREREQS = ["ksh", "binutils", "m4", "libaio1", "g++", "cpp", "make", "gcc"] |
376 | -# TODO: gpfs.msg.en_us - change it to any language |
377 | -GPFS_PKGS = ["gpfs.base", "gpfs.crypto", "gpfs.docs", "gpfs.ext", |
378 | - "gpfs.gpl", "gpfs.gski", "gpfs.msg.en_us"] |
379 | -GPFS_PATH = '/Linux/x86_64' |
380 | + |
381 | |
382 | @hooks.hook('install') |
383 | def install(): |
384 | log('Installing gpfs') |
385 | |
386 | # Things that need to happen here |
387 | - # Fetch GPFS packages from user given location? |
388 | gpfs_url = config.get('gpfs_url') |
389 | version = config.get('version') |
390 | update = config.get('update') # boolean value whether to apply patches |
391 | |
392 | - gpfs_source = get_source(gpfs_url, source_dir=GPFS_PATH) |
393 | - log('Gpfs source' + gpfs_source) |
394 | - |
395 | - # Add gpfs source and update apt |
396 | - fetch.add_source(gpfs_source) |
397 | - fetch.apt_update() |
398 | - # Apt install prereqs |
399 | - fetch.apt_install(PREREQS) |
400 | - # install kernel prereq |
401 | + # install kernel prereq and other prereqs |
402 | linux_headers = "linux-headers-%s" % get_kernel_version() |
403 | - fetch.apt_install(linux_headers) |
404 | - |
405 | - # Install gpfs packages |
406 | - fetch.apt_install("gpfs*", options=["--allow-unauthenticated"]) |
407 | - |
408 | - # Apply patch packages |
409 | - if update: |
410 | - log('Applying patches') |
411 | - source_dir = '/gpfs' + version + '_patches' + GPFS_PATH |
412 | - patch_source = get_source(gpfs_url, source_dir=source_dir) |
413 | - fetch.add_source(patch_source) |
414 | - fetch.apt_update() |
415 | - fetch.apt_install("gpfs*", options=["--allow-unauthenticated"]) |
416 | - |
417 | - # Build binary modules |
418 | - os.environ['PATH'] += (':/usr/lpp/mmfs/bin') |
419 | - try: |
420 | - subprocess.check_call(["mmbuildgpl"]) |
421 | - except subprocess.CalledProcessError: |
422 | - log('mmbuildgpl was not executed', level=hookenv.WARNING) |
423 | - except OSError: |
424 | - log('mmbuildgpl not found/installed') |
425 | - |
426 | -def get_source(url, source_dir=""): |
427 | - return "deb %s%s ./" % (url,source_dir) |
428 | + fetch.apt_install(PREREQS + [linux_headers]) |
429 | + |
430 | + if gpfs_url == "": |
431 | + log("""No GPFS source packages. Use juju set gpfs gpfs_url=<url> |
432 | + to install packages. See README for more info""", |
433 | + level=hookenv.ERROR) |
434 | + sys.exit(0) |
435 | + |
436 | + gpfshooklib.gpfs_install(gpfs_url, version) |
437 | + gpfshooklib.gpfs_install_updates(gpfs_url, version, update) |
438 | + gpfshooklib.build_modules() |
439 | + |
440 | |
441 | def get_kernel_version(): |
442 | - return subprocess.check_output(['uname','-r']).strip() |
443 | + return subprocess.check_output(['uname', '-r']).strip() |
444 | |
445 | if __name__ == "__main__": |
446 | # execute a hook based on the name the program is called by |
447 | |
448 | === modified file 'charms/trusty/gpfs/hooks/start' |
449 | --- charms/trusty/gpfs/hooks/start 2015-02-10 02:11:55 +0000 |
450 | +++ charms/trusty/gpfs/hooks/start 2015-03-09 15:35:58 +0000 |
451 | @@ -15,6 +15,7 @@ |
452 | hooks = hookenv.Hooks() |
453 | log = hookenv.log |
454 | |
455 | + |
456 | @hooks.hook('start') |
457 | def start(): |
458 | log("Starting cluster (manager only)") |
459 | |
460 | === modified file 'charms/trusty/gpfs/hooks/stop' |
461 | --- charms/trusty/gpfs/hooks/stop 2015-02-10 02:11:55 +0000 |
462 | +++ charms/trusty/gpfs/hooks/stop 2015-03-09 15:35:58 +0000 |
463 | @@ -14,6 +14,7 @@ |
464 | hooks = hookenv.Hooks() |
465 | log = hookenv.log |
466 | |
467 | + |
468 | @hooks.hook('stop') |
469 | def stop(): |
470 | gpfshooklib.stop() |
471 | |
472 | === modified file 'charms/trusty/gpfs/tests/10-deploy' |
473 | --- charms/trusty/gpfs/tests/10-deploy 2015-03-09 15:24:07 +0000 |
474 | +++ charms/trusty/gpfs/tests/10-deploy 2015-03-09 15:35:58 +0000 |
475 | @@ -25,7 +25,6 @@ |
476 | |
477 | unit_manager_0 = d.sentry.unit['gpfs/0'] |
478 | unit_client_0 = d.sentry.unit['gpfs-client/0'] |
479 | - |
480 | print(unit_manager_0.info) |
481 | |
482 | # verify unit_manager is manager |
Looks good to me.