forked from RedHatSatellite/sat6_scripts
-
Notifications
You must be signed in to change notification settings - Fork 1
/
clean_content_views.py
executable file
·311 lines (260 loc) · 12.5 KB
/
clean_content_views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#!/usr/bin/python
#title :clean_content_views.py
#description :Removes orphaned versions of Satellite 6 content views
#URL :https://github.com/ggatward/sat6_scripts
#author :Geoff Gatward <[email protected]>
#notes :This script is NOT SUPPORTED by Red Hat Global Support Services.
#license :GPLv3
#==============================================================================
"""
Removes content view versions that don't belong to any environment
"""
#pylint: disable-msg=R0912,R0913,R0914,R0915
import sys, argparse
import simplejson as json
import helpers
def get_cv(org_id, cleanup_list, keep):
"""Get the content views"""
# Query API to get all content views for our org
cvs = helpers.get_json(
helpers.KATELLO_API + "organizations/" + str(org_id) + "/content_views/")
ver_list = {}
ver_descr = {}
ver_keep = {}
for cv_result in cvs['results']:
# We will never clean the DOV
if cv_result['name'] != "Default Organization View":
# Handle specific includes
if cleanup_list:
# The list contains dictionaries as elements. Process each dictionary
for cv in cleanup_list:
# If the CV name does not appear in our config list, skip
if cv['view'] != cv_result['name']:
msg = "Skipping " + cv_result['name']
helpers.log_msg(msg, 'DEBUG')
continue
else:
msg = "Processing content view '" + cv_result['name'] + "' " \
+ str(cv_result['id'])
helpers.log_msg(msg, 'DEBUG')
# Add the next version of the view, and how many versions to keep
ver_list[cv_result['id']] = cv_result['id']
ver_descr[cv_result['id']] = cv_result['name']
ver_keep[cv_result['id']] = cv['keep']
# Handle the 'all' option
else:
msg = "Processing content view '" + cv_result['name'] + "' " \
+ str(cv_result['id'])
helpers.log_msg(msg, 'DEBUG')
# Add the next version of the view, and how many versions to keep
ver_list[cv_result['id']] = cv_result['id']
ver_descr[cv_result['id']] = cv_result['name']
ver_keep[cv_result['id']] = keep
return ver_list, ver_descr, ver_keep
def get_content_view_version(cvid):
cvv = helpers.get_json(
helpers.KATELLO_API + "content_view_versions/" + str(cvid))
return cvv
def get_content_view_info(cvid):
"""
Return Content View Info for a given CV ID
"""
cvinfo = helpers.get_json(
helpers.KATELLO_API + "content_views/" + str(cvid))
return cvinfo
def cleanup(ver_list, ver_descr, dry_run, runuser, ver_keep, cleanall, ignorefirstpromoted):
"""Clean Content Views"""
# Set the task name to be displayed in the task monitoring stage
task_name = "Cleanup content views"
# Now we have all the info needed, we can actually trigger the cleanup.
task_list = []
ref_list = {}
# Catch scenario that no CV versions are found matching cleanup criteria
if not ver_list:
msg = "No content view versions found matching cleanup criteria"
helpers.log_msg(msg, 'ERROR')
sys.exit(1)
for cvid in sorted(ver_list.keys(),reverse=True):
# Check if there is a publish/promote already running on this content view
locked = helpers.check_running_publish(ver_list[cvid], ver_descr[cvid])
msg = "Cleaning content view '" + str(ver_descr[cvid]) + "'"
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
# For the given content view we need to find the orphaned versions
cvinfo = get_content_view_info(cvid)
# Find the oldest published version
version_list = []
version_list_all = []
for version in cvinfo['versions']:
if not version['environment_ids']:
version_list_all.append(float(version['version']))
continue
else:
msg = "Found version " + str(version['version'])
helpers.log_msg(msg, 'DEBUG')
# Add the version id to a list
version_list.append(float(version['version']))
# Find the oldest 'in use' version id
if not version_list:
msg = "No oldest in-use version found"
else:
lastver = min(version_list)
msg = "Oldest in-use version is " + str(lastver)
helpers.log_msg(msg, 'DEBUG')
# Find the oldest 'NOT in use' version id
if not version_list_all:
msg = "No oldest NOT-in-use version found"
else:
msg = "Oldest NOT-in-use version is " + str(min(version_list_all))
helpers.log_msg(msg, 'DEBUG')
# Find version to delete (based on keep parameter) if --ignorefirstpromoted
version_list_all.sort()
todelete = version_list_all[:(len(version_list_all) - int(ver_keep[cvid]))]
msg = "Versions to remove if --ignorefirstpromoted: " + str(todelete)
helpers.log_msg(msg, 'DEBUG')
for version in cvinfo['versions']:
# Get composite content views for version
cvv = get_content_view_version(version['id'])
# Find versions that are not in any environment and not in any composite content view
if not version['environment_ids'] and not cvv['composite_content_view_ids']:
if not locked:
msg = "Orphan view version " + str(version['version']) + " found in '" +\
str(ver_descr[cvid]) + "'"
helpers.log_msg(msg, 'DEBUG')
if ignorefirstpromoted:
if cleanall:
msg = "Removing version " + str(version['version'])
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
else:
if float(version['version']) in todelete:
# If ignorefirstpromoted delete CV
msg = "Removing version " + str(version['version'])
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
else:
msg = "Skipping delete of version " + str(version['version']) + " due to --keep value"
helpers.log_msg(msg, 'INFO')
print msg
continue
else:
if float(version['version']) > float(lastver):
# If we have chosen to remove all orphans
if cleanall:
msg = "Removing version " + str(version['version'])
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
else:
msg = "Skipping delete of version " + str(version['version'])
helpers.log_msg(msg, 'INFO')
print msg
continue
else:
if float(version['version']) < (lastver - float(ver_keep[cvid])):
msg = "Removing version " + str(version['version'])
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
else:
msg = "Skipping delete of version " + str(version['version']) + " due to --keep value"
helpers.log_msg(msg, 'INFO')
print msg
continue
# Delete the view version from the content view
if not dry_run and not locked:
try:
task = helpers.put_json(
helpers.KATELLO_API + "content_views/" + str(cvid) + "/remove/",
json.dumps(
{
"id": cvid,
"content_view_version_ids": version['id']
}
)
)
if id in task:
task_id = task['id']
# Wait for the task to complete
helpers.wait_for_task(task_id,'clean')
# Check if the deletion completed successfully
tinfo = helpers.get_task_status(task_id)
if tinfo['state'] != 'running' and tinfo['result'] == 'success':
msg = "Removal of content view version OK"
helpers.log_msg(msg, 'INFO')
print helpers.GREEN + "OK" + helpers.ENDC
else:
msg = "Failed"
helpers.log_msg(msg, 'ERROR')
else:
msg = "Can't remove content view " + str(cvid)
helpers.log_msg(msg, 'INFO')
print helpers.HEADER + msg + helpers.ENDC
except Warning:
msg = "Failed to initiate removal"
helpers.log_msg(msg, 'WARNING')
# Exit in the case of a dry-run
if dry_run:
msg = "Dry run - not actually performing removal"
helpers.log_msg(msg, 'WARNING')
sys.exit(2)
def main(args):
"""
Main routine
"""
# Who is running this script?
runuser = helpers.who_is_running()
# Check for sane input
parser = argparse.ArgumentParser(
description='Cleans content views for specified organization.')
group = parser.add_mutually_exclusive_group()
# pylint: disable=bad-continuation
parser.add_argument('-o', '--org', help='Organization (Uses default if not specified)',
required=False)
parser.add_argument('-k', '--keep', help='How many old versions to keep (only used with -a)',
required=False)
group.add_argument('-a', '--all', help='Clean ALL content views', required=False,
action="store_true")
parser.add_argument('-c', '--cleanall', help='Remove orphan versions between in-use views',
required=False, action="store_true")
parser.add_argument('-i', '--ignorefirstpromoted', help='Version to keep count starts from first CV, not first promoted CV',
required=False, action="store_true")
parser.add_argument('-d', '--dryrun', help='Dry Run - Only show what will be cleaned',
required=False, action="store_true")
args = parser.parse_args()
# Log the fact we are starting
msg = "-------- Content view cleanup started by " + runuser + " -----------"
helpers.log_msg(msg, 'INFO')
# Set our script variables from the input args
if args.org:
org_name = args.org
else:
org_name = helpers.ORG_NAME
dry_run = args.dryrun
cleanall = args.cleanall
ignorefirstpromoted = args.ignorefirstpromoted
if args.keep:
keep = args.keep
else:
keep = "0"
cleanup_list = []
if not args.all:
cleanup_list = helpers.CONFIG['cleanup']['content_views']
if not cleanup_list:
msg = "Cannot find cleanup configuration"
helpers.log_msg(msg, 'ERROR')
sys.exit(1)
msg = "Config found for CV's " + str(cleanup_list)
helpers.log_msg(msg, 'DEBUG')
# Get the org_id (Validates our connection to the API)
org_id = helpers.get_org_id(org_name)
# Get the list of Content Views along with the latest view version in each environment
(ver_list, ver_descr, ver_keep) = get_cv(org_id, cleanup_list, keep)
# Clean the content views. Returns a list of task IDs.
cleanup(ver_list, ver_descr, dry_run, runuser, ver_keep, cleanall, ignorefirstpromoted)
# Exit cleanly
sys.exit(0)
if __name__ == "__main__":
try:
main(sys.argv[1:])
except KeyboardInterrupt, e:
print >> sys.stderr, ("\n\nExiting on user cancel.")
sys.exit(1)