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