1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Client Services Base Interface}.
10
11 """
12 from __future__ import with_statement
13 import time
14 from entropy.exceptions import *
15 from entropy.i18n import _
16 from entropy.misc import TimeScheduled
17 from entropy.i18n import _
18
20
21 ssl_connection = True
22 - def __init__(self, OutputInterface, MethodsInterface = None,
23 ClientCommandsInterface = None, quiet = True, show_progress = False,
24 do_cache_connection = False, do_cache_session = False):
25
26 if not hasattr(OutputInterface, 'updateProgress'):
27 mytxt = _("OutputInterface does not have an updateProgress method")
28 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
29 elif not callable(OutputInterface.updateProgress):
30 mytxt = _("OutputInterface does not have an updateProgress method")
31 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
32
33 from entropy.client.services.system.commands import Client as ClientCommands
34 if not issubclass(ClientCommandsInterface, ClientCommands):
35 mytxt = _("A valid entropy.client.services.system.commands.Client class/subclass is needed")
36 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
37
38 from entropy.client.services.system.methods import BaseMixin
39 if not issubclass(MethodsInterface, BaseMixin):
40 mytxt = _("A valid entropy.client.services.system.methods.BaseMixin class/subclass is needed")
41 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
42
43 self.ClientCommandsInterface = ClientCommandsInterface
44 import socket, struct
45 import entropy.tools as entropyTools
46 self.socket, self.struct, self.entropyTools = socket, struct, entropyTools
47 from datetime import datetime
48 self.datetime = datetime
49 import threading
50 self.threading = threading
51 self.Output = OutputInterface
52 self.hostname = None
53 self.hostport = None
54 self.username = None
55 self.password = None
56 self.quiet = quiet
57 self.do_cache_connection = do_cache_connection
58 self.show_progress = show_progress
59 self.ClientCommandsInterface = ClientCommandsInterface
60 self.Methods = MethodsInterface(self)
61 self.session_cache = {}
62 self.SessionCacheLock = self.threading.Lock()
63 self.connection_cache = {}
64 self.CacheLock = self.threading.Lock()
65 self.shutdown = False
66 self.connection_killer = None
67
68
69
70
71
72
73 self.do_cache_session = do_cache_session
74 if self.do_cache_connection:
75 self.connection_killer = TimeScheduled(2, self.connection_killer_handler)
76 self.connection_killer.start()
77
79 if hasattr(self,'shutdown'):
80 self.shutdown = True
81 if hasattr(self,'connection_killer'):
82 if self.connection_killer != None:
83 self.connection_killer.kill()
84
86 if not isinstance(self.hostname,basestring):
87 raise IncorrectParameter("IncorrectParameter: hostname: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
88 if not isinstance(self.username,basestring):
89 raise IncorrectParameter("IncorrectParameter: username: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
90 if not isinstance(self.password,basestring):
91 raise IncorrectParameter("IncorrectParameter: password: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
92 if not isinstance(self.hostport,int):
93 raise IncorrectParameter("IncorrectParameter: port: %s. %s" % (_('not an int'),_('Please use setup_connection() properly'),))
94 if not isinstance(self.ssl_connection,bool):
95 raise IncorrectParameter("IncorrectParameter: ssl_connection: %s. %s" % (_('not a bool'),_('Please use setup_connection() properly'),))
96
98 if self.do_cache_session:
99 with self.SessionCacheLock:
100 return self.session_cache.get(cmd_tuple)
101
103 if self.do_cache_session:
104 with self.SessionCacheLock:
105 self.session_cache[cmd_tuple] = session_id
106
108 if self.do_cache_session:
109 with self.SessionCacheLock:
110 del self.session_cache[cmd_tuple]
111
113 return hash((self.hostname, self.hostport, self.username, self.password, self.ssl_connection,))
114
116 if self.do_cache_connection:
117 key = self.get_connection_cache_key()
118 srv = self.connection_cache.get(key)
119
120
121
122 return srv
123
125 if self.do_cache_connection:
126 key = self.get_connection_cache_key()
127 self.connection_cache[key] = {
128 'conn': srv,
129 'ts': self.get_ts(),
130 }
131
133 if self.do_cache_connection:
134 key = self.get_connection_cache_key()
135 if key not in self.connection_cache:
136 return
137 self.connection_cache[key]['ts'] = self.get_ts()
138
140 if self.do_cache_connection:
141 self.CacheLock.acquire()
142 try:
143 keys = self.connection_cache.keys()
144 for key in keys:
145 data = self.connection_cache.pop(key)
146 data['conn'].disconnect()
147 finally:
148 self.CacheLock.release()
149
151
152 if not self.do_cache_connection: return
153 if self.shutdown: return
154 if not self.connection_cache: return
155
156 keys = self.connection_cache.keys()
157 for key in keys:
158 curr_ts = self.get_ts()
159 ts = self.connection_cache[key]['ts']
160 delta = curr_ts - ts
161 if delta.seconds < 60:
162 continue
163 self.CacheLock.acquire()
164 try:
165 data = self.connection_cache.pop(key)
166 finally:
167 self.CacheLock.release()
168 srv = data['conn']
169 srv.disconnect()
170
172 return self.datetime.fromtimestamp(time.time())
173
175 self.hostname = hostname
176 self.hostport = port
177 self.username = username
178 self.password = password
179 self.ssl_connection = ssl
180 self._validate_credentials()
181
183 self._validate_credentials()
184 args = [self.Output, self.ClientCommandsInterface]
185 kwargs = {
186 'ssl': self.ssl_connection,
187 'quiet': self.quiet,
188 'show_progress': self.show_progress
189 }
190 if timeout != None: kwargs['socket_timeout'] = timeout
191 from entropy.services.ugc.interfaces import Client
192 srv = Client(*args,**kwargs)
193 srv.connect(self.hostname, self.hostport)
194 return srv
195
202
203 - def logout(self, srv, session_id):
204 self._validate_credentials()
205 return srv.CmdInterface.service_logout(self.username, session_id)
206
207 - def login(self, srv, session_id):
208 self._validate_credentials()
209 return srv.CmdInterface.service_login(self.username, self.password, session_id)
210
211
212 - def do_cmd(self, login_required, func, args, kwargs):
213
214 with self.CacheLock:
215
216 srv = self.get_connection_cache()
217 if srv == None:
218 srv = self.get_service_connection(timeout = 10)
219 if srv != None: self.cache_connection(srv)
220 else:
221 srv = srv['conn']
222
223 if srv == None:
224 return False, 'no connection'
225
226 cmd_tuple = (login_required, func,)
227 new_session = False
228 session = self.get_session_cache(cmd_tuple)
229 if session == None:
230 new_session = True
231 session = srv.open_session()
232 if session == None:
233 return False, 'no session'
234 else:
235 if not srv.is_session_alive(session):
236 new_session = True
237 session = srv.open_session()
238 if session == None:
239 return False, 'no session'
240 self.set_session_cache(cmd_tuple, session)
241
242 self.update_connection_ts()
243 args.insert(0,session)
244
245 if login_required and new_session:
246 logged, error = self.login(srv, session)
247 if not logged:
248 srv.close_session(session)
249 self.remove_session_cache(cmd_tuple)
250 if not self.do_cache_connection:
251 srv.disconnect()
252 return False, error
253
254 cmd_func = getattr(srv.CmdInterface, func)
255 rslt = cmd_func(*args, **kwargs)
256 if not self.do_cache_session:
257 if login_required:
258 self.logout(srv, session)
259 srv.close_session(session)
260 if not self.do_cache_connection:
261 srv.disconnect()
262 return rslt
263
266