]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/policymanager.py
python3: 2to3 changes
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / policymanager.py
1 #!/usr/bin/env python3
2 #
3 # Copyright 2015-2017 Cumulus Networks, Inc. All rights reserved.
4 #
5 #
6 '''
7 The PolicyManager should be subclassed by addon modules
8 to read a JSON policy config file that is later used to
9 set defaults:
10
11 Initialize: This module defines a list of config file location based
12 on module. There are defined in the __init__(): All the
13 addon modules need to do is import the policymanager module.
14
15 import ifupdown2.ifupdown.policymanager as policymanager
16
17
18 Provides: an API to retrieve link attributes based on addon module name,
19 interface name, and attribute.
20
21 The ifupdown.policymanager module provides a global object policymanager_api
22 that can be called like so:
23
24 speed_default = policymanager.policymanager_api.get_default(
25 module_name='ethtool',
26 ifname=ifaceobj.name,
27 attr='link-speed'
28 )
29 '''
30
31 import json
32 import glob
33 import logging
34
35
36 class policymanager():
37 def __init__(self):
38 # we should check for these files in order
39 # so that customers can override the /var/lib file settings
40 self.logger = logging.getLogger('ifupdown.' +
41 self.__class__.__name__)
42
43 self.logger.info("policymanager init")
44
45 # we grab the json files from a known location and make sure that
46 # the defaults_policy is checked first
47 user_files = glob.glob('/etc/network/ifupdown2/policy.d/*.json')
48 # grab the default module files
49 default_files = glob.glob('/var/lib/ifupdown2/policy.d/*.json')
50 # keep an array of defaults indexed by module name
51 self.system_policy_array = {}
52 for filename in default_files:
53 system_array = {}
54 try:
55 with open(filename, 'r') as fd:
56 system_array = json.load(fd)
57 self.logger.debug('reading %s system policy defaults config' \
58 % filename)
59 except Exception as e:
60 self.logger.warning('could not read %s system policy defaults config' \
61 % filename)
62 self.logger.warning(' exception is %s' % str(e))
63
64 for module in list(system_array.keys()):
65 if module in self.system_policy_array:
66 self.logger.debug("policymanager: merging system module %s policy with file %s" % (module, filename))
67 self.system_policy_array[module].update(system_array[module])
68 else:
69 json_dict = system_array[module]
70
71 if isinstance(json_dict, dict):
72 self.system_policy_array[module] = system_array[module]
73 elif module != "README":
74 self.logger.warning(
75 "file %s contains an invalid policy schema, key "
76 "\"%s\" contains %s when a dictionary is expected" %
77 (filename, module, type(json_dict))
78 )
79
80 # take care of user defined policy defaults
81 self.user_policy_array = {}
82 for filename in user_files:
83 user_array = {}
84 try:
85 with open(filename, 'r') as fd:
86 user_array = json.load(fd)
87 self.logger.debug('reading %s policy user defaults config' \
88 % filename)
89 except Exception as e:
90 self.logger.warning('could not read %s user policy defaults config' \
91 % filename)
92 self.logger.warning(' exception is %s' % str(e))
93 # customer added module attributes
94 for module in list(user_array.keys()):
95 if module in self.system_policy_array:
96 # warn user that we are overriding the system module setting
97 self.logger.debug('warning: overwriting system with user module %s from file %s' \
98 % (module,filename))
99 if module in self.user_policy_array:
100 self.logger.debug("policymanager: merging user module %s policy with file %s" % (module, filename))
101 self.user_policy_array[module].update(user_array[module])
102 else:
103 self.user_policy_array[module] = user_array[module]
104 return
105
106 def get_iface_default(self,module_name=None,ifname=None,attr=None):
107 '''
108 get_iface_default: Addon modules must use one of two types of access methods to
109 the default configs. In this method, we expect the default to be
110 either in
111 [module]['iface_defaults'][ifname][attr] or
112 [module]['defaults'][attr]
113 We first check the user_policy_array and return that value. But if
114 the user did not specify an override, we use the system_policy_array.
115 '''
116 # make sure we have an index
117 if (not ifname or not attr or not module_name):
118 return None
119
120 val = None
121 # users can specify defaults to override the systemwide settings
122 # look for user specific interface attribute iface_defaults first
123 try:
124 # looks for user specified value
125 val = self.user_policy_array[module_name]['iface_defaults'][ifname][attr]
126 return val
127 except (TypeError, KeyError, IndexError):
128 pass
129 try:
130 # failing that, there may be a user default for all intefaces
131 val = self.user_policy_array[module_name]['defaults'][attr]
132 return val
133 except (TypeError, KeyError, IndexError):
134 pass
135 try:
136 # failing that, look for system setting for the interface
137 val = self.system_policy_array[module_name]['iface_defaults'][ifname][attr]
138 return val
139 except (TypeError, KeyError, IndexError):
140 pass
141 try:
142 # failing that, look for system setting for all interfaces
143 val = self.system_policy_array[module_name]['defaults'][attr]
144 return val
145 except (TypeError, KeyError, IndexError):
146 pass
147
148 # could not find any system or user default so return Non
149 return val
150
151 def get_attr_default(self,module_name=None,attr=None):
152 '''
153 get_attr_default: Addon modules must use one of two types of access methods to
154 the default configs. In this method, we expect the default to be in
155
156 [module]['defaults'][attr]
157
158 We first check the user_policy_array and return that value. But if
159 the user did not specify an override, we use the system_policy_array.
160 '''
161 if (not attr or not module_name):
162 return None
163 # users can specify defaults to override the systemwide settings
164 # look for user specific attribute defaults first
165 val = None
166 try:
167 # looks for user specified value
168 val = self.user_policy_array[module_name]['defaults'][attr]
169 return val
170 except (TypeError, KeyError, IndexError):
171 pass
172 try:
173 # failing that, look for system setting
174 val = self.system_policy_array[module_name]['defaults'][attr]
175 return val
176 except (TypeError, KeyError, IndexError):
177 pass
178
179 return val
180
181 def get_module_globals(self,module_name=None,attr=None):
182 '''
183 get_module_globals: Addon modules must use one of two types of access methods to
184 the default configs. In this method, we expect the default to be in
185
186 [module]['module_globals'][attr]
187
188 We first check the user_policy_array and return that value. But if
189 the user did not specify an override, we use the system_policy_array.
190 '''
191
192 if (not attr or not module_name):
193 return None
194 # users can specify defaults to override the systemwide settings
195 # look for user specific attribute defaults first
196 val = None
197 try:
198 # looks for user specified value
199 val = self.user_policy_array[module_name]['module_globals'][attr]
200 return val
201 except (TypeError, KeyError, IndexError):
202 pass
203 try:
204 # failing that, look for system setting
205 val = self.system_policy_array[module_name]['module_globals'][attr]
206 return val
207 except (TypeError, KeyError, IndexError):
208 pass
209
210 return val
211
212 def get_module_defaults(self, module_name):
213 """
214 get_module_defaults: returns a merged dictionary of default values
215 specified in policy files. Users provided values override system
216 values.
217 """
218
219 if not module_name:
220 raise NotImplementedError('get_module_defaults: module name can\'t be None')
221
222 defaults = dict()
223 defaults.update(self.system_policy_array.get(module_name, {}).get('defaults', {}))
224 defaults.update(self.user_policy_array.get(module_name, {}).get('defaults', {}))
225 return defaults
226
227 def get_iface_defaults(self, module_name):
228 defaults = dict()
229
230 if not module_name:
231 self.logger.info('get_iface_defaults: module name can\'t be None')
232 else:
233 defaults.update(self.system_policy_array.get(module_name, {}).get('iface_defaults', {}))
234 defaults.update(self.user_policy_array.get(module_name, {}).get('iface_defaults', {}))
235 return defaults
236
237
238 policymanager_api = policymanager()
239
240 def reset():
241 global policymanager_api
242 policymanager_api = policymanager()