]>
Commit | Line | Data |
---|---|---|
a6f80f0e | 1 | #!/usr/bin/python |
3e8ee54f | 2 | # |
904908bc | 3 | # Copyright 2014 Cumulus Networks, Inc. All rights reserved. |
3e8ee54f | 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 | ||
ee3fcf44 RP |
103 | self.logger.debug('%s: statemanager sync state %s' |
104 | %(ifaceobj.name, op)) | |
53b00224 | 105 | old_ifaceobjs = self.ifaceobjdict.get(ifaceobj.name) |
cb7cc592 | 106 | if 'up' in op: |
107 | if not old_ifaceobjs: | |
53b00224 | 108 | self.ifaceobjdict[ifaceobj.name] = [ifaceobj] |
31a5f4c3 | 109 | else: |
cb7cc592 | 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 | |
a6f80f0e | 137 | |
31a5f4c3 | 138 | def save_state(self): |
2c0ad8b3 RP |
139 | """ saves state (ifaceobjects) to persistent state file """ |
140 | ||
a6f80f0e | 141 | try: |
142 | with open(self.state_file, 'w') as f: | |
cb7cc592 | 143 | if not len(self.ifaceobjdict): |
525f0a30 | 144 | f.truncate(0) |
cb7cc592 | 145 | return |
525f0a30 | 146 | self.logger.debug('saving state ..') |
31a5f4c3 | 147 | for ifaceobjs in self.ifaceobjdict.values(): |
53b00224 | 148 | [pickling.save_obj(f, i) for i in ifaceobjs] |
a6f80f0e | 149 | except: |
150 | raise | |
151 | ||
5c721925 | 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() | |
a6f80f0e | 164 | |
165 | def dump(self, ifacenames=None): | |
31a5f4c3 | 166 | self.logger.debug('statemanager iface state:') |
fe0a57d3 | 167 | if ifacenames: |
a6f80f0e | 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: | |
31a5f4c3 | 175 | for ifacename, ifaceobjs in self.ifaceobjdict.items(): |
176 | [i.dump(self.logger) for i in ifaceobjs] |