Initial commit
[ta/config-manager.git] / cmframework / src / cmframework / filebackend / cmfilebackend.py
1 # Copyright 2019 Nokia
2
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 from __future__ import print_function
15 import logging
16 import re
17 import os
18 import stat
19
20 from cmframework.apis import cmbackend
21 from cmframework.apis import cmerror
22
23
24 class CMFileBackend(cmbackend.CMBackend):
25     def __init__(self, **kw):
26         self.uri = kw['uri']
27         logging.debug('CMFileBackend constructor called, uri=%s', self.uri)
28         self.data = {}
29         self.load_file()
30
31     def load_file(self):
32         logging.debug('load_file started')
33         try:
34             self.data = {}
35             with open(self.uri) as f:
36                 lines = f.read().splitlines()
37                 for line in lines:
38                     name, var = line.partition('=')[::2]
39                     logging.debug('Adding %s=%s', name, var)
40                     self.data[name.strip()] = var
41                 f.close()
42         except IOError:
43             logging.debug('File %s does not exist', self.uri)
44
45     def write_file(self):
46         logging.debug('write_file started')
47         try:
48             with open(self.uri, 'w') as f:
49                 os.chmod(self.uri, stat.S_IRUSR | stat.S_IWUSR)
50                 for key, value in self.data.iteritems():
51                     logging.debug('Writing %s=%s', key, value)
52                     f.write(key + '=' + value + '\n')
53                 f.flush()
54                 os.fsync(f.fileno())
55         except IOError as exp:
56             raise cmerror.CMError(str(exp))
57
58     def get_property(self, prop_name):
59         logging.debug('get_property called for %s', prop_name)
60         try:
61             value = self.data[prop_name]
62             return value
63         except KeyError:
64             raise cmerror.CMError('Invalid property name')
65
66     def get_properties(self, prop_filter):
67         logging.debug('get_properties called with filter %s', prop_filter)
68         returned = {}
69         pattern = re.compile(prop_filter)
70         for key, value in self.data.iteritems():
71             logging.debug('Matching %s against %s', key, prop_filter)
72             if pattern.match(key):
73                 logging.debug('Adding %s', key)
74                 returned[key] = value
75         return returned
76
77     def set_property(self, prop_name, prop_value):
78         logging.debug('set_property %s=%s', prop_name, prop_value)
79         props = {}
80         props[prop_name] = prop_value
81         self.set_properties(props)
82
83     def set_properties(self, properties):
84         logging.debug('set_properties called props=%s', str(properties))
85         try:
86             for key, value in properties.iteritems():
87                 self.data[key] = value
88             self.write_file()
89         except cmerror.CMError:
90             self.load_file()
91             raise
92
93     def delete_property(self, prop_name):
94         logging.debug('delete_property called for %s', prop_name)
95         try:
96             del self.data[prop_name]
97             self.write_file()
98         except KeyError:
99             logging.debug('Property not found')
100             raise cmerror.CMError('Property not found')
101         except cmerror.CMError:
102             self.load_file()
103             raise
104
105     def delete_properties(self, arg):
106         logging.debug('delete_properties called with arg %s', arg)
107         try:
108             if isinstance(arg, str):
109                 pattern = re.compile(arg)
110                 for key in self.data.keys():  # pylint: disable=consider-iterating-dictionary
111                     if pattern.match(key):
112                         del self.data[key]
113             else:
114                 for prop in arg:
115                     for key in self.data.keys():  # pylint: disable=consider-iterating-dictionary
116                         if key == prop:
117                             del self.data[key]
118             self.write_file()
119         except cmerror.CMError:
120             self.load_file()
121             raise
122
123
124 def main():
125     import sys
126
127     filepath = sys.argv[1]
128     try:
129         print('Initializing backend at %s' % filepath)
130         filebackend = CMFileBackend(uri=filepath)
131         print('Adding key1=value1')
132         filebackend.set_property("key1", "value1")
133         properties = {'key2': 'value2', 'key3': 'value3'}
134         print('Adding %s' % str(properties))
135         filebackend.set_properties(properties)
136         print('Getting key1')
137         value = filebackend.get_property('key1')
138         print('value of key1 is %s' % value)
139         print('Deleting key2')
140         filebackend.delete_property('key2')
141         print('Getting *')
142         properties = filebackend.get_properties('.*')
143         print('Got %s' % str(properties))
144         print('Delete all properties')
145         filebackend.delete_properties('.*')
146     except cmerror.CMError as exp:
147         print('Got exeption %s' % str(exp))
148         sys.exit(1)
149
150
151 if __name__ == '__main__':
152     main()