Script spacewalk_channel_py
[hide private]
[frames] | no frames]

Source Code for Script script-spacewalk_channel_py

  1  #!/usr/bin/python2 
  2  # 
  3  # Copyright (c) 2009--2018 Red Hat, Inc. 
  4  # 
  5  # This software is licensed to you under the GNU General Public License, 
  6  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  7  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  8  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  9  # along with this software; if not, see 
 10  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 11  # 
 12  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 13  # granted to use or replicate Red Hat trademarks that are incorporated 
 14  # in this software or its documentation. 
 15   
 16  import getpass 
 17  import os 
 18  import re 
 19  import sys 
 20  from rhn import rpclib 
 21  from rhn.i18n import sstr 
 22  from optparse import Option, OptionParser 
 23   
 24  try: # python2 
 25      import urlparse 
 26      import xmlrpclib 
 27  except ImportError: # python3 
 28      import urllib.parse as urlparse 
 29      import xmlrpc.client as xmlrpclib 
 30   
 31  import gettext 
 32  t = gettext.translation('rhn-client-tools', fallback=True) 
 33  # Python 3 translations don't have a ugettext method 
 34  if not hasattr(t, 'ugettext'): 
 35      t.ugettext = t.gettext 
 36  _ = t.ugettext 
 37   
 38  from up2date_client.rhnChannel import subscribeChannels, unsubscribeChannels, getChannels 
 39  from up2date_client import up2dateAuth, config, up2dateErrors, rhncli, rhnserver 
 40   
 41   
42 -class Credentials(object):
43 - def __init__(self, username=None, password=None):
44 if username is not None: 45 self.user = username 46 if password is not None: 47 self.password = password
48
49 - def __getattr__(self, attr):
50 if attr == 'user': 51 tty = open("/dev/tty", "w") 52 tty.write('Username: ') 53 tty.close() 54 setattr(self, 'user', sys.stdin.readline().rstrip('\n')) 55 return self.user 56 elif attr == 'password': 57 # force user population 58 _user = self.user 59 60 setattr(self, 'password', getpass.getpass()) 61 return self.password 62 else: 63 raise AttributeError(attr)
64
65 - def user_callback(self, _option, _opt_str, value, _parser):
66 self.user = value
67
68 - def password_callback(self, _option, _opt_str, value, _parser):
69 self.password = value
70 71 72 VERBOSE = False 73 74
75 -def info(text):
76 if VERBOSE: 77 print(text)
78 79
80 -def systemExit(code, msgs=None):
81 "Exit with a code and optional message(s). Saved a few lines of code." 82 if msgs is not None: 83 if type(msgs) not in [type([]), type(())]: 84 msgs = (msgs, ) 85 for msg in msgs: 86 if hasattr(msg, 'value'): 87 msg = msg.value 88 sys.stderr.write(sstr(msg) + "\n") 89 sys.exit(code)
90 91
92 -def processCommandline():
93 "process the command-line" 94 credentials = Credentials() 95 96 optionsTable = [ 97 Option('-c', '--channel', action='append', dest='channels', 98 help=_('name of channel you want to (un)subscribe')), 99 Option('-a', '--add', action='store_true', 100 help=_('subscribe to channel')), 101 Option('-r', '--remove', action='store_true', 102 help=_('unsubscribe from channel')), 103 Option('-l', '--list', action='store_true', 104 help=_('list channels')), 105 Option('-b', '--base', action='store_true', 106 help=_('show base channel of a system')), 107 Option('-L', '--available-channels', action='store_true', 108 help=_('list all available child channels')), 109 Option('-v', '--verbose', action='store_true', 110 help=_('verbose output')), 111 Option('-u', '--user', action='callback', callback=credentials.user_callback, 112 nargs=1, type='string', help=_('your user name')), 113 Option('-p', '--password', action='callback', callback=credentials.password_callback, 114 nargs=1, type='string', help=_('your password')), 115 ] 116 optionParser = OptionParser(option_list=optionsTable) 117 opts, args = optionParser.parse_args() 118 119 # we take no extra commandline arguments that are not linked to an option 120 if args: 121 systemExit(1, _("ERROR: these arguments make no sense in this context (try --help)")) 122 123 # remove confusing stuff 124 delattr(opts, 'user') 125 delattr(opts, 'password') 126 127 return opts, credentials
128 129
130 -def get_available_channels(user, password):
131 """ return list of available child channels """ 132 modified_servers = [] 133 servers = config.getServerlURL() 134 for server in servers: 135 scheme, netloc, path, query, fragment = urlparse.urlsplit(server) 136 modified_servers.append(urlparse.urlunsplit((scheme, netloc, '/rpc/api', query, fragment))) 137 client = rhnserver.RhnServer(serverOverride=modified_servers) 138 try: 139 key = client.auth.login(user, password) 140 except xmlrpclib.Fault: 141 exc = sys.exc_info()[1] 142 systemExit(1, "Error during client authentication: %s" % exc.faultString) 143 144 system_id = re.sub('^ID-', '', rpclib.xmlrpclib.loads(up2dateAuth.getSystemId())[0][0]['system_id']) 145 result = [] 146 try: 147 channels = client.system.listChildChannels(key, int(system_id)) 148 except xmlrpclib.Fault: 149 exc = sys.exc_info()[1] 150 systemExit(1, "Error when listing child channels: %s" % exc.faultString) 151 152 for channel in channels: 153 if 'LABEL' in channel: 154 result.extend([channel['LABEL']]) 155 else: 156 result.extend([channel['label']]) 157 return result
158 159
160 -def need_channel(channel):
161 """ die gracefully if channel is empty """ 162 if not channel: 163 systemExit(4, _("ERROR: you have to specify at least one channel"))
164 165
166 -def no_channels(channels):
167 """ for actions that does not require channel as a parameter """ 168 if channels: 169 systemExit(4, _("ERROR: this action does not require channel"))
170 171
172 -def add_channel(channels, credentials):
173 need_channel(channels) 174 result = subscribeChannels(channels, credentials.user, credentials.password) 175 if result == 0: 176 info(_("Channel(s): %s successfully added") % ', '.join(channels)) 177 else: 178 systemExit(result, _("Error during adding channel(s) %s") % ', '.join(channels))
179 180
181 -def remove_channel(channels, credentials):
182 need_channel(channels) 183 result = unsubscribeChannels(channels, credentials.user, credentials.password) 184 if result == 0: 185 info(_("Channel(s): %s successfully removed") % ', '.join(channels)) 186 else: 187 systemExit(result, _("Error during removal of channel(s) %s") % ', '.join(channels))
188 189
190 -def list_channels(only_base_channels=False):
191 try: 192 channels = getChannels().channels() 193 except up2dateErrors.NoChannelsError: 194 systemExit(1, _('This system is not associated with any channel.')) 195 except up2dateErrors.NoSystemIdError: 196 systemExit(1, _('Unable to locate SystemId file. Is this system registered?')) 197 198 for channel in sorted(channels): 199 if not (only_base_channels and channel['parent_channel']): 200 print(channel['label'])
201 202
203 -def list_available_channels(credentials):
204 channels = get_available_channels(credentials.user, credentials.password) 205 channels.sort() 206 print('\n'.join(channels))
207 208
209 -def main():
210 options, credentials = processCommandline() 211 212 if options.verbose: 213 VERBOSE = True 214 215 if options.add: 216 add_channel(options.channels, credentials) 217 elif options.remove: 218 remove_channel(options.channels, credentials) 219 elif options.list: 220 no_channels(options.channels) 221 list_channels() 222 elif options.base: 223 no_channels(options.channels) 224 list_channels(only_base_channels=True) 225 elif options.available_channels: 226 no_channels(options.channels) 227 list_available_channels(credentials) 228 else: 229 systemExit(3, _("ERROR: you may want to specify --add, --remove or --list"))
230 231 if __name__ == '__main__': 232 # quick check to see if you are a super-user. 233 if os.getuid() != 0: 234 systemExit(8, _('ERROR: must be root to execute\n')) 235 try: 236 sys.excepthook = rhncli.exceptionHandler 237 main() 238 except KeyboardInterrupt: 239 systemExit(0, "\n" + _("User interrupted process.")) 240 except up2dateErrors.RhnServerException: 241 # do not print traceback, it will scare people 242 systemExit(1, sys.exc_info()[1]) 243 else: 244 # If you need some code from here, separate it to some proper place... 245 raise ImportError('This was never supposed to be used as a library') 246