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