Merge lp:~gnuoy/charms/trusty/nova-compute/stable-charm-sync into lp:~openstack-charmers-archive/charms/trusty/nova-compute/trunk

Proposed by Liam Young
Status: Merged
Merged at revision: 72
Proposed branch: lp:~gnuoy/charms/trusty/nova-compute/stable-charm-sync
Merge into: lp:~openstack-charmers-archive/charms/trusty/nova-compute/trunk
Diff against target: 311 lines (+165/-13)
8 files modified
.bzrignore (+2/-0)
Makefile (+7/-2)
hooks/charmhelpers/contrib/openstack/context.py (+9/-4)
hooks/charmhelpers/contrib/storage/linux/utils.py (+4/-0)
hooks/charmhelpers/core/fstab.py (+116/-0)
hooks/charmhelpers/core/host.py (+24/-6)
hooks/charmhelpers/fetch/__init__.py (+1/-0)
hooks/charmhelpers/fetch/bzrurl.py (+2/-1)
To merge this branch: bzr merge lp:~gnuoy/charms/trusty/nova-compute/stable-charm-sync
Reviewer Review Type Date Requested Status
Chris Glass (community) Approve
Review via email: mp+230679@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Chris Glass (tribaal) wrote :

+1.

Couldn't reproduce the linked bug with this branch, but I didn't hit the bug before (might be just luck). The fix seems rational and should help, anyway.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2014-08-13 16:35:50 +0000
4@@ -0,0 +1,2 @@
5+bin
6+.coverage
7
8=== modified file 'Makefile'
9--- Makefile 2014-05-21 10:14:58 +0000
10+++ Makefile 2014-08-13 16:35:50 +0000
11@@ -9,8 +9,13 @@
12 @echo Starting tests...
13 @$(PYTHON) /usr/bin/nosetests --nologcapture --with-coverage unit_tests
14
15-sync:
16- @charm-helper-sync -c charm-helpers.yaml
17+bin/charm_helpers_sync.py:
18+ @mkdir -p bin
19+ @bzr cat lp:charm-helpers/tools/charm_helpers_sync/charm_helpers_sync.py \
20+ > bin/charm_helpers_sync.py
21+
22+sync: bin/charm_helpers_sync.py
23+ @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers.yaml
24
25 publish: lint test
26 bzr push lp:charms/nova-compute
27
28=== modified file 'hooks/charmhelpers/contrib/openstack/context.py'
29--- hooks/charmhelpers/contrib/openstack/context.py 2014-05-19 11:41:02 +0000
30+++ hooks/charmhelpers/contrib/openstack/context.py 2014-08-13 16:35:50 +0000
31@@ -24,6 +24,7 @@
32 unit_get,
33 unit_private_ip,
34 ERROR,
35+ INFO
36 )
37
38 from charmhelpers.contrib.hahelpers.cluster import (
39@@ -657,7 +658,7 @@
40 self.interface = interface
41
42 def __call__(self):
43- ctxt = {}
44+ ctxt = {'sections': {}}
45 for rid in relation_ids(self.interface):
46 for unit in related_units(rid):
47 sub_config = relation_get('subordinate_configuration',
48@@ -683,10 +684,14 @@
49
50 sub_config = sub_config[self.config_file]
51 for k, v in sub_config.iteritems():
52- ctxt[k] = v
53+ if k == 'sections':
54+ for section, config_dict in v.iteritems():
55+ log("adding section '%s'" % (section))
56+ ctxt[k][section] = config_dict
57+ else:
58+ ctxt[k] = v
59
60- if not ctxt:
61- ctxt['sections'] = {}
62+ log("%d section(s) found" % (len(ctxt['sections'])), level=INFO)
63
64 return ctxt
65
66
67=== modified file 'hooks/charmhelpers/contrib/storage/linux/utils.py'
68--- hooks/charmhelpers/contrib/storage/linux/utils.py 2014-05-19 11:41:02 +0000
69+++ hooks/charmhelpers/contrib/storage/linux/utils.py 2014-08-13 16:35:50 +0000
70@@ -37,6 +37,7 @@
71 check_call(['dd', 'if=/dev/zero', 'of=%s' % (block_device),
72 'bs=512', 'count=100', 'seek=%s' % (gpt_end)])
73
74+
75 def is_device_mounted(device):
76 '''Given a device path, return True if that device is mounted, and False
77 if it isn't.
78@@ -45,5 +46,8 @@
79 :returns: boolean: True if the path represents a mounted device, False if
80 it doesn't.
81 '''
82+ is_partition = bool(re.search(r".*[0-9]+\b", device))
83 out = check_output(['mount'])
84+ if is_partition:
85+ return bool(re.search(device + r"\b", out))
86 return bool(re.search(device + r"[0-9]+\b", out))
87
88=== added file 'hooks/charmhelpers/core/fstab.py'
89--- hooks/charmhelpers/core/fstab.py 1970-01-01 00:00:00 +0000
90+++ hooks/charmhelpers/core/fstab.py 2014-08-13 16:35:50 +0000
91@@ -0,0 +1,116 @@
92+#!/usr/bin/env python
93+# -*- coding: utf-8 -*-
94+
95+__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
96+
97+import os
98+
99+
100+class Fstab(file):
101+ """This class extends file in order to implement a file reader/writer
102+ for file `/etc/fstab`
103+ """
104+
105+ class Entry(object):
106+ """Entry class represents a non-comment line on the `/etc/fstab` file
107+ """
108+ def __init__(self, device, mountpoint, filesystem,
109+ options, d=0, p=0):
110+ self.device = device
111+ self.mountpoint = mountpoint
112+ self.filesystem = filesystem
113+
114+ if not options:
115+ options = "defaults"
116+
117+ self.options = options
118+ self.d = d
119+ self.p = p
120+
121+ def __eq__(self, o):
122+ return str(self) == str(o)
123+
124+ def __str__(self):
125+ return "{} {} {} {} {} {}".format(self.device,
126+ self.mountpoint,
127+ self.filesystem,
128+ self.options,
129+ self.d,
130+ self.p)
131+
132+ DEFAULT_PATH = os.path.join(os.path.sep, 'etc', 'fstab')
133+
134+ def __init__(self, path=None):
135+ if path:
136+ self._path = path
137+ else:
138+ self._path = self.DEFAULT_PATH
139+ file.__init__(self, self._path, 'r+')
140+
141+ def _hydrate_entry(self, line):
142+ # NOTE: use split with no arguments to split on any
143+ # whitespace including tabs
144+ return Fstab.Entry(*filter(
145+ lambda x: x not in ('', None),
146+ line.strip("\n").split()))
147+
148+ @property
149+ def entries(self):
150+ self.seek(0)
151+ for line in self.readlines():
152+ try:
153+ if not line.startswith("#"):
154+ yield self._hydrate_entry(line)
155+ except ValueError:
156+ pass
157+
158+ def get_entry_by_attr(self, attr, value):
159+ for entry in self.entries:
160+ e_attr = getattr(entry, attr)
161+ if e_attr == value:
162+ return entry
163+ return None
164+
165+ def add_entry(self, entry):
166+ if self.get_entry_by_attr('device', entry.device):
167+ return False
168+
169+ self.write(str(entry) + '\n')
170+ self.truncate()
171+ return entry
172+
173+ def remove_entry(self, entry):
174+ self.seek(0)
175+
176+ lines = self.readlines()
177+
178+ found = False
179+ for index, line in enumerate(lines):
180+ if not line.startswith("#"):
181+ if self._hydrate_entry(line) == entry:
182+ found = True
183+ break
184+
185+ if not found:
186+ return False
187+
188+ lines.remove(line)
189+
190+ self.seek(0)
191+ self.write(''.join(lines))
192+ self.truncate()
193+ return True
194+
195+ @classmethod
196+ def remove_by_mountpoint(cls, mountpoint, path=None):
197+ fstab = cls(path=path)
198+ entry = fstab.get_entry_by_attr('mountpoint', mountpoint)
199+ if entry:
200+ return fstab.remove_entry(entry)
201+ return False
202+
203+ @classmethod
204+ def add(cls, device, mountpoint, filesystem, options=None, path=None):
205+ return cls(path=path).add_entry(Fstab.Entry(device,
206+ mountpoint, filesystem,
207+ options=options))
208
209=== modified file 'hooks/charmhelpers/core/host.py'
210--- hooks/charmhelpers/core/host.py 2014-05-19 11:41:02 +0000
211+++ hooks/charmhelpers/core/host.py 2014-08-13 16:35:50 +0000
212@@ -17,6 +17,7 @@
213 from collections import OrderedDict
214
215 from hookenv import log
216+from fstab import Fstab
217
218
219 def service_start(service_name):
220@@ -35,7 +36,8 @@
221
222
223 def service_reload(service_name, restart_on_failure=False):
224- """Reload a system service, optionally falling back to restart if reload fails"""
225+ """Reload a system service, optionally falling back to restart if
226+ reload fails"""
227 service_result = service('reload', service_name)
228 if not service_result and restart_on_failure:
229 service_result = service('restart', service_name)
230@@ -144,7 +146,19 @@
231 target.write(content)
232
233
234-def mount(device, mountpoint, options=None, persist=False):
235+def fstab_remove(mp):
236+ """Remove the given mountpoint entry from /etc/fstab
237+ """
238+ return Fstab.remove_by_mountpoint(mp)
239+
240+
241+def fstab_add(dev, mp, fs, options=None):
242+ """Adds the given device entry to the /etc/fstab file
243+ """
244+ return Fstab.add(dev, mp, fs, options=options)
245+
246+
247+def mount(device, mountpoint, options=None, persist=False, filesystem="ext3"):
248 """Mount a filesystem at a particular mountpoint"""
249 cmd_args = ['mount']
250 if options is not None:
251@@ -155,9 +169,9 @@
252 except subprocess.CalledProcessError, e:
253 log('Error mounting {} at {}\n{}'.format(device, mountpoint, e.output))
254 return False
255+
256 if persist:
257- # TODO: update fstab
258- pass
259+ return fstab_add(device, mountpoint, filesystem, options=options)
260 return True
261
262
263@@ -169,9 +183,9 @@
264 except subprocess.CalledProcessError, e:
265 log('Error unmounting {}\n{}'.format(mountpoint, e.output))
266 return False
267+
268 if persist:
269- # TODO: update fstab
270- pass
271+ return fstab_remove(mountpoint)
272 return True
273
274
275@@ -306,6 +320,10 @@
276 '''
277 if not pkgcache:
278 apt_pkg.init()
279+ # Force Apt to build its cache in memory. That way we avoid race
280+ # conditions with other applications building the cache in the same
281+ # place.
282+ apt_pkg.config.set("Dir::Cache::pkgcache", "")
283 pkgcache = apt_pkg.Cache()
284 pkg = pkgcache[package]
285 return apt_pkg.version_compare(pkg.current_ver.ver_str, revno)
286
287=== modified file 'hooks/charmhelpers/fetch/__init__.py'
288--- hooks/charmhelpers/fetch/__init__.py 2014-05-19 11:41:02 +0000
289+++ hooks/charmhelpers/fetch/__init__.py 2014-08-13 16:35:50 +0000
290@@ -113,6 +113,7 @@
291 # Tell apt to build an in-memory cache to prevent race conditions (if
292 # another process is already building the cache).
293 apt_pkg.config.set("Dir::Cache::pkgcache", "")
294+ apt_pkg.config.set("Dir::Cache::srcpkgcache", "")
295
296 cache = apt_pkg.Cache()
297 _pkgs = []
298
299=== modified file 'hooks/charmhelpers/fetch/bzrurl.py'
300--- hooks/charmhelpers/fetch/bzrurl.py 2013-11-06 03:50:44 +0000
301+++ hooks/charmhelpers/fetch/bzrurl.py 2014-08-13 16:35:50 +0000
302@@ -39,7 +39,8 @@
303 def install(self, source):
304 url_parts = self.parse_url(source)
305 branch_name = url_parts.path.strip("/").split("/")[-1]
306- dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", branch_name)
307+ dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched",
308+ branch_name)
309 if not os.path.exists(dest_dir):
310 mkdir(dest_dir, perms=0755)
311 try:

Subscribers

People subscribed via source and target branches