1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from spacewalk.common.rhnLog import log_debug, log_error
18 from spacewalk.common.rhnException import rhnFault
19 import rhnSQL
20 import rhnLib
21 import rpm
22
23
24
25 __packages_with_arch_and_id_sql = """
26 select distinct
27 p.id id,
28 pn.name,
29 (pe.evr).version as version,
30 (pe.evr).release as release,
31 (pe.evr).epoch as epoch,
32 pa.label as arch,
33 1 as preference
34 from
35 rhnPackageEvr pe,
36 rhnChannelPackage cp,
37 rhnPackage p,
38 rhnServerChannel sc,
39 rhnPackageName pn,
40 rhnPackageArch pa
41 where 1=1
42 and pn.name = :dep
43 and sc.server_id = :server_id
44 and p.name_id = pn.id
45 and cp.channel_id = sc.channel_id
46 and p.id = cp.package_id
47 and p.evr_id = pe.id
48 and p.package_arch_id = pa.id
49 and pe.evr = (
50 select MAX(pe1.evr)
51 from
52 rhnPackageEVR pe1,
53 rhnChannelPackage cp1,
54 rhnPackage p1,
55 rhnServerChannel sc1
56 where
57 sc1.server_id = :server_id
58 and p1.name_id = pn.id
59 and sc1.channel_id = cp1.channel_id
60 and cp1.package_id = p1.id
61 and p1.evr_id = pe1.id
62 )
63 """
64 __packages_sql = """
65 select distinct
66 pn.name,
67 (pe.evr).version as version,
68 (pe.evr).release as release,
69 (pe.evr).epoch as epoch,
70 pa.label as arch,
71 1 as preference
72 from
73 rhnPackageEvr pe,
74 rhnChannelPackage cp,
75 rhnPackage p,
76 rhnServerChannel sc,
77 rhnPackageName pn,
78 rhnPackageArch pa
79 where 1=1
80 and pn.name = :dep
81 and sc.server_id = :server_id
82 and p.name_id = pn.id
83 and cp.channel_id = sc.channel_id
84 and p.id = cp.package_id
85 and p.evr_id = pe.id
86 and p.package_arch_id = pa.id
87 and pe.evr = (
88 select MAX(pe1.evr)
89 from
90 rhnPackageEVR pe1,
91 rhnChannelPackage cp1,
92 rhnPackage p1,
93 rhnServerChannel sc1
94 where
95 sc1.server_id = :server_id
96 and p1.name_id = pn.id
97 and sc1.channel_id = cp1.channel_id
98 and cp1.package_id = p1.id
99 and p1.evr_id = pe1.id
100 )
101 """
102
103 __packages_all_sql = """
104 select distinct
105 pn.name,
106 (pe.evr).version as version,
107 (pe.evr).release as release,
108 (pe.evr).epoch as epoch,
109 pa.label as arch,
110 1 as preference
111 from
112 rhnPackageEvr pe,
113 rhnChannelPackage cp,
114 rhnPackage p,
115 rhnServerChannel sc,
116 rhnPackageName pn,
117 rhnPackageArch pa
118 where 1=1
119 and pn.name = :dep
120 and sc.server_id = :server_id
121 and p.name_id = pn.id
122 and cp.channel_id = sc.channel_id
123 and p.id = cp.package_id
124 and p.evr_id = pe.id
125 and p.package_arch_id = pa.id
126 """
127
128
129 __provides_sql = """
130 select distinct
131 pn.name,
132 (pe.evr).version as version,
133 (pe.evr).release as release,
134 (pe.evr).epoch as epoch,
135 pa.label as arch,
136 2 as preference
137 from
138 rhnServerChannel sc,
139 rhnChannelPackage cp,
140 rhnPackageProvides pr,
141 rhnPackage p,
142 rhnPackageCapability cap,
143 rhnPackageName pn,
144 rhnPackageEVR pe,
145 rhnPackageArch pa
146 where
147 sc.server_id = :server_id
148 and sc.channel_id = cp.channel_id
149 and cp.package_id = p.id
150 and cp.package_id = pr.package_id
151 and pr.package_id = p.id
152 and pr.capability_id = cap.id
153 and cap.name = :dep
154 and p.name_id = pn.id
155 and p.evr_id = pe.id
156 and p.package_arch_id = pa.id
157 -- and this package is the latest one from all the channels
158 -- this server is subscribed to.
159 and pe.evr = (
160 select MAX(pe1.evr)
161 from
162 rhnPackage p1,
163 rhnPackageEVR pe1,
164 rhnServerChannel sc1,
165 rhnChannelPackage cp1
166 where
167 sc1.server_id = :server_id
168 and sc1.channel_id = cp1.channel_id
169 and cp1.package_id = p1.id
170 and p1.name_id = pn.id
171 and p1.evr_id = pe1.id
172 )
173 """
174
175 __provides_all_sql = """
176 select distinct
177 pn.name,
178 (pe.evr).version as version,
179 (pe.evr).release as release,
180 (pe.evr).epoch as epoch,
181 pa.label as arch,
182 2 as preference
183 from
184 rhnServerChannel sc,
185 rhnChannelPackage cp,
186 rhnPackageProvides pr,
187 rhnPackage p,
188 rhnPackageCapability cap,
189 rhnPackageName pn,
190 rhnPackageEVR pe,
191 rhnPackageArch pa
192 where
193 sc.server_id = :server_id
194 and sc.channel_id = cp.channel_id
195 and cp.package_id = p.id
196 and cp.package_id = pr.package_id
197 and pr.package_id = p.id
198 and pr.capability_id = cap.id
199 and cap.name = :dep
200 and p.name_id = pn.id
201 and p.evr_id = pe.id
202 and p.package_arch_id = pa.id
203 """
204
205
206 __files_sql = """
207 select distinct
208 pn.name,
209 (pe.evr).version as version,
210 (pe.evr).release as release,
211 (pe.evr).epoch as epoch,
212 pa.label as arch,
213 3 as preference
214 from
215 rhnServerChannel sc,
216 rhnChannelPackage cp,
217 rhnPackageFile f,
218 rhnPackage p,
219 rhnPackageCapability cap,
220 rhnPackageName pn,
221 rhnPackageEVR pe,
222 rhnPackageArch pa
223 where
224 sc.server_id = :server_id
225 and sc.channel_id = cp.channel_id
226 and cp.package_id = p.id
227 and cp.package_id = f.package_id
228 and f.capability_id = cap.id
229 and cap.name = :dep
230 and p.name_id = pn.id
231 and p.evr_id = pe.id
232 and p.package_arch_id = pa.id
233 -- and this package is the latest one from all the channels
234 -- this server is subscribed to.
235 and pe.evr = (
236 select MAX(pe1.evr)
237 from
238 rhnPackage p1,
239 rhnPackageEVR pe1,
240 rhnServerChannel sc1,
241 rhnChannelPackage cp1
242 where
243 sc1.server_id = :server_id
244 and sc1.channel_id = cp1.channel_id
245 and cp1.package_id = p1.id
246 and p1.name_id = pn.id
247 and p1.evr_id = pe1.id
248 )
249 """
250
251
252 __files_all_sql = """
253 select distinct
254 pn.name,
255 (pe.evr).version as version,
256 (pe.evr).release as release,
257 (pe.evr).epoch as epoch,
258 pa.label as arch,
259 3 as preference
260 from
261 rhnServerChannel sc,
262 rhnChannelPackage cp,
263 rhnPackageFile f,
264 rhnPackage p,
265 rhnPackageCapability cap,
266 rhnPackageName pn,
267 rhnPackageEVR pe,
268 rhnPackageArch pa
269 where
270 sc.server_id = :server_id
271 and sc.channel_id = cp.channel_id
272 and cp.package_id = p.id
273 and cp.package_id = f.package_id
274 and f.capability_id = cap.id
275 and cap.name = :dep
276 and p.name_id = pn.id
277 and p.evr_id = pe.id
278 and p.package_arch_id = pa.id
279 """
280
281
283
284 - def __init__(self, deps=None, packages=None, *args, **kwargs):
288
289
291 """ Run one of the queries and return the results along with the arch. """
292 ret = {}
293 h = rhnSQL.prepare(query)
294 for dep in deps:
295 h.execute(server_id=server_id, dep=dep)
296 data = h.fetchall() or []
297 ret[dep] = [a[:6] for a in data]
298 return ret
299
300
301
302
303
304
305
306
310
311
313 """ This version of solve_dependencies allows the caller to get all of the packages that solve a dependency and limit
314 the packages that are returned to those that match the criteria defined by limit_operator and limit. This version
315 of the function also returns the architecture label of the package[s] that get returned.
316
317 limit_operator can be any of: '<', '<=', '==', '>=', or '>'.
318 limit is a a string of the format [epoch:]name-version-release
319 deps is a list of filenames that the packages that are returned must provide.
320 version is the version of the client that is calling the function.
321
322 Indexes for the tuple
323 entry_index = 0
324 preference_index = 1
325
326 Indexes for the list of package fields.
327 name_index = 0
328 version_index = 1
329 release_index = 2
330 epoch_index = 3
331 """
332
333 packages_all = {}
334 package_list = []
335
336
337 nvre = ['name', 'version', 'release', 'epoch', 'arch']
338
339
340 deplist = set(deps)
341
342 statement = "%s UNION ALL %s UNION ALL %s" % (__packages_all_sql, __provides_all_sql, __files_all_sql)
343 h = rhnSQL.prepare(statement)
344
345
346 packages = {}
347
348 for dep in deplist:
349 dict = {}
350
351
352 h.execute(server_id=server_id, dep=dep)
353
354
355 rs = h.fetchall_dict() or []
356
357
358 for record in rs:
359 if record['name'] in packages_all:
360 packages_all[record['name']].append(record)
361 else:
362 packages_all[record['name']] = [record]
363
364
365 for pl in packages_all.keys():
366
367 packages_all[pl].sort(cmp_evr)
368 package_list = package_list + packages_all[pl]
369
370 package_list.reverse()
371
372 if limit_operator is not None and limit is not None:
373 keep_list = []
374
375 try:
376 limit = rhnLib.make_evr(limit)
377 except:
378 raise
379
380 for package in package_list:
381 try:
382 keep = test_evr(package, limit_operator, limit)
383 except:
384 raise
385
386 if keep:
387 keep_list.append(package)
388
389 package_list = keep_list
390
391 list_of_tuples = []
392 for p in package_list:
393 if p['epoch'] is None:
394 p['epoch'] = ""
395
396 entry = []
397
398 list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre))
399
400
401 name_key = entry[0]
402
403 if all == 0:
404
405
406
407
408
409
410 if name_key in dict and dict[name_key][1] <= p['preference']:
411
412 continue
413
414 dict[name_key] = (entry, p['preference'])
415 else:
416 name_key = entry[0]
417 newtuple = (entry, p['preference'])
418 list_of_tuples.append(newtuple)
419
420 if all == 0:
421 packages[dep] = _avoid_compat_packages(dict)
422 else:
423
424 if len(list_of_tuples) > 1:
425 filterstring = "compat-"
426 len_filter = len(filterstring)
427 tup_keep = []
428 for tup in list_of_tuples:
429 if tup[0][0][:len_filter] != filterstring:
430 tup_keep.append(tup)
431 list_of_tuples = tup_keep
432
433 list_of_tuples.sort(lambda a, b: cmp(a[1], b[1]))
434 packages[dep] = [x[0] for x in list_of_tuples]
435
436
437 if version > 1:
438 return packages
439 else:
440 return _v2packages_to_v1list(packages, deplist, all)
441
442
460
461
463 """ Does the same thing as solve_dependencies, but also returns the architecture label with the package info.
464 E.g.
465 OUT:
466 Dictionary with key values being the filnames in deps and the values being a list of lists of package info.
467 Example := {'filename1' : [['name', 'version', 'release', 'epoch', 'architecture'],
468 ['name2', 'version2', 'release2', 'epoch2', 'architecture2']]}
469 """
470
471 nvre = ['name', 'version', 'release', 'epoch', 'arch']
472 return solve_dependencies(server_id, deps, version, nvre)
473
474
476 """ The unchanged version of solve_dependencies.
477 IN:
478 server_id := id info of the server
479 deps := list of filenames that are needed by the caller
480 version := version of the client
481
482 OUT:
483 Dictionary with key values being the filnames in deps and the values being a list of lists of package info.
484 Example := {'filename1' : [['name', 'version', 'release', 'epoch'],
485 ['name2', 'version2', 'release2', 'epoch2']]}
486 """
487 if not nvre:
488
489 nvre = ['name', 'version', 'release', 'epoch']
490
491
492 deplist = set(deps)
493
494
495
496
497
498
499 statement = "%s UNION ALL %s UNION ALL %s" % (
500 __packages_sql, __provides_sql, __files_sql)
501 h = rhnSQL.prepare(statement)
502
503
504 packages = {}
505
506 for dep in deplist:
507 dict = {}
508 h.execute(server_id=server_id, dep=dep)
509 rs = h.fetchall_dict() or []
510 if not rs:
511 log_error("Unable to solve dependency", server_id, dep)
512 packages[dep] = []
513 continue
514
515 for p in rs:
516 if p['epoch'] is None:
517 p['epoch'] = ""
518 entry = []
519 list(map(lambda f, e=entry, p=p: e.append(p[f]), nvre))
520
521 name_key = entry[0]
522 if name_key in dict and dict[name_key][1] < p['preference']:
523
524 continue
525
526 dict[name_key] = (entry, p['preference'])
527
528 packages[dep] = _avoid_compat_packages(dict)
529
530
531 if version > 1:
532 return packages
533 else:
534 return _v2packages_to_v1list(packages, deplist)
535
536
538 """ attempt to avoid giving out the compat-* packages
539 if there are other candidates
540 """
541 if len(dict) > 1:
542 matches = list(dict.keys())
543
544 compats = [a for a in matches if a[:7] == "compat-"]
545 if len(compats) > 0 and len(compats) < len(matches):
546 for p in compats:
547 del dict[p]
548
549
550 l = list(dict.values())
551 l.sort(lambda a, b: cmp(a[1], b[1]))
552 return [x[0] for x in l]
553
554
556 """ Intended to be passed to a list object's sort().
557 In: {'epoch': 'value', 'version':'value', 'release':'value'}
558 """
559 pkg1_epoch = pkg1['epoch']
560 pkg1_version = pkg1['version']
561 pkg1_release = pkg1['release']
562
563 pkg2_epoch = pkg2['epoch']
564 pkg2_version = pkg2['version']
565 pkg2_release = pkg2['release']
566
567 if pkg1_epoch is not None:
568 pkg1_epoch = str(pkg1_epoch)
569 elif pkg1_epoch == '':
570 pkg1_epoch = None
571
572 if pkg2_epoch is not None:
573 pkg2_epoch = str(pkg2_epoch)
574 elif pkg1_epoch == '':
575 pkg1_epoch = None
576
577 return rpm.labelCompare((pkg1_epoch, pkg1_version, pkg1_release),
578 (pkg2_epoch, pkg2_version, pkg2_release))
579
580
582 """ Check to see if evr is within the limit.
583 IN: evr = { 'epoch' : value, 'version':value, 'release':value }
584 operator can be any of: '<', '<=', '==', '>=', '>'
585 limit = { 'epoch' : value, 'version':value, 'release':value }
586 OUT:
587 1 or 0
588 """
589 good_operators = ['<', '<=', '==', '>=', '>']
590
591 if not operator in good_operators:
592 raise rhnFault(err_code=21,
593 err_text="Bad operator passed into test_evr.")
594
595 evr_epoch = evr['epoch']
596 evr_version = evr['version']
597 evr_release = evr['release']
598
599 limit_epoch = limit['epoch']
600 limit_version = limit['version']
601 limit_release = limit['release']
602
603 if evr_epoch is not None:
604 evr_epoch = str(evr_epoch)
605 elif evr_epoch == '':
606 evr_epoch = None
607
608 if limit_epoch is not None:
609 limit_epoch = str(limit_epoch)
610 elif limit_epoch == '':
611 limit_epoch = None
612
613 ret = rpm.labelCompare((evr_epoch, evr_version, evr_release),
614 (limit_epoch, limit_version, limit_release))
615
616 return check_against_operator(ret, operator)
617
618
620 if ret == -1:
621 if operator in (">", ">=", "=="):
622 return 0
623 if operator in ("<", "<="):
624 return 1
625 if ret == 0:
626 if operator in (">", "<"):
627 return 0
628 if operator in (">=", "<=", "=="):
629 return 1
630 if ret == 1:
631 if operator in ("<", "<=", "=="):
632 return 0
633 if operator in (">", ">="):
634 return 1
635 return 0
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670