-
Notifications
You must be signed in to change notification settings - Fork 2
/
reassign-base-channel.py
executable file
·221 lines (208 loc) · 10.5 KB
/
reassign-base-channel.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
#!/usr/bin/python
__author__ = "Felix Dewaleyne"
__credits__ = ["Felix Dewaleyne"]
__license__ = "GPL"
__maintainer__ = "Felix Dewaleyne"
__email__ = "[email protected]"
__status__ = "prod"
__version__ = "1.1"
###
#
# Script to detect the base channel to attach from the version of RHEL installed.
#
###
# To the extent possible under law, Red Hat, Inc. has dedicated all copyright to this software to the public domain worldwide, pursuant to the CC0 Public Domain Dedication.
# This software is distributed without any warranty. See <http://creativecommons.org/publicdomain/zero/1.0/>.
###
# NOTE: this version supposes the systems still are subscribed to their channels when listing the channels through certain api calls
import xmlrpclib, os, ConfigParser, re, sys, getpass
#global variables
client=None;
SATELLITE_LOGIN=None;
config = ConfigParser.ConfigParser()
config.read(['.satellite', os.path.expanduser('~/.satellite'), '/etc/sysconfig/rhn/satellite'])
# this will initialize a session and return its key.
# for security reason the password is removed from memory before exit, but we want to keep the current username.
def session_init(orgname='baseorg', settings={} ):
global client;
global config;
global SATELLITE_LOGIN;
if 'url' in settings and not settings['url'] == None:
SATELLITE_URL = settings['url']
elif config.has_section('default') and config.has_option('default', 'url'):
SATELLITE_URL = config.get('default','url')
else:
sys.stderr.write("enter the satellite url, such as https://satellite.example.com/rpc/api")
sys.stderr.write("\n")
SATELLITE_URL = raw_input().strip()
#format the url if a part is missing
if re.match('^http(s)?://[\w\-.]+/rpc/api',SATELLITE_URL) == None:
if re.search('^http(s)?://', SATELLITE_URL) == None:
SATELLITE_URL = "https://"+SATELLITE_URL
if re.search('/rpc/api$', SATELLITE_URL) == None:
SATELLITE_URL = SATELLITE_URL+"/rpc/api"
if 'login' in settings and not settings['login'] == None:
SATELLITE_LOGIN = settings['login']
elif config.has_section(orgname) and config.has_option(orgname, 'username'):
SATELLITE_LOGIN = config.get(orgname, 'username')
else:
sys.stderr.write("Login details for %s\n\n" % SATELLITE_URL)
sys.stderr.write("Login: ")
SATELLITE_LOGIN = raw_input().strip()
if 'password' in settings and not settings['password'] == None:
SATELLITE_PASSWORD = settings['password']
elif config.has_section(orgname) and config.has_option(orgname, 'password'):
SATELLITE_PASSWORD = config.get(orgname, 'password')
else:
SATELLITE_PASSWORD = getpass.getpass(prompt="Password: ")
sys.stderr.write("\n")
#inits the connection
client = xmlrpclib.Server(SATELLITE_URL, verbose=0)
key = client.auth.login(SATELLITE_LOGIN, SATELLITE_PASSWORD)
# removes the password from memory
del SATELLITE_PASSWORD
return key
def get_base(key,systemid):
"""gathers the data on what base channel should be set"""
global client
data = client.system.listSubscribableBaseChannels(key,systemid)
return data['label']
def get_childs(key,systemid):
"""gathers the list of child channels that should be set"""
data = client.system.listSubscribedChildChannels(key,systemid)
childs = []
for channel in data:
childs.append(channel['label'])
return childs
def set_channels(key,systemid,base,childs):
"""sets the channels or displays an error indicating that the operation failed, then offers to continue or retry. childs needs to be None or a list.
depending on the None arguments used on base and childs, decides to try only the elements that are not none"""
global client
print "Working on system "+str(systemid)
#add management if we aren't in a retry loop for base or childs
if base != None and childs != None :
try:
client.system.upgradeEntitlement(key,systemid,"enterprise_entitled")
except e:
while True:
print "Unable to assign a management entitmenet to the system with reason"
print str(e)
answer = raw_input("Do you want to continue, retry or stop? (c, r, [s])").strip()
if answer == 'c':
print "Failed to assign a management entitlement"
print "continueing with the Base channel"
pass
elif answer == 'r':
#enter the retry condition for entitlements
set_channels(key,systemid,None,None)
pass
else:
raise
#reassign the base channel if not a retry loop out of base ; childs can be None or another value. need to be able to continue on the first run too.
if base != None:
try:
client.system.setBaseChannel(key,systemid,base)
print "\tBase channel restored to "+base
except e:
while True:
print "unable to reattach the base channel with the reason"
print str(e)
answer = raw_input("Do you want to continue, retry or stop? (c, r, [s])").strip()
if answer == 'c':
print "Failed to assign to the base channel "+base
print "continueing with the child channels"
pass
elif answer == 'r':
#enter the retry condition for base
set_channels(key,systemid,base,None)
pass
else:
raise
#add childs if there are any
if childs != None and len(childs) > 0:
try:
client.system.setChildChannels(key,systemid,childs)
print "\tChild channels restored to "+str(childs)
except e:
while True:
print "unable to reattach the child channels with the reason"
print str(e)
answer = raw_input("Do you want to continue, retry or stop? (c, r, [s])").strip()
if answer == 'c':
print "Failed to alter this system with child channels"
for channel in childs:
print "\t"+channel
pass
elif answer == 'r':
#enter the retry condition for childs
set_channels(key,systemid,None,childs)
pass
else:
raise
return
def process_group(key,groupname,convertflex):
"""processes the list of systems in the group of that name"""
global client
ids = []
data = client.systemgroup.listSystems(key,groupname)
print "processing group "+groupname
for system in data:
base = get_base(key,system['id'])
childs = get_childs(key,system['id'])
ids.append(system['id'])
set_channels(key,system['id'],base,childs)
print "finished processing the group"
if convertflex and len(ids) > 0:
client.system.convertToFlexEntitlement(key,ids)
def list_groups(key):
"""displays a list of all groups"""
global client
data = client.systemgroup.listAllGroups(key)
print "There are "+str(len(data))+" groups:"
print ("%60s - %3s - %7s - %s " % ("Name", "Org", "Systems", "Description" ))
for group in data:
print ("%60s - %3s - %7s - %s" % (group['name'], str(group['org_id']) ,str(group['system_count']), group['description'] ))
pass
def main(version):
"""main function - takes in the options and selects the behaviour"""
global verbose;
import optparse
parser = optparse.OptionParser("%prog -s SYSID|-g GROUPNAME|-l [--flex]\n reassigns their entitlements to systems (based on the information pulled by the api for that system)", version=version)
parser.add_option("-s", "--systemid", dest="systemid", type='int',default=None, help="attempt to reassign entitlements to a single system")
parser.add_option("-g", "--group", dest="groupname",default=None, help="attempt to reassign entitlements to a system group")
parser.add_option("-l", "--list", dest="grouplist", action="store_true", default=False, help="Displays the list of groups you have access to")
parser.add_option("-f", "--flex", dest="convertflex", action="store_true", default=False, help="indicates to try to convert to flex the systems")
parser.add_option("-H", "--url", dest="saturl",default=None, help="URL of the satellite api, e.g. https://satellite.example.com/rpc/api or http://127.0.0.1/rpc/api ; can also be just the hostname or ip of the satellite. Facultative.")
parser.add_option("-U", "--user", dest="satuser",default=None, help="username to use with the satellite. Should be admin of the organization owning the channels. Faculative.")
parser.add_option("-P", "--password", dest="satpwd",default=None, help="password of the user. Will be asked if not given and not in the configuration file.")
parser.add_option("--org", dest="satorg", default="baseorg", help="name of the organization to use - refers to the section of the config file to use, not an org of the satellite. Facultative, defaults to %default")
parser.add_option("-v","--verbose",dest="verbose",default=False,action="store_true",help="activate verbose output")
(options, args) = parser.parse_args()
#set verbosity globally
verbose = options.verbose
if options.grouplist:
key = session_init(options.satorg , {"url" : options.saturl, "login" : options.satuser, "password" : options.satpwd})
list_groups(key)
client.auth.logout(key)
elif options.systemid != None:
key = session_init(options.satorg , {"url" : options.saturl, "login" : options.satuser, "password" : options.satpwd})
base = get_base(key,options.systemid)
childs = get_childs(key,options.systemid)
set_channels(key,options.systemid,base,childs)
if options.convertflex:
print "attempting flex conversion"
try:
client.system.convertToFlexEntitlement(key,[options.systemid])
except e:
print "conversion failed with"
print str(e)
pass
client.auth.logout(key)
elif options.groupname != None:
key = session_init(options.satorg , {"url" : options.saturl, "login" : options.satuser, "password" : options.satpwd})
process_group(key,options.groupname,options.convertflex)
client.auth.logout(key)
else:
parser.error('incorrect usage - use --help or -h for more information')
if __name__ == "__main__":
main(__version__)