~quobyte/charms/trusty/quobyte-webconsole/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/core/fstab.py

  • Committer: Bruno Ranieri
  • Date: 2016-07-13 14:50:01 UTC
  • Revision ID: bruno@quobyte.com-20160713145001-1h6cddu9sltlvx7w
Initial charm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# Copyright 2014-2015 Canonical Limited.
 
5
#
 
6
# This file is part of charm-helpers.
 
7
#
 
8
# charm-helpers is free software: you can redistribute it and/or modify
 
9
# it under the terms of the GNU Lesser General Public License version 3 as
 
10
# published by the Free Software Foundation.
 
11
#
 
12
# charm-helpers is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU Lesser General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU Lesser General Public License
 
18
# along with charm-helpers.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
import io
 
21
import os
 
22
 
 
23
__author__ = 'Jorge Niedbalski R. <jorge.niedbalski@canonical.com>'
 
24
 
 
25
 
 
26
class Fstab(io.FileIO):
 
27
    """This class extends file in order to implement a file reader/writer
 
28
    for file `/etc/fstab`
 
29
    """
 
30
 
 
31
    class Entry(object):
 
32
        """Entry class represents a non-comment line on the `/etc/fstab` file
 
33
        """
 
34
        def __init__(self, device, mountpoint, filesystem,
 
35
                     options, d=0, p=0):
 
36
            self.device = device
 
37
            self.mountpoint = mountpoint
 
38
            self.filesystem = filesystem
 
39
 
 
40
            if not options:
 
41
                options = "defaults"
 
42
 
 
43
            self.options = options
 
44
            self.d = int(d)
 
45
            self.p = int(p)
 
46
 
 
47
        def __eq__(self, o):
 
48
            return str(self) == str(o)
 
49
 
 
50
        def __str__(self):
 
51
            return "{} {} {} {} {} {}".format(self.device,
 
52
                                              self.mountpoint,
 
53
                                              self.filesystem,
 
54
                                              self.options,
 
55
                                              self.d,
 
56
                                              self.p)
 
57
 
 
58
    DEFAULT_PATH = os.path.join(os.path.sep, 'etc', 'fstab')
 
59
 
 
60
    def __init__(self, path=None):
 
61
        if path:
 
62
            self._path = path
 
63
        else:
 
64
            self._path = self.DEFAULT_PATH
 
65
        super(Fstab, self).__init__(self._path, 'rb+')
 
66
 
 
67
    def _hydrate_entry(self, line):
 
68
        # NOTE: use split with no arguments to split on any
 
69
        #       whitespace including tabs
 
70
        return Fstab.Entry(*filter(
 
71
            lambda x: x not in ('', None),
 
72
            line.strip("\n").split()))
 
73
 
 
74
    @property
 
75
    def entries(self):
 
76
        self.seek(0)
 
77
        for line in self.readlines():
 
78
            line = line.decode('us-ascii')
 
79
            try:
 
80
                if line.strip() and not line.strip().startswith("#"):
 
81
                    yield self._hydrate_entry(line)
 
82
            except ValueError:
 
83
                pass
 
84
 
 
85
    def get_entry_by_attr(self, attr, value):
 
86
        for entry in self.entries:
 
87
            e_attr = getattr(entry, attr)
 
88
            if e_attr == value:
 
89
                return entry
 
90
        return None
 
91
 
 
92
    def add_entry(self, entry):
 
93
        if self.get_entry_by_attr('device', entry.device):
 
94
            return False
 
95
 
 
96
        self.write((str(entry) + '\n').encode('us-ascii'))
 
97
        self.truncate()
 
98
        return entry
 
99
 
 
100
    def remove_entry(self, entry):
 
101
        self.seek(0)
 
102
 
 
103
        lines = [l.decode('us-ascii') for l in self.readlines()]
 
104
 
 
105
        found = False
 
106
        for index, line in enumerate(lines):
 
107
            if line.strip() and not line.strip().startswith("#"):
 
108
                if self._hydrate_entry(line) == entry:
 
109
                    found = True
 
110
                    break
 
111
 
 
112
        if not found:
 
113
            return False
 
114
 
 
115
        lines.remove(line)
 
116
 
 
117
        self.seek(0)
 
118
        self.write(''.join(lines).encode('us-ascii'))
 
119
        self.truncate()
 
120
        return True
 
121
 
 
122
    @classmethod
 
123
    def remove_by_mountpoint(cls, mountpoint, path=None):
 
124
        fstab = cls(path=path)
 
125
        entry = fstab.get_entry_by_attr('mountpoint', mountpoint)
 
126
        if entry:
 
127
            return fstab.remove_entry(entry)
 
128
        return False
 
129
 
 
130
    @classmethod
 
131
    def add(cls, device, mountpoint, filesystem, options=None, path=None):
 
132
        return cls(path=path).add_entry(Fstab.Entry(device,
 
133
                                                    mountpoint, filesystem,
 
134
                                                    options=options))