1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import time
20 import string
21
22 from spacewalk.server.rhnServer import server_lib
23 from spacewalk.common.usix import ListType, TupleType, StringType
24 from spacewalk.common import rhnFlags
25 from spacewalk.common.rhnLog import log_debug, log_error
26 from spacewalk.common.rhnConfig import CFG
27 from spacewalk.common.rhnException import rhnFault
28 from spacewalk.common.rhnTB import add_to_seclist
29 from spacewalk.common.rhnTranslate import _
30 from spacewalk.server.rhnLib import computeSignature
31 from spacewalk.server.rhnHandler import rhnHandler
32 from spacewalk.server import rhnChannel, rhnDependency, rhnCapability
33 from spacewalk.server.rhnServer import server_route
34
35 import re
36 NONSUBSCRIBABLE_CHANNELS = re.compile("(rhn-proxy|rhn-satellite)")
37
38
40
41 """ xml-rpc Server Functions that we will provide for the outside world.
42 """
43
45 """ Up2date Class Constructor
46
47 o Initializes inherited class.
48 o Appends the functions available to the outside world in the
49 rhnHandler list.
50 """
51 rhnHandler.__init__(self)
52
53
54
55
56
57 self.functions.append('login')
58 self.functions.append('listChannels')
59 self.functions.append('subscribeChannels')
60 self.functions.append('unsubscribeChannels')
61 self.functions.append('history')
62 self.functions.append('solvedep')
63 self.functions.append('solveDependencies')
64 self.functions.append('solveDependencies_arch')
65 self.functions.append('solveDependencies_with_limits')
66
72
73 - def login(self, system_id, extra_data={}):
74 """ Clients v2+
75 Log in routine.
76 Return a dictionary of session token/channel information.
77 Also sets this information in the headers.
78 """
79 log_debug(5, system_id)
80
81
82 self.load_user = 1
83 server = self.auth_system('login', system_id)
84
85 log_debug(1, self.server_id)
86
87 rhnCapability.update_client_capabilities(self.server_id)
88
89 channels = rhnChannel.getSubscribedChannels(self.server_id)
90
91 rhnServerTime = str(time.time())
92 expireOffset = str(CFG.CLIENT_AUTH_TIMEOUT)
93 signature = computeSignature(CFG.SECRET_KEY,
94 self.server_id,
95 self.user,
96 rhnServerTime,
97 expireOffset)
98
99 loginDict = {
100 'X-RHN-Server-Id': self.server_id,
101 'X-RHN-Auth-User-Id': self.user,
102 'X-RHN-Auth': signature,
103 'X-RHN-Auth-Server-Time': rhnServerTime,
104 'X-RHN-Auth-Expire-Offset': expireOffset,
105
106 'X-RHN-Auth-Channels': channels
107 }
108
109
110
111 transport = rhnFlags.get('outputTransportOptions')
112 for k, v in loginDict.items():
113
114 if string.lower(k) == string.lower('X-RHN-Auth-Channels'):
115
116 transport[k] = [string.join(x, ':') for x in v]
117 else:
118 transport[k] = v
119 log_debug(5, "loginDict", loginDict, transport)
120
121
122 server_route.store_client_route(self.server_id)
123
124 return loginDict
125
135
137 """ Clients v2+ """
138 add_to_seclist(passwd)
139 log_debug(5, system_id, channelNames, username, passwd)
140
141 self.auth_system('subscribeChannel', system_id)
142
143 log_debug(1, self.server_id, channelNames)
144 server_lib.snapshot_server(self.server_id, 'Base Channel Updated')
145 for channelName in channelNames:
146 if NONSUBSCRIBABLE_CHANNELS.search(channelName):
147 raise rhnFault(73, explain=False)
148 else:
149 rhnChannel.subscribe_channel(self.server_id, channelName,
150 username, passwd)
151 return 0
152
165
167 """ Clients v1-
168 Solve dependencies for a given dependency problem list.
169 IN: a dependency problem list: [name, name, name, ...]
170 RET: a package list: [[n,v,r,e],[n,v,r,e],...] That solves the
171 dependencies.
172 """
173 log_debug(4, system_id)
174 return self.__solveDep(system_id, deps, action="solvedep",
175 clientVersion=1)
176
178 """ Clients v2+
179 Solve dependencies for a given dependency problem list (newer version)
180 IN: a dependency problem list: [name, name, name, ...]
181 RET: a hash {name: [[n, v, r, e], [n, v, r, e], ...], ...}
182 """
183 log_debug(4, system_id)
184 return self.__solveDep(system_id, deps, action="solvedep",
185 clientVersion=2)
186
188 """ Does the same thing as solve_dependencies, but also returns the architecture label with the
189 package info.
190 IN: a dependency problem list: [name, name, name, ...]
191 RET: a hash {name: [[n, v, r, e, a], [n, v, r, e, a], ...], ...}
192 """
193 log_debug(4, system_id)
194 return self.__solveDep_arch(system_id, deps, action="solvedep",
195 clientVersion=2)
196
198 """ This version of solve_dependencies allows the caller to get all of the packages that solve a
199 dependency and limit the packages that are returned to those that match the criteria defined
200 by limit_operator and limit. This version of the function also returns the architecture label
201 of the package[s] that get returned.
202
203 limit_operator can be any of: '<', '<=', '==', '>=', or '>'.
204 limit is a a string of the format [epoch:]name-version-release
205 deps is a list of filenames that the packages that are returned must provide.
206 version is the version of the client that is calling the function.
207 """
208 log_debug(4, system_id)
209 return self.__solveDep_with_limits(system_id, deps, action="solvedep",
210 clientVersion=2, all=all, limit_operator=limit_operator, limit=limit)
211
212 - def history(self, system_id, summary, body=""):
213 """ Clients v2+
214 Add a history log for a performed action
215 """
216 log_debug(5, system_id, summary, body)
217
218 server = self.auth_system('history', system_id)
219
220 log_debug(1, self.server_id)
221
222 server.add_history(summary, body)
223 server.save_history()
224 return 0
225
226
227
229 """ Response for clients:
230 version 1: list
231 version 2: hash
232 """
233 log_debug(7, system_id, deps, action, clientVersion)
234 faultString = _("Invalid value %s (%s)")
235 if type(deps) not in (ListType, TupleType):
236 log_error("Invalid argument type", type(deps))
237 raise rhnFault(30, faultString % (deps, type(deps)))
238 for dep in deps:
239 if type(dep) is not StringType:
240 log_error("Invalid dependency member", type(dep))
241 raise rhnFault(30, faultString % (dep, type(dep)))
242
243 deps = list(filter(len, deps))
244
245 if not deps:
246 return []
247
248 server = self.auth_system(action, system_id)
249 log_debug(1, self.server_id, action, "items: %d" % len(deps))
250 return deps
251
252 - def __solveDep(self, system_id, deps, action, clientVersion):
264
277
278 - def __solveDep_with_limits(self, system_id, deps, action, clientVersion, all=0, limit_operator=None, limit=None):
279 """ Response for clients:
280 version 1: list
281 version 2: hash
282 """
283 log_debug(5, system_id, deps, action, clientVersion)
284 result = self.__solveDep_prepare(system_id, deps, action, clientVersion)
285 if result:
286
287 result = rhnDependency.solve_dependencies_with_limits(self.server_id,
288 deps, clientVersion, all, limit_operator, limit)
289 return result
290
291
293
294 """ A class to handle the site selection... """
295
301
302 - def get(self, *junk):
303 """ Older funtion that can be a noop. """
304 return []
305
306 - def list(self, systemid=None):
307 """ Returns a list of available servers the client can connect to. """
308 servers_list = [
309 {
310 'server': 'xmlrpc.rhn.redhat.com',
311 'handler': '/XMLRPC',
312 'description': 'XML-RPC Server',
313 'location': 'United States',
314 },
315 ]
316 return servers_list
317