]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdown/statemanager.py
ifupdown2 2.0.0 release
[mirror_ifupdown2.git] / ifupdown2 / ifupdown / statemanager.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 #
6 # stateManager --
7 # interface state manager
8 #
9
10 import os
11 import cPickle
12 import logging
13
14 try:
15 from ifupdown2.ifupdown.iface import *
16
17 import ifupdown2.ifupdown.exceptions as exceptions
18 except ImportError:
19 from ifupdown.iface import *
20
21 import ifupdown.exceptions as exceptions
22
23
24 class pickling():
25 """ class with helper methods for pickling/unpickling iface objects """
26
27 @classmethod
28 def save(cls, filename, list_of_objects):
29 """ pickle a list of iface objects """
30 try:
31 with open(filename, 'w') as f:
32 for obj in list_of_objects:
33 cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL)
34 except:
35 raise
36
37 @classmethod
38 def save_obj(cls, f, obj):
39 """ pickle iface object """
40 try:
41 cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL)
42 except:
43 raise
44
45 @classmethod
46 def load(cls, filename):
47 """ load picked iface object """
48 with open(filename, 'r') as f:
49 while True:
50 try: yield cPickle.load(f)
51 except EOFError: break
52 except: raise
53
54 class stateManager():
55 """ state manager for managing ifupdown iface obj state
56
57 ifupdown2 has to maitain old objects for down operation on
58 interfaces. ie to down or delete old configuration.
59
60 This class uses pickle to store iface objects.
61
62 """
63
64 state_dir = '/var/tmp/network/'
65 """directory where the state file is stored """
66
67 state_filename = 'ifstatenew'
68 """name of the satefile """
69
70 state_rundir = '/run/network/'
71 """name of the state run dir """
72
73 state_runlockfile = 'ifstatelock'
74 """name of the state run lock file """
75
76 def __init__(self):
77 """ Initializes statemanager internal state
78
79 which includes a dictionary of last pickled iface objects
80 """
81 self.ifaceobjdict = OrderedDict()
82 self.logger = logging.getLogger('ifupdown.' +
83 self.__class__.__name__)
84 if not os.path.exists(self.state_dir):
85 os.mkdir(self.state_dir)
86 if not os.path.exists(self.state_rundir):
87 os.mkdir(self.state_rundir)
88 self.state_file = self.state_dir + self.state_filename
89
90 def save_ifaceobj(self, ifaceobj):
91 self.ifaceobjdict.setdefault(ifaceobj.name,
92 []).append(ifaceobj)
93
94 def read_saved_state(self, filename=None):
95 """This member function reads saved iface objects
96
97 Kwargs:
98 filename (str): name of the state file
99 """
100
101 pickle_filename = filename
102 if not pickle_filename:
103 pickle_filename = self.state_file
104 if not os.path.exists(pickle_filename):
105 return
106 for ifaceobj in pickling.load(pickle_filename):
107 self.save_ifaceobj(ifaceobj)
108
109 def get_ifaceobjs(self, ifacename):
110 return self.ifaceobjdict.get(ifacename)
111
112 def ifaceobj_sync(self, ifaceobj, op):
113 """This member function sync's new obj state to old statemanager state
114
115 Args:
116 ifaceobj (object): new iface object
117 op (str): ifupdown operation
118 """
119
120 self.logger.debug('%s: statemanager sync state %s'
121 %(ifaceobj.name, op))
122 old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.name)
123 if 'up' in op:
124 if not old_ifaceobjs:
125 self.ifaceobjdict[ifaceobj.name] = [ifaceobj]
126 else:
127 # If it matches any of the object, return
128 if any(o.compare(ifaceobj) for o in old_ifaceobjs):
129 return
130 # If it does not match any of the objects, and if
131 # all objs in the list came from the pickled file,
132 # then reset the list and add this object as a fresh one,
133 # else append to the list
134 if old_ifaceobjs[0].flags & iface._PICKLED:
135 del self.ifaceobjdict[ifaceobj.name]
136 self.ifaceobjdict[ifaceobj.name] = [ifaceobj]
137 else:
138 self.ifaceobjdict[ifaceobj.name].append(ifaceobj)
139 elif 'down' in op:
140 # If down of object successfull, delete object from state manager
141 if not old_ifaceobjs:
142 return
143 if ifaceobj.status != ifaceStatus.SUCCESS:
144 return
145 # If it matches any of the object, return
146 oidx = 0
147 for o in old_ifaceobjs:
148 if o.compare(ifaceobj):
149 old_ifaceobjs.pop(oidx)
150 if not len(old_ifaceobjs):
151 del self.ifaceobjdict[ifaceobj.name]
152 return
153 oidx += 1
154
155 def save_state(self):
156 """ saves state (ifaceobjects) to persistent state file """
157
158 try:
159 with open(self.state_file, 'w') as f:
160 if not len(self.ifaceobjdict):
161 f.truncate(0)
162 return
163 self.logger.debug('saving state ..')
164 for ifaceobjs in self.ifaceobjdict.values():
165 [pickling.save_obj(f, i) for i in ifaceobjs]
166 open('%s/%s' %(self.state_rundir, self.state_runlockfile), 'w').close()
167 except:
168 raise
169
170 def dump_pretty(self, ifacenames, format='native'):
171 if not ifacenames:
172 ifacenames = self.ifaceobjdict.keys()
173 for i in ifacenames:
174 ifaceobjs = self.get_ifaceobjs(i)
175 if not ifaceobjs:
176 continue
177 for ifaceobj in ifaceobjs:
178 if format == 'json':
179 ifaceobj.dump_json()
180 else:
181 ifaceobj.dump_pretty()
182
183 def dump(self, ifacenames=None):
184 self.logger.debug('statemanager iface state:')
185 if ifacenames:
186 for i in ifacenames:
187 ifaceobj = self.ifaces.get(i)
188 if ifaceobj is None:
189 raise exceptions.ifaceNotFoundError('ifname %s'
190 % i + ' not found')
191 ifaceobj.dump(self.logger)
192 else:
193 for ifacename, ifaceobjs in self.ifaceobjdict.items():
194 [i.dump(self.logger) for i in ifaceobjs]
195
196 statemanager_api = stateManager()
197
198 def reset():
199 global statemanager_api
200 statemanager_api = stateManager()