]>
Commit | Line | Data |
---|---|---|
a6f80f0e | 1 | #!/usr/bin/python |
3e8ee54f | 2 | # |
d486dd0d | 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. |
3e8ee54f | 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com |
5 | # | |
6 | # stateManager -- | |
7 | # interface state manager | |
8 | # | |
d486dd0d JF |
9 | |
10 | import os | |
a6f80f0e | 11 | import cPickle |
a6f80f0e | 12 | import logging |
d486dd0d JF |
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 | ||
a6f80f0e | 23 | |
24 | class pickling(): | |
53b00224 | 25 | """ class with helper methods for pickling/unpickling iface objects """ |
a6f80f0e | 26 | |
27 | @classmethod | |
28 | def save(cls, filename, list_of_objects): | |
2c0ad8b3 | 29 | """ pickle a list of iface objects """ |
a6f80f0e | 30 | try: |
31 | with open(filename, 'w') as f: | |
32 | for obj in list_of_objects: | |
5c721925 | 33 | cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL) |
a6f80f0e | 34 | except: |
35 | raise | |
36 | ||
37 | @classmethod | |
38 | def save_obj(cls, f, obj): | |
2c0ad8b3 | 39 | """ pickle iface object """ |
a6f80f0e | 40 | try: |
5c721925 | 41 | cPickle.dump(obj, f, cPickle.HIGHEST_PROTOCOL) |
a6f80f0e | 42 | except: |
43 | raise | |
44 | ||
a6f80f0e | 45 | @classmethod |
46 | def load(cls, filename): | |
2c0ad8b3 | 47 | """ load picked iface object """ |
a6f80f0e | 48 | with open(filename, 'r') as f: |
49 | while True: | |
50 | try: yield cPickle.load(f) | |
51 | except EOFError: break | |
52 | except: raise | |
53 | ||
a6f80f0e | 54 | class stateManager(): |
2c0ad8b3 RP |
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 | """ | |
a6f80f0e | 63 | |
a690dfae | 64 | state_dir = '/var/tmp/network/' |
2c0ad8b3 RP |
65 | """directory where the state file is stored """ |
66 | ||
a690dfae | 67 | state_filename = 'ifstatenew' |
2c0ad8b3 | 68 | """name of the satefile """ |
a6f80f0e | 69 | |
a33e94f7 RP |
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 | ||
a6f80f0e | 76 | def __init__(self): |
2c0ad8b3 RP |
77 | """ Initializes statemanager internal state |
78 | ||
79 | which includes a dictionary of last pickled iface objects | |
80 | """ | |
a6f80f0e | 81 | self.ifaceobjdict = OrderedDict() |
82 | self.logger = logging.getLogger('ifupdown.' + | |
83 | self.__class__.__name__) | |
a690dfae | 84 | if not os.path.exists(self.state_dir): |
85 | os.mkdir(self.state_dir) | |
a33e94f7 RP |
86 | if not os.path.exists(self.state_rundir): |
87 | os.mkdir(self.state_rundir) | |
a690dfae | 88 | self.state_file = self.state_dir + self.state_filename |
a6f80f0e | 89 | |
90 | def save_ifaceobj(self, ifaceobj): | |
62ddec8b | 91 | self.ifaceobjdict.setdefault(ifaceobj.name, |
5c721925 | 92 | []).append(ifaceobj) |
a6f80f0e | 93 | |
94 | def read_saved_state(self, filename=None): | |
2c0ad8b3 RP |
95 | """This member function reads saved iface objects |
96 | ||
97 | Kwargs: | |
98 | filename (str): name of the state file | |
99 | """ | |
100 | ||
a6f80f0e | 101 | pickle_filename = filename |
fe0a57d3 | 102 | if not pickle_filename: |
a6f80f0e | 103 | pickle_filename = self.state_file |
a6f80f0e | 104 | if not os.path.exists(pickle_filename): |
105 | return | |
a6f80f0e | 106 | for ifaceobj in pickling.load(pickle_filename): |
107 | self.save_ifaceobj(ifaceobj) | |
a6f80f0e | 108 | |
5c721925 | 109 | def get_ifaceobjs(self, ifacename): |
110 | return self.ifaceobjdict.get(ifacename) | |
111 | ||
cb7cc592 | 112 | def ifaceobj_sync(self, ifaceobj, op): |
2c0ad8b3 RP |
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 | ||
ee3fcf44 RP |
120 | self.logger.debug('%s: statemanager sync state %s' |
121 | %(ifaceobj.name, op)) | |
53b00224 | 122 | old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.name) |
cb7cc592 | 123 | if 'up' in op: |
124 | if not old_ifaceobjs: | |
53b00224 | 125 | self.ifaceobjdict[ifaceobj.name] = [ifaceobj] |
31a5f4c3 | 126 | else: |
cb7cc592 | 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 | |
a6f80f0e | 154 | |
31a5f4c3 | 155 | def save_state(self): |
2c0ad8b3 RP |
156 | """ saves state (ifaceobjects) to persistent state file """ |
157 | ||
a6f80f0e | 158 | try: |
159 | with open(self.state_file, 'w') as f: | |
cb7cc592 | 160 | if not len(self.ifaceobjdict): |
525f0a30 | 161 | f.truncate(0) |
cb7cc592 | 162 | return |
525f0a30 | 163 | self.logger.debug('saving state ..') |
31a5f4c3 | 164 | for ifaceobjs in self.ifaceobjdict.values(): |
53b00224 | 165 | [pickling.save_obj(f, i) for i in ifaceobjs] |
a33e94f7 | 166 | open('%s/%s' %(self.state_rundir, self.state_runlockfile), 'w').close() |
a6f80f0e | 167 | except: |
168 | raise | |
169 | ||
5c721925 | 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() | |
a6f80f0e | 182 | |
183 | def dump(self, ifacenames=None): | |
31a5f4c3 | 184 | self.logger.debug('statemanager iface state:') |
fe0a57d3 | 185 | if ifacenames: |
a6f80f0e | 186 | for i in ifacenames: |
187 | ifaceobj = self.ifaces.get(i) | |
188 | if ifaceobj is None: | |
afe51251 | 189 | raise exceptions.ifaceNotFoundError('ifname %s' |
d486dd0d | 190 | % i + ' not found') |
a6f80f0e | 191 | ifaceobj.dump(self.logger) |
192 | else: | |
31a5f4c3 | 193 | for ifacename, ifaceobjs in self.ifaceobjdict.items(): |
194 | [i.dump(self.logger) for i in ifaceobjs] | |
55072bd1 ST |
195 | |
196 | statemanager_api = stateManager() | |
d486dd0d JF |
197 | |
198 | def reset(): | |
199 | global statemanager_api | |
200 | statemanager_api = stateManager() |