1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import os
16 import shutil
17 import sys
18 from spacewalk.common.rhnConfig import CFG
19 from spacewalk.common.rhnLog import log_debug, log_error
20 from spacewalk.satellite_tools.progress_bar import ProgressBar
21 from spacewalk.server.rhnPackage import unlink_package_file
22 from spacewalk.server import rhnSQL
23
24
26 sql = """
27 select distinct S.org_id, S.id, S.name
28 from rhnChannel c inner join
29 rhnServerChannel sc on c.id = sc.channel_id inner join
30 rhnServer s on s.id = sc.server_id
31 where c.label in (%s)
32 """
33 params, bind_params = _bind_many(labels)
34 bind_params = ', '.join(bind_params)
35 h = rhnSQL.prepare(sql % (bind_params))
36 h.execute(**params)
37 server_list = h.fetchall_dict()
38 if not server_list:
39 return 0
40
41 if unsubscribe:
42 return __unsubscribeServers(labels)
43
44 print("\nCurrently there are systems subscribed to one or more of the specified channels.")
45 print("If you would like to automatically unsubscribe these systems, simply use the --unsubscribe flag.\n")
46 print("The following systems were found to be subscribed:")
47
48 print("%-8s %-14s name" % ('org_id', 'id'))
49 print("-" * 32)
50 for server in server_list:
51 print("%-8s %-14s %s" % (server['org_id'], server['id'], server['name']))
52
53 return len(server_list)
54
55
57 sql = """
58 select distinct sc.server_id as server_id, C.id as channel_id, c.parent_channel, c.label
59 from rhnChannel c inner join
60 rhnServerChannel sc on c.id = sc.channel_id
61 where c.label in (%s) order by C.parent_channel
62 """
63 params, bind_params = _bind_many(labels)
64 bind_params = ', '.join(bind_params)
65 h = rhnSQL.prepare(sql % (bind_params))
66 h.execute(**params)
67 server_channel_list = h.fetchall_dict()
68
69 channel_counts = {}
70 for i in server_channel_list:
71 if i['label'] in channel_counts:
72 channel_counts[i['label']] = channel_counts[i['label']] + 1
73 else:
74 channel_counts[i['label']] = 1
75 print("\nThe following channels will have their systems unsubscribed:")
76 channel_list = channel_counts.keys()
77 channel_list.sort()
78 for i in channel_list:
79 print("%-40s %-8s" % (i, channel_counts[i]))
80
81 pb = ProgressBar(prompt='Unsubscribing: ', endTag=' - complete',
82 finalSize=len(server_channel_list), finalBarLength=40, stream=sys.stdout)
83 pb.printAll(1)
84
85 unsubscribe_server_proc = rhnSQL.Procedure("rhn_channel.unsubscribe_server")
86 for i in server_channel_list:
87 unsubscribe_server_proc(i['server_id'], i['channel_id'])
88 pb.addTo(1)
89 pb.printIncrement()
90 pb.printComplete()
91
92
94 sql = """
95 select K.org_id, K.label
96 from rhnKSData K inner join
97 rhnKickstartDefaults KD on KD.kickstart_id = K.id inner join
98 rhnKickstartableTree KT on KT.id = KD.kstree_id inner join
99 rhnChannel c on c.id = KT.channel_id
100 where c.label in (%s)
101 """
102 params, bind_params = _bind_many(labels)
103 bind_params = ', '.join(bind_params)
104 h = rhnSQL.prepare(sql % (bind_params))
105 h.execute(**params)
106 kickstart_list = h.fetchall_dict()
107
108 if not kickstart_list:
109 return 0
110
111 print("The following kickstarts are associated with one of the specified channels. " +
112 "Please remove these or change their associated base channel.\n")
113 print("%-8s label" % 'org_id')
114 print("-" * 20)
115 for kickstart in kickstart_list:
116 print("%-8s %s" % (kickstart['org_id'], kickstart['label']))
117
118 return len(kickstart_list)
119
120
122 sql = """
123 select c1.label, c2.label parent_channel
124 from rhnChannel c1 left outer join rhnChannel c2 on c1.parent_channel = c2.id
125 order by c2.label desc, c1.label asc
126 """
127 h = rhnSQL.prepare(sql)
128 h.execute()
129 labels = {}
130 parents = {}
131 while 1:
132 row = h.fetchone_dict()
133 if not row:
134 break
135 parent_channel = row['parent_channel']
136 labels[row['label']] = parent_channel
137 if not parent_channel:
138 parents[row['label']] = []
139
140 if parent_channel:
141 parents[parent_channel].append(row['label'])
142
143 return labels, parents
144
145
156
157
158 -def delete_channels(channelLabels, force=0, justdb=0, skip_packages=0, skip_channels=0,
159 skip_kickstart_trees=0, just_kickstart_trees=0):
160
161 if not channelLabels:
162 return
163
164 rpms_ids = list_packages(channelLabels, force=force, sources=0)
165 rpms_paths = _get_package_paths(rpms_ids, sources=0)
166 srpms_ids = list_packages(channelLabels, force=force, sources=1)
167 srpms_paths = _get_package_paths(srpms_ids, sources=1)
168
169 if not skip_packages and not just_kickstart_trees:
170 _delete_srpms(srpms_ids)
171 _delete_rpms(rpms_ids)
172
173 if not skip_kickstart_trees and not justdb:
174 _delete_ks_files(channelLabels)
175
176 if not justdb and not skip_packages and not just_kickstart_trees:
177 _delete_files(rpms_paths + srpms_paths)
178
179
180 h = rhnSQL.prepare("""
181 select id, parent_channel
182 from rhnChannel
183 where label = :label
184 order by parent_channel""")
185 channel_ids = []
186 for label in channelLabels:
187 h.execute(label=label)
188 row = h.fetchone_dict()
189 if not row:
190 break
191 channel_id = row['id']
192 if row['parent_channel']:
193
194 channel_ids.insert(0, channel_id)
195 else:
196 channel_ids.append(channel_id)
197
198 if not channel_ids:
199 return
200
201 indirect_tables = [
202 ['rhnKickstartableTree', 'channel_id', 'rhnKSTreeFile', 'kstree_id'],
203 ]
204 query = """
205 delete from %(table_2)s where %(link_field)s in (
206 select id
207 from %(table_1)s
208 where %(channel_field)s = :channel_id
209 )
210 """
211 for e in indirect_tables:
212 args = {
213 'table_1': e[0],
214 'channel_field': e[1],
215 'table_2': e[2],
216 'link_field': e[3],
217 }
218 h = rhnSQL.prepare(query % args)
219 h.executemany(channel_id=channel_ids)
220
221 tables = [
222 ['rhnErrataFileChannel', 'channel_id'],
223 ['rhnErrataNotificationQueue', 'channel_id'],
224 ['rhnChannelErrata', 'channel_id'],
225 ['rhnChannelPackage', 'channel_id'],
226 ['rhnRegTokenChannels', 'channel_id'],
227 ['rhnServerProfile', 'base_channel'],
228 ['rhnKickstartableTree', 'channel_id'],
229 ]
230
231 if not skip_channels:
232 tables.extend([
233 ['rhnChannelFamilyMembers', 'channel_id'],
234 ['rhnDistChannelMap', 'channel_id'],
235 ['rhnReleaseChannelMap', 'channel_id'],
236 ['rhnChannel', 'id'],
237 ])
238
239 if just_kickstart_trees:
240 tables = [['rhnKickstartableTree', 'channel_id']]
241
242 query = "delete from %s where %s = :channel_id"
243 for table, field in tables:
244 log_debug(3, "Processing table %s" % table)
245 h = rhnSQL.prepare(query % (table, field))
246 h.executemany(channel_id=channel_ids)
247
248 if not justdb and not just_kickstart_trees:
249 __deleteRepoData(channelLabels)
250
251
253 directory = '/var/cache/' + CFG.repomd_path_prefix
254 for label in labels:
255 if os.path.isdir(directory + '/' + label):
256 shutil.rmtree(directory + '/' + label)
257
258
260 """List packages in given org outside any channel"""
261
262 if sources:
263 query = """
264 select ps.id from rhnPackage p inner join
265 rhnPackageSource ps on p.source_rpm_id = ps.source_rpm_id left join
266 rhnChannelPackage cp on cp.package_id = p.id
267 where cp.channel_id is null
268 """
269 else:
270 query = """
271 select p.id from rhnPackage p left join
272 rhnChannelPackage cp on cp.package_id = p.id
273 where cp.channel_id is null
274 """
275
276 if org_id:
277 query += """
278 and p.org_id = :org_id
279 """
280 if sources:
281 query += """
282 and p.org_id = ps.org_id
283 """
284 else:
285 query += """
286 and p.org_id is null
287 """
288 if sources:
289 query += """
290 and ps.org_id is null
291 """
292
293 h = rhnSQL.prepare(query)
294 h.execute(org_id=org_id)
295
296 return [x['id'] for x in h.fetchall_dict() or []]
297
298
300 "List the source ids for the channels"
301 if sources:
302 packages = "srpms"
303 else:
304 packages = "rpms"
305 log_debug(3, "Listing %s" % packages)
306 if not channelLabels:
307 return []
308
309 params, bind_params = _bind_many(channelLabels)
310 bind_params = ', '.join(bind_params)
311
312 if sources:
313 templ = _templ_srpms()
314 else:
315 templ = _templ_rpms()
316
317 if force:
318 query = templ % ("", bind_params)
319 else:
320 if CFG.DB_BACKEND == 'oracle':
321 minus_op = 'MINUS'
322 else:
323 minus_op = 'EXCEPT'
324 query = """
325 %s
326 %s
327 %s
328 """ % (
329 templ % ("", bind_params),
330 minus_op,
331 templ % ("not", bind_params),
332 )
333 h = rhnSQL.prepare(query)
334 h.execute(**params)
335 return [x['id'] for x in h.fetchall_dict() or []]
336
337
339 "Returns a template for querying rpms"
340 log_debug(4, "Generating template for querying rpms")
341 return """\
342 select cp.package_id id
343 from rhnChannel c, rhnChannelPackage cp
344 where c.label %s in (%s)
345 and cp.channel_id = c.id"""
346
347
349 "Returns a template for querying srpms"
350 log_debug(4, "Generating template for querying srpms")
351 return """\
352 select ps.id id
353 from rhnPackage p,
354 rhnPackageSource ps,
355 rhnChannelPackage cp,
356 rhnChannel c
357 where c.label %s in (%s)
358 and c.id = cp.channel_id
359 and cp.package_id = p.id
360 and p.source_rpm_id = ps.source_rpm_id
361 and ((p.org_id is null and ps.org_id is null) or
362 p.org_id = ps.org_id)"""
363
364
366 """Blow away rhnPackageSource and rhnFile entries.
367 """
368 if not srcPackageIds:
369 return
370
371 h = rhnSQL.prepare("""
372 delete
373 from rhnPackageSource
374 where id = :id
375 """)
376 count = h.executemany(id=srcPackageIds)
377 if not count:
378 count = 0
379 log_debug(2, "Successfully deleted %s/%s source package ids" % (
380 count, len(srcPackageIds)))
381
382
384 if not packageIds:
385 return
386 group = 300
387 toDel = packageIds[:]
388 print "Deleting package metadata (" + str(len(toDel)) + "):"
389 pb = ProgressBar(prompt='Removing: ', endTag=' - complete',
390 finalSize=len(packageIds), finalBarLength=40, stream=sys.stdout)
391 pb.printAll(1)
392
393 while toDel:
394 _delete_rpm_group(toDel[:group])
395 del toDel[:group]
396 pb.addTo(group)
397 pb.printIncrement()
398 pb.printComplete()
399
400
402
403 references = [
404 'rhnChannelPackage',
405 'rhnErrataPackage',
406 'rhnErrataPackageTMP',
407 'rhnPackageChangelogRec',
408 'rhnPackageConflicts',
409 'rhnPackageFile',
410 'rhnPackageObsoletes',
411 'rhnPackageProvides',
412 'rhnPackageRequires',
413 'rhnPackageRecommends',
414 'rhnPackageSuggests',
415 'rhnPackageSupplements',
416 'rhnPackageEnhances',
417 'rhnPackageBreaks',
418 'rhnPackagePredepends',
419 'rhnServerNeededCache',
420 ]
421 deleteStatement = "delete from %s where package_id = :package_id"
422 for table in references:
423 h = rhnSQL.prepare(deleteStatement % table)
424 count = h.executemany(package_id=packageIds)
425 log_debug(3, "Deleted from %s: %d rows" % (table, count))
426 deleteStatement = "delete from rhnPackage where id = :package_id"
427 h = rhnSQL.prepare(deleteStatement)
428 count = h.executemany(package_id=packageIds)
429 if count:
430 log_debug(2, "DELETED package id %s" % str(packageIds))
431 else:
432 log_error("No such package id %s" % str(packageIds))
433 rhnSQL.commit()
434
435
443
444
446 h = {}
447 lr = []
448 for i, item in enumerate(l):
449 key = 'p_%s' % i
450 h[key] = item
451 lr.append(':' + key)
452 return h, lr
453
454
456 if sources:
457 table = "rhnPackageSource"
458 else:
459 table = "rhnPackage"
460 h = rhnSQL.prepare("select path from %s where id = :package_id" % table)
461 pdict = {}
462 for package_id in package_ids:
463 h.execute(package_id=package_id)
464 row = h.fetchone_dict()
465 if not row:
466 continue
467 if not row['path']:
468 continue
469 pdict[row['path']] = None
470
471 return pdict.keys()
472
473
475 sql = """
476 select kt.base_path
477 from rhnChannel c
478 join rhnKickstartableTree kt on c.id = kt.channel_id
479 where c.label in (%s) and not exists (
480 select 1
481 from rhnKickstartableTree ktx
482 join rhnChannel cx on cx.id = ktx.channel_id
483 where replace(ktx.base_path, :mnt_point, '') =
484 replace(kt.base_path, :mnt_point, '')
485 and cx.label not in (%s))
486 """
487
488 params, bind_params = _bind_many(channel_labels)
489 params['mnt_point'] = CFG.MOUNT_POINT + '/'
490 bind_params = ', '.join(bind_params)
491 h = rhnSQL.prepare(sql % (bind_params, bind_params))
492 h.execute(**params)
493 kickstart_list = h.fetchall_dict() or []
494
495 for kickstart in kickstart_list:
496 path = os.path.join(CFG.MOUNT_POINT, str(kickstart['base_path']))
497 if not os.path.exists(path):
498 log_debug(1, "Not removing %s: no such file" % path)
499 continue
500 shutil.rmtree(path)
501