14
14
Event = namedtuple ('Event' , ['action' , # A string representing an event type (see EVENT_TYPES)
15
15
'in_pkgs' , # A dictionary with packages in format {<pkg_name>: <repository>}
16
16
'out_pkgs' , # A dictionary with packages in format {<pkg_name>: <repository>}
17
+ 'from_release' , # A tuple representing a release in format (major, minor)
18
+ 'to_release' , # A tuple representing a release in format (major, minor)
17
19
'architectures' # A list of strings representing architectures
18
20
])
19
21
20
22
EVENT_TYPES = ('Present' , 'Removed' , 'Deprecated' , 'Replaced' , 'Split' , 'Merged' , 'Moved' , 'Renamed' )
23
+ RELEASES = ((7 , 5 ), (7 , 6 ), (7 , 7 ), (7 , 8 ), (8 , 0 ), (8 , 1 )) # TODO: bad, bad hardcode
21
24
22
25
23
26
def pes_events_scanner (pes_json_filepath ):
@@ -28,8 +31,7 @@ def pes_events_scanner(pes_json_filepath):
28
31
arch = api .current_actor ().configuration .architecture
29
32
arch_events = filter_events_by_architecture (events , arch )
30
33
add_output_pkgs_to_transaction_conf (transaction_configuration , arch_events )
31
- filtered_events = get_events_for_installed_pkgs_only (arch_events , installed_pkgs )
32
- tasks = process_events (filtered_events , installed_pkgs )
34
+ tasks = process_events (arch_events , installed_pkgs )
33
35
filter_out_transaction_conf_pkgs (tasks , transaction_configuration )
34
36
produce_messages (tasks )
35
37
@@ -151,6 +153,13 @@ def parse_entry(entry):
151
153
{
152
154
'action': 3,
153
155
'id': 15,
156
+ 'initial_release': { # can be None
157
+ 'z_stream': None,
158
+ 'major_version': 7,
159
+ 'tag': None,
160
+ 'os_name': 'RHEL',
161
+ 'minor_version': 7
162
+ },
154
163
'release': {
155
164
'z_stream': None,
156
165
'major_version': 8,
@@ -165,9 +174,9 @@ def parse_entry(entry):
165
174
'name': 'espeak',
166
175
'repository': 'rhel7-optional'
167
176
}
168
- ]
169
- }
170
- 'out_packageset': { # 'out_packageset' can be None
177
+ ]
178
+ },
179
+ 'out_packageset': { # can be None
171
180
'set_id': 21,
172
181
'package': [
173
182
{
@@ -176,8 +185,10 @@ def parse_entry(entry):
176
185
}
177
186
]
178
187
},
179
- 'architectures': [ # ' can be empty'
188
+ 'architectures': [ # can be empty
180
189
'x86_64',
190
+ 'aarch64',
191
+ 'ppc64le',
181
192
's390x'
182
193
]
183
194
}
@@ -186,9 +197,11 @@ def parse_entry(entry):
186
197
action = parse_action (entry ['action' ])
187
198
in_pkgs = parse_packageset (entry .get ('in_packageset' ) or {})
188
199
out_pkgs = parse_packageset (entry .get ('out_packageset' ) or {})
200
+ from_release = parse_release (entry .get ('initial_release' ) or {})
201
+ to_release = parse_release (entry .get ('release' ) or {})
189
202
architectures = parse_architectures (entry .get ('architectures' ) or [])
190
203
191
- return Event (action , in_pkgs , out_pkgs , architectures )
204
+ return Event (action , in_pkgs , out_pkgs , from_release , to_release , architectures )
192
205
193
206
194
207
def parse_action (action_id ):
@@ -208,32 +221,32 @@ def parse_packageset(packageset):
208
221
return {p ['name' ]: p ['repository' ].lower () for p in packageset .get ('package' , [])}
209
222
210
223
224
+ def parse_release (release ):
225
+ return (release ['major_version' ], release ['minor_version' ]) if release else (0 , 0 )
226
+
227
+
211
228
def parse_architectures (architectures ):
212
229
for arch in architectures :
213
230
if arch not in architecture .ARCH_ACCEPTED :
214
231
raise ValueError ('Found event with invalid architecture: {}' . format (arch ))
215
232
return architectures
216
233
217
234
218
- def get_events_for_installed_pkgs_only ( events , installed_rh_pkgs ):
219
- """
220
- Get those PES events that have at least one of the event's "input" packages installed and signed by Red Hat.
221
-
222
- :param events: List of Event tuples, where each event contains event type and input/output pkgs
223
- :param installed_rh_pkgs: Set of names of the installed Red Hat-signed packages
224
- :return: List of Event tuples, not including those events whose input packages are not installed
225
- """
235
+ def is_event_relevant ( event , installed_pkgs , tasks ):
236
+ """Determine if event is applicable given the installed packages and tasks planned so far."""
237
+ for package in event . in_pkgs . keys ():
238
+ if package in tasks [ 'to_remove' ]:
239
+ return False
240
+ if package not in installed_pkgs and package not in tasks [ 'to_install' ]:
241
+ return False
242
+ return True
226
243
227
- filtered = []
228
- for event in events :
229
- if is_at_least_one_event_input_pkg_installed (installed_rh_pkgs , event .in_pkgs ):
230
- filtered .append (event )
231
-
232
- return filtered
233
244
234
-
235
- def is_at_least_one_event_input_pkg_installed (installed_rh_pkgs , event_in_pkgs ):
236
- return installed_rh_pkgs .intersection (set (event_in_pkgs .keys ()))
245
+ def add_packages_to_tasks (tasks , packages , key ):
246
+ verb = key [3 :].upper () # 'to_remove' -> 'REMOVE' and so on
247
+ if packages :
248
+ api .current_logger ().debug ('{v} {p}' .format (v = verb , p = ', ' .join (packages )))
249
+ tasks [key ].update (packages )
237
250
238
251
239
252
def process_events (events , installed_pkgs ):
@@ -248,31 +261,83 @@ def process_events(events, installed_pkgs):
248
261
tasks = { # Contains dicts in format {<pkg_name>: <repository>}
249
262
'to_keep' : {},
250
263
'to_install' : {},
251
- 'to_remove' : {}}
252
- for event in events :
253
- if event .action in ('Deprecated' , 'Present' ):
254
- # Add these packages to to_keep to make sure the repo they're in on RHEL 8 gets enabled
255
- tasks ['to_keep' ].update (event .in_pkgs )
256
-
257
- if event .action == 'Moved' :
258
- # Add these packages to to_keep to make sure the repo they're in on RHEL 8 gets enabled
259
- # We don't care about the "in_pkgs" as it contains always just one pkg - the same as the "out" pkg
260
- tasks ['to_keep' ].update (event .out_pkgs )
261
-
262
- if event .action in ('Split' , 'Merged' , 'Renamed' , 'Replaced' ):
263
- non_installed_out_pkgs = filter_out_installed_pkgs (event .out_pkgs , installed_pkgs )
264
- tasks ['to_install' ].update (non_installed_out_pkgs )
265
- # Add the already installed "out" pkgs to to_keep to make sure the repo they're in on RHEL 8 gets enabled
266
- installed_out_pkgs = get_installed_out_pkgs (event .out_pkgs , installed_pkgs )
267
- tasks ['to_keep' ].update (installed_out_pkgs )
268
- if event .action in ('Split' , 'Merged' ):
269
- # Uninstall those RHEL 7 pkgs that are no longer on RHEL 8
270
- in_pkgs_without_out_pkgs = filter_out_out_pkgs (event .in_pkgs , event .out_pkgs )
271
- tasks ['to_remove' ].update (in_pkgs_without_out_pkgs )
272
-
273
- if event .action in ('Renamed' , 'Replaced' , 'Removed' ):
274
- # Uninstall those RHEL 7 pkgs that are no longer on RHEL 8
275
- tasks ['to_remove' ].update (event .in_pkgs )
264
+ 'to_remove' : {}
265
+ }
266
+ for release in RELEASES :
267
+ current = {
268
+ 'to_keep' : {},
269
+ 'to_install' : {},
270
+ 'to_remove' : {}
271
+ }
272
+ release_events = [e for e in events if e .to_release == release ]
273
+ api .current_logger ().debug ('---- Processing {n} eligible events for release {r}' .format (
274
+ n = len (release_events ), r = release ))
275
+ for event in release_events :
276
+ if is_event_relevant (event , installed_pkgs , tasks ):
277
+ if event .action in ('Deprecated' , 'Present' ):
278
+ # Add these packages to to_keep to make sure the repo they're in on RHEL 8 gets enabled
279
+ add_packages_to_tasks (current , event .in_pkgs , 'to_keep' )
280
+
281
+ if event .action == 'Moved' :
282
+ # Add these packages to to_keep to make sure the repo they're in on RHEL 8 gets enabled
283
+ # We don't care about the "in_pkgs" as it contains always just one pkg - the same as the "out" pkg
284
+ add_packages_to_tasks (current , event .out_pkgs , 'to_keep' )
285
+
286
+ if event .action in ('Split' , 'Merged' , 'Renamed' , 'Replaced' ):
287
+ non_installed_out_pkgs = filter_out_installed_pkgs (event .out_pkgs , installed_pkgs )
288
+ add_packages_to_tasks (current , non_installed_out_pkgs , 'to_install' )
289
+ # Add already installed "out" pkgs to to_keep to ensure the repo they're in on RHEL 8 gets enabled
290
+ installed_out_pkgs = get_installed_event_pkgs (event .out_pkgs , installed_pkgs )
291
+ add_packages_to_tasks (current , installed_out_pkgs , 'to_keep' )
292
+
293
+ if event .action in ('Split' , 'Merged' ):
294
+ # Uninstall those RHEL 7 pkgs that are no longer on RHEL 8
295
+ in_pkgs_without_out_pkgs = filter_out_out_pkgs (event .in_pkgs , event .out_pkgs )
296
+ add_packages_to_tasks (current , in_pkgs_without_out_pkgs , 'to_remove' )
297
+
298
+ if event .action in ('Renamed' , 'Replaced' , 'Removed' ):
299
+ add_packages_to_tasks (current , event .in_pkgs , 'to_remove' )
300
+
301
+ do_not_remove = set ()
302
+ for package in current ['to_remove' ]:
303
+ if package in tasks ['to_keep' ]:
304
+ api .current_logger ().warning (
305
+ '{p} :: {r} to be kept / currently removed - removing package' .format (
306
+ p = package , r = current ['to_remove' ][package ]))
307
+ del tasks ['to_keep' ][package ]
308
+ elif package in tasks ['to_install' ]:
309
+ api .current_logger ().warning (
310
+ '{p} :: {r} to be installed / currently removed - ignoring tasks' .format (
311
+ p = package , r = current ['to_remove' ][package ]))
312
+ del tasks ['to_install' ][package ]
313
+ do_not_remove .add (package )
314
+ for package in do_not_remove :
315
+ del current ['to_remove' ][package ]
316
+
317
+ for package in current ['to_install' ]:
318
+ if package in tasks ['to_remove' ]:
319
+ api .current_logger ().warning (
320
+ '{p} :: {r} to be removed / currently installed - keeping package' .format (
321
+ p = package , r = current ['to_install' ][package ]))
322
+ current ['to_keep' ][package ] = current ['to_install' ][package ]
323
+ del tasks ['to_remove' ][package ]
324
+ del current ['to_install' ][package ]
325
+
326
+ for package in current ['to_keep' ]:
327
+ if package in tasks ['to_remove' ]:
328
+ api .current_logger ().warning (
329
+ '{p} :: {r} to be removed / currently kept - keeping package' .format (
330
+ p = package , r = current ['to_keep' ][package ]))
331
+ del tasks ['to_remove' ][package ]
332
+
333
+ verbs = {'to_keep' : 'kept' , 'to_install' : 'installed' , 'to_remove' : 'removed' }
334
+ for key in 'to_keep' , 'to_install' , 'to_remove' :
335
+ for package in current [key ]:
336
+ if package in tasks [key ]:
337
+ api .current_logger ().warning (
338
+ '{p} :: {r} to be {v} TWICE - internal bug (not serious, continuing)' .format (
339
+ p = package , r = current [key ][package ], v = verbs [key ]))
340
+ tasks [key ].update (current [key ])
276
341
277
342
map_repositories (tasks ['to_install' ])
278
343
map_repositories (tasks ['to_keep' ])
@@ -287,14 +352,14 @@ def filter_out_installed_pkgs(event_out_pkgs, installed_pkgs):
287
352
return {k : v for k , v in event_out_pkgs .items () if k not in installed_pkgs }
288
353
289
354
290
- def get_installed_out_pkgs ( event_out_pkgs , installed_pkgs ):
355
+ def get_installed_event_pkgs ( event_pkgs , installed_pkgs ):
291
356
"""
292
- Get those event's "out" packages which are already installed.
357
+ Get those event's "in" or " out" packages which are already installed.
293
358
294
359
Even though we don't want to install the already installed pkgs, to be able to upgrade them to their RHEL 8 version
295
360
we need to know in which repos they are and enable such repos.
296
361
"""
297
- return {k : v for k , v in event_out_pkgs .items () if k in installed_pkgs }
362
+ return {k : v for k , v in event_pkgs .items () if k in installed_pkgs }
298
363
299
364
300
365
def filter_out_out_pkgs (event_in_pkgs , event_out_pkgs ):
0 commit comments