1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import sys
17 import os
18 try:
19
20 import cPickle
21 except ImportError:
22 import pickle as cPickle
23 import time
24 import traceback
25
26 from spacewalk.common.usix import LongType
27
28
29
30
31
32 CACHE_DATA_PATH = '/var/cache/rhn/virt_state.cache'
33 CACHE_EXPIRE_SECS = 60 * 60 * 6
34
35
36
37
38
40
41
42
43
44
45 - def __init__(self, domain_data, debug = 0):
46 """
47 This method creates a new poller state based on the provided domain
48 list. The domain_data list should be in the form returned from
49 poller.poll_hypervisor. That is,
50
51 { uuid : { 'name' : '...',
52 'uuid' : '...',
53 'virt_type' : '...',
54 'memory_size' : '...',
55 'vcpus' : '...',
56 'state' : '...' }, ... }
57 """
58 self.__debug = debug
59
60
61 self._load_state()
62 self.__new_domain_data = domain_data
63
64
65
66 self._compare_domain_data()
67
68 self._log_debug("Added: %s" % repr(self.__added))
69 self._log_debug("Removed: %s" % repr(self.__removed))
70 self._log_debug("Modified: %s" % repr(self.__modified))
71
73 """
74 Updates the cache on disk with the latest domain data.
75 """
76 self._save_state()
77
79 """
80 Returns true if this cache is expired.
81 """
82 if self.__expire_time is None:
83 return False
84 else:
85 return LongType(time.time()) >= self.__expire_time
86
88 return self.__added or self.__removed or self.__modified
89
91 """
92 Returns a list of uuids for each domain that has been added since the
93 last state poll.
94 """
95 return self.__added
96
98 """
99 Returns a list of uuids for each domain that has been modified since
100 the last state poll.
101 """
102 return self.__modified
103
105 """
106 Returns a list of uuids for each domain that has been removed since
107 the last state poll.
108 """
109 return self.__removed
110
111
112
113
114
116 """
117 Loads the last hypervisor state from disk.
118 """
119
120 cache_file = None
121 try:
122 cache_file = open(CACHE_DATA_PATH, 'rb')
123 except IOError:
124 ioe = sys.exc_info()[1]
125
126
127 self._log_debug("Could not open cache file '%s': %s" % \
128 (CACHE_DATA_PATH, str(ioe)))
129
130
131 state = {}
132 if cache_file:
133 try:
134 state = cPickle.load(cache_file)
135 except cPickle.PickleError:
136 pe = sys.exc_info()[1]
137
138
139 self._log_debug("Error occurred while loading state: %s" % \
140 str(pe))
141 except EOFError:
142 self._log_debug("Unexpected EOF. Probably an empty file.")
143 cache_file.close()
144
145 cache_file.close()
146
147 if state:
148 self._log_debug("Loaded state: %s" % repr(state))
149
150 self.__expire_time = LongType(state['expire_time'])
151
152
153
154 if self.is_expired():
155 self.__old_domain_data = None
156 os.unlink(CACHE_DATA_PATH)
157 else:
158 self.__old_domain_data = state['domain_data']
159
160 else:
161 self.__old_domain_data = None
162 self.__expire_time = None
163
165 """
166 Saves the given polling state to disk.
167 """
168
169 cache_dir_path = os.path.dirname(CACHE_DATA_PATH)
170 if not os.path.exists(cache_dir_path):
171 os.makedirs(cache_dir_path, int('0700', 8))
172
173 state = {}
174 state['domain_data'] = self.__new_domain_data
175 if self.__expire_time is None or self.is_expired():
176 state['expire_time'] = LongType(time.time()) + CACHE_EXPIRE_SECS
177 else:
178 state['expire_time'] = self.__expire_time
179
180
181
182 cache_file = open(CACHE_DATA_PATH, "wb")
183 cPickle.dump(state, cache_file)
184 cache_file.close()
185
187 """
188 Compares the old domain_data to the new domain_data. Returns a tuple
189 of lists, relative to the new domain_data:
190
191 (added, removed, modified)
192 """
193 self.__added = {}
194 self.__removed = {}
195 self.__modified = {}
196
197
198 if self.__new_domain_data:
199 for (uuid, new_properties) in self.__new_domain_data.items():
200 if not self.__old_domain_data or uuid not in self.__old_domain_data:
201
202 self.__added[uuid] = self.__new_domain_data[uuid]
203 else:
204 old_properties = self.__old_domain_data[uuid]
205 if old_properties != new_properties:
206 self.__modified[uuid] = self.__new_domain_data[uuid]
207
208
209 if self.__old_domain_data:
210 for uuid in self.__old_domain_data.keys():
211 if not self.__new_domain_data or uuid not in self.__new_domain_data:
212
213 self.__removed[uuid] = self.__old_domain_data[uuid]
214
216 if self.__debug:
217 print("DEBUG: " + str(msg))
218 if include_trace:
219 e_info = sys.exc_info()
220 traceback.print_exception(e_info[0], e_info[1], e_info[2])
221