~openstack-charmers/charms/precise/ceilometer/old-1410

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/fetch/__init__.py

  • Committer: james.page at ubuntu
  • Date: 2014-06-04 13:07:28 UTC
  • Revision ID: james.page@ubuntu.com-20140604130728-s4o5iv7lr7nvowpo
resync helpers for juno support

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import importlib
 
2
import time
2
3
from yaml import safe_load
3
4
from charmhelpers.core.host import (
4
5
    lsb_release
15
16
import apt_pkg
16
17
import os
17
18
 
 
19
 
18
20
CLOUD_ARCHIVE = """# Ubuntu Cloud Archive
19
21
deb http://ubuntu-cloud.archive.canonical.com/ubuntu {} main
20
22
"""
54
56
    'icehouse/proposed': 'precise-proposed/icehouse',
55
57
    'precise-icehouse/proposed': 'precise-proposed/icehouse',
56
58
    'precise-proposed/icehouse': 'precise-proposed/icehouse',
 
59
    # Juno
 
60
    'juno': 'trusty-updates/juno',
 
61
    'trusty-juno': 'trusty-updates/juno',
 
62
    'trusty-juno/updates': 'trusty-updates/juno',
 
63
    'trusty-updates/juno': 'trusty-updates/juno',
 
64
    'juno/proposed': 'trusty-proposed/juno',
 
65
    'juno/proposed': 'trusty-proposed/juno',
 
66
    'trusty-juno/proposed': 'trusty-proposed/juno',
 
67
    'trusty-proposed/juno': 'trusty-proposed/juno',
57
68
}
58
69
 
 
70
# The order of this list is very important. Handlers should be listed in from
 
71
# least- to most-specific URL matching.
 
72
FETCH_HANDLERS = (
 
73
    'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler',
 
74
    'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler',
 
75
)
 
76
 
 
77
APT_NO_LOCK = 100  # The return code for "couldn't acquire lock" in APT.
 
78
APT_NO_LOCK_RETRY_DELAY = 10  # Wait 10 seconds between apt lock checks.
 
79
APT_NO_LOCK_RETRY_COUNT = 30  # Retry to acquire the lock X times.
 
80
 
 
81
 
 
82
class SourceConfigError(Exception):
 
83
    pass
 
84
 
 
85
 
 
86
class UnhandledSource(Exception):
 
87
    pass
 
88
 
 
89
 
 
90
class AptLockError(Exception):
 
91
    pass
 
92
 
 
93
 
 
94
class BaseFetchHandler(object):
 
95
 
 
96
    """Base class for FetchHandler implementations in fetch plugins"""
 
97
 
 
98
    def can_handle(self, source):
 
99
        """Returns True if the source can be handled. Otherwise returns
 
100
        a string explaining why it cannot"""
 
101
        return "Wrong source type"
 
102
 
 
103
    def install(self, source):
 
104
        """Try to download and unpack the source. Return the path to the
 
105
        unpacked files or raise UnhandledSource."""
 
106
        raise UnhandledSource("Wrong source type {}".format(source))
 
107
 
 
108
    def parse_url(self, url):
 
109
        return urlparse(url)
 
110
 
 
111
    def base_url(self, url):
 
112
        """Return url without querystring or fragment"""
 
113
        parts = list(self.parse_url(url))
 
114
        parts[4:] = ['' for i in parts[4:]]
 
115
        return urlunparse(parts)
 
116
 
59
117
 
60
118
def filter_installed_packages(packages):
61
119
    """Returns a list of packages that require installation"""
62
120
    apt_pkg.init()
 
121
 
 
122
    # Tell apt to build an in-memory cache to prevent race conditions (if
 
123
    # another process is already building the cache).
 
124
    apt_pkg.config.set("Dir::Cache::pkgcache", "")
 
125
 
63
126
    cache = apt_pkg.Cache()
64
127
    _pkgs = []
65
128
    for package in packages:
87
150
        cmd.extend(packages)
88
151
    log("Installing {} with options: {}".format(packages,
89
152
                                                options))
90
 
    env = os.environ.copy()
91
 
    if 'DEBIAN_FRONTEND' not in env:
92
 
        env['DEBIAN_FRONTEND'] = 'noninteractive'
93
 
 
94
 
    if fatal:
95
 
        subprocess.check_call(cmd, env=env)
96
 
    else:
97
 
        subprocess.call(cmd, env=env)
 
153
    _run_apt_command(cmd, fatal)
98
154
 
99
155
 
100
156
def apt_upgrade(options=None, fatal=False, dist=False):
109
165
    else:
110
166
        cmd.append('upgrade')
111
167
    log("Upgrading with options: {}".format(options))
112
 
 
113
 
    env = os.environ.copy()
114
 
    if 'DEBIAN_FRONTEND' not in env:
115
 
        env['DEBIAN_FRONTEND'] = 'noninteractive'
116
 
 
117
 
    if fatal:
118
 
        subprocess.check_call(cmd, env=env)
119
 
    else:
120
 
        subprocess.call(cmd, env=env)
 
168
    _run_apt_command(cmd, fatal)
121
169
 
122
170
 
123
171
def apt_update(fatal=False):
124
172
    """Update local apt cache"""
125
173
    cmd = ['apt-get', 'update']
126
 
    if fatal:
127
 
        subprocess.check_call(cmd)
128
 
    else:
129
 
        subprocess.call(cmd)
 
174
    _run_apt_command(cmd, fatal)
130
175
 
131
176
 
132
177
def apt_purge(packages, fatal=False):
137
182
    else:
138
183
        cmd.extend(packages)
139
184
    log("Purging {}".format(packages))
140
 
    if fatal:
141
 
        subprocess.check_call(cmd)
142
 
    else:
143
 
        subprocess.call(cmd)
 
185
    _run_apt_command(cmd, fatal)
144
186
 
145
187
 
146
188
def apt_hold(packages, fatal=False):
151
193
    else:
152
194
        cmd.extend(packages)
153
195
    log("Holding {}".format(packages))
 
196
 
154
197
    if fatal:
155
198
        subprocess.check_call(cmd)
156
199
    else:
184
227
            apt.write(PROPOSED_POCKET.format(release))
185
228
    if key:
186
229
        subprocess.check_call(['apt-key', 'adv', '--keyserver',
187
 
                               'keyserver.ubuntu.com', '--recv',
 
230
                               'hkp://keyserver.ubuntu.com:80', '--recv',
188
231
                               key])
189
232
 
190
233
 
191
 
class SourceConfigError(Exception):
192
 
    pass
193
 
 
194
 
 
195
234
def configure_sources(update=False,
196
235
                      sources_var='install_sources',
197
236
                      keys_var='install_keys'):
224
263
    if update:
225
264
        apt_update(fatal=True)
226
265
 
227
 
# The order of this list is very important. Handlers should be listed in from
228
 
# least- to most-specific URL matching.
229
 
FETCH_HANDLERS = (
230
 
    'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler',
231
 
    'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler',
232
 
)
233
 
 
234
 
 
235
 
class UnhandledSource(Exception):
236
 
    pass
237
 
 
238
266
 
239
267
def install_remote(source):
240
268
    """
265
293
    return install_remote(source)
266
294
 
267
295
 
268
 
class BaseFetchHandler(object):
269
 
 
270
 
    """Base class for FetchHandler implementations in fetch plugins"""
271
 
 
272
 
    def can_handle(self, source):
273
 
        """Returns True if the source can be handled. Otherwise returns
274
 
        a string explaining why it cannot"""
275
 
        return "Wrong source type"
276
 
 
277
 
    def install(self, source):
278
 
        """Try to download and unpack the source. Return the path to the
279
 
        unpacked files or raise UnhandledSource."""
280
 
        raise UnhandledSource("Wrong source type {}".format(source))
281
 
 
282
 
    def parse_url(self, url):
283
 
        return urlparse(url)
284
 
 
285
 
    def base_url(self, url):
286
 
        """Return url without querystring or fragment"""
287
 
        parts = list(self.parse_url(url))
288
 
        parts[4:] = ['' for i in parts[4:]]
289
 
        return urlunparse(parts)
290
 
 
291
 
 
292
296
def plugins(fetch_handlers=None):
293
297
    if not fetch_handlers:
294
298
        fetch_handlers = FETCH_HANDLERS
306
310
            log("FetchHandler {} not found, skipping plugin".format(
307
311
                handler_name))
308
312
    return plugin_list
 
313
 
 
314
 
 
315
def _run_apt_command(cmd, fatal=False):
 
316
    """
 
317
    Run an APT command, checking output and retrying if the fatal flag is set
 
318
    to True.
 
319
 
 
320
    :param: cmd: str: The apt command to run.
 
321
    :param: fatal: bool: Whether the command's output should be checked and
 
322
        retried.
 
323
    """
 
324
    env = os.environ.copy()
 
325
 
 
326
    if 'DEBIAN_FRONTEND' not in env:
 
327
        env['DEBIAN_FRONTEND'] = 'noninteractive'
 
328
 
 
329
    if fatal:
 
330
        retry_count = 0
 
331
        result = None
 
332
 
 
333
        # If the command is considered "fatal", we need to retry if the apt
 
334
        # lock was not acquired.
 
335
 
 
336
        while result is None or result == APT_NO_LOCK:
 
337
            try:
 
338
                result = subprocess.check_call(cmd, env=env)
 
339
            except subprocess.CalledProcessError, e:
 
340
                retry_count = retry_count + 1
 
341
                if retry_count > APT_NO_LOCK_RETRY_COUNT:
 
342
                    raise
 
343
                result = e.returncode
 
344
                log("Couldn't acquire DPKG lock. Will retry in {} seconds."
 
345
                    "".format(APT_NO_LOCK_RETRY_DELAY))
 
346
                time.sleep(APT_NO_LOCK_RETRY_DELAY)
 
347
 
 
348
    else:
 
349
        subprocess.call(cmd, env=env)