Statistics
| Branch: | Tag: | Revision:

root / image_creator / util.py @ 5e18a927

History | View | Annotate | Download (3.8 kB)

1 121f3bc0 Nikos Skalkotos
# -*- coding: utf-8 -*-
2 121f3bc0 Nikos Skalkotos
#
3 ae48a082 Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
4 ae48a082 Nikos Skalkotos
#
5 ae48a082 Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
6 ae48a082 Nikos Skalkotos
# without modification, are permitted provided that the following
7 ae48a082 Nikos Skalkotos
# conditions are met:
8 ae48a082 Nikos Skalkotos
#
9 ae48a082 Nikos Skalkotos
#   1. Redistributions of source code must retain the above
10 ae48a082 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
11 ae48a082 Nikos Skalkotos
#      disclaimer.
12 ae48a082 Nikos Skalkotos
#
13 ae48a082 Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
14 ae48a082 Nikos Skalkotos
#      copyright notice, this list of conditions and the following
15 ae48a082 Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
16 ae48a082 Nikos Skalkotos
#      provided with the distribution.
17 ae48a082 Nikos Skalkotos
#
18 ae48a082 Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 ae48a082 Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 ae48a082 Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 ae48a082 Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 ae48a082 Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 ae48a082 Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 ae48a082 Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 ae48a082 Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 ae48a082 Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 ae48a082 Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 ae48a082 Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 ae48a082 Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
30 ae48a082 Nikos Skalkotos
#
31 ae48a082 Nikos Skalkotos
# The views and conclusions contained in the software and
32 ae48a082 Nikos Skalkotos
# documentation are those of the authors and should not be
33 ae48a082 Nikos Skalkotos
# interpreted as representing official policies, either expressed
34 ae48a082 Nikos Skalkotos
# or implied, of GRNET S.A.
35 3ccb2618 Nikos Skalkotos
36 121f3bc0 Nikos Skalkotos
"""This module provides various helper functions to be used by other parts of
37 121f3bc0 Nikos Skalkotos
the package.
38 121f3bc0 Nikos Skalkotos
"""
39 121f3bc0 Nikos Skalkotos
40 0dbc4db9 Nikos Skalkotos
import sh
41 8e3065a0 Nikos Skalkotos
import hashlib
42 f3845095 Nikos Skalkotos
import time
43 c16850ae Nikos Skalkotos
import os
44 979096dd Nikos Skalkotos
45 f165adc0 Nikos Skalkotos
46 f165adc0 Nikos Skalkotos
class FatalError(Exception):
47 88f83027 Nikos Skalkotos
    """Fatal Error exception of snf-image-creator"""
48 f165adc0 Nikos Skalkotos
    pass
49 f165adc0 Nikos Skalkotos
50 f165adc0 Nikos Skalkotos
51 3ccb2618 Nikos Skalkotos
def get_command(command):
52 88f83027 Nikos Skalkotos
    """Return a file system binary command"""
53 3ccb2618 Nikos Skalkotos
    def find_sbin_command(command, exception):
54 3ccb2618 Nikos Skalkotos
        search_paths = ['/usr/local/sbin', '/usr/sbin', '/sbin']
55 3ccb2618 Nikos Skalkotos
        for fullpath in map(lambda x: "%s/%s" % (x, command), search_paths):
56 3ccb2618 Nikos Skalkotos
            if os.path.exists(fullpath) and os.access(fullpath, os.X_OK):
57 0dbc4db9 Nikos Skalkotos
                return sh.Command(fullpath)
58 3ccb2618 Nikos Skalkotos
        raise exception
59 3ccb2618 Nikos Skalkotos
60 3ccb2618 Nikos Skalkotos
    try:
61 0dbc4db9 Nikos Skalkotos
        return sh.__getattr__(command)
62 3f2ae845 Nikos Skalkotos
    except sh.CommandNotFound as e:
63 3ccb2618 Nikos Skalkotos
        return find_sbin_command(command, e)
64 22a6d232 Nikos Skalkotos
65 22a6d232 Nikos Skalkotos
66 f3845095 Nikos Skalkotos
def try_fail_repeat(command, *args):
67 88f83027 Nikos Skalkotos
    """Execute a command multiple times until it succeeds"""
68 f3845095 Nikos Skalkotos
    times = (0.1, 0.5, 1, 2)
69 f3845095 Nikos Skalkotos
    i = iter(times)
70 f3845095 Nikos Skalkotos
    while True:
71 f3845095 Nikos Skalkotos
        try:
72 f3845095 Nikos Skalkotos
            command(*args)
73 f3845095 Nikos Skalkotos
            return
74 f3845095 Nikos Skalkotos
        except sh.ErrorReturnCode:
75 f3845095 Nikos Skalkotos
            try:
76 f3845095 Nikos Skalkotos
                wait = i.next()
77 f3845095 Nikos Skalkotos
            except StopIteration:
78 f3845095 Nikos Skalkotos
                break
79 f3845095 Nikos Skalkotos
            time.sleep(wait)
80 f3845095 Nikos Skalkotos
81 f3845095 Nikos Skalkotos
    raise FatalError("Command: `%s %s' failed" % (command, " ".join(args)))
82 f3845095 Nikos Skalkotos
83 f3845095 Nikos Skalkotos
84 c16850ae Nikos Skalkotos
def free_space(dirname):
85 88f83027 Nikos Skalkotos
    """Compute the free space in a directory"""
86 c16850ae Nikos Skalkotos
    stat = os.statvfs(dirname)
87 c16850ae Nikos Skalkotos
    return stat.f_bavail * stat.f_frsize
88 c16850ae Nikos Skalkotos
89 c16850ae Nikos Skalkotos
90 e77e66a9 Nikos Skalkotos
class MD5:
91 88f83027 Nikos Skalkotos
    """Represents MD5 computations"""
92 e77e66a9 Nikos Skalkotos
    def __init__(self, output):
93 88f83027 Nikos Skalkotos
        """Create an MD5 instance"""
94 e77e66a9 Nikos Skalkotos
        self.out = output
95 8e3065a0 Nikos Skalkotos
96 e77e66a9 Nikos Skalkotos
    def compute(self, filename, size):
97 88f83027 Nikos Skalkotos
        """Compute the MD5 checksum of a file"""
98 96171db1 Nikos Skalkotos
        MB = 2 ** 20
99 96171db1 Nikos Skalkotos
        BLOCKSIZE = 4 * MB  # 4MB
100 8e3065a0 Nikos Skalkotos
101 96171db1 Nikos Skalkotos
        prog_size = ((size + MB - 1) // MB)  # in MB
102 4e58b51b Nikos Skalkotos
        progressbar = self.out.Progress(prog_size, "Calculating md5sum", 'mb')
103 e77e66a9 Nikos Skalkotos
        md5 = hashlib.md5()
104 e77e66a9 Nikos Skalkotos
        with open(filename, "r") as src:
105 e77e66a9 Nikos Skalkotos
            left = size
106 e77e66a9 Nikos Skalkotos
            while left > 0:
107 e77e66a9 Nikos Skalkotos
                length = min(left, BLOCKSIZE)
108 e77e66a9 Nikos Skalkotos
                data = src.read(length)
109 e77e66a9 Nikos Skalkotos
                md5.update(data)
110 e77e66a9 Nikos Skalkotos
                left -= length
111 96171db1 Nikos Skalkotos
                progressbar.goto((size - left) // MB)
112 42ace959 Nikos Skalkotos
113 e77e66a9 Nikos Skalkotos
        checksum = md5.hexdigest()
114 e77e66a9 Nikos Skalkotos
        progressbar.success(checksum)
115 8e3065a0 Nikos Skalkotos
116 e77e66a9 Nikos Skalkotos
        return checksum
117 22a6d232 Nikos Skalkotos
118 22a6d232 Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :