1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22 from __future__ import with_statement
23 import time
24 from entropy.exceptions import *
25 from entropy.i18n import _
26 from entropy.misc import TimeScheduled
27 from entropy.i18n import _
28
30
31 ssl_connection = True
32 - def __init__(self, OutputInterface, MethodsInterface = None,
33 ClientCommandsInterface = None, quiet = True, show_progress = False,
34 do_cache_connection = False, do_cache_session = False):
35
36 if not hasattr(OutputInterface, 'updateProgress'):
37 mytxt = _("OutputInterface does not have an updateProgress method")
38 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
39 elif not callable(OutputInterface.updateProgress):
40 mytxt = _("OutputInterface does not have an updateProgress method")
41 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
42
43 from entropy.client.services.system.commands import Client as ClientCommands
44 if not issubclass(ClientCommandsInterface, ClientCommands):
45 mytxt = _("A valid entropy.client.services.system.commands.Client class/subclass is needed")
46 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
47
48 from entropy.client.services.system.methods import BaseMixin
49 if not issubclass(MethodsInterface, BaseMixin):
50 mytxt = _("A valid entropy.client.services.system.methods.BaseMixin class/subclass is needed")
51 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
52
53 self.ClientCommandsInterface = ClientCommandsInterface
54 import socket, struct
55 import entropy.tools as entropyTools
56 self.socket, self.struct, self.entropyTools = socket, struct, entropyTools
57 from datetime import datetime
58 self.datetime = datetime
59 import threading
60 self.threading = threading
61 self.Output = OutputInterface
62 self.hostname = None
63 self.hostport = None
64 self.username = None
65 self.password = None
66 self.quiet = quiet
67 self.do_cache_connection = do_cache_connection
68 self.show_progress = show_progress
69 self.ClientCommandsInterface = ClientCommandsInterface
70 self.Methods = MethodsInterface(self)
71 self.session_cache = {}
72 self.SessionCacheLock = self.threading.Lock()
73 self.connection_cache = {}
74 self.CacheLock = self.threading.Lock()
75 self.shutdown = False
76 self.connection_killer = None
77
78
79
80
81
82
83 self.do_cache_session = do_cache_session
84 if self.do_cache_connection:
85 self.connection_killer = TimeScheduled(2, self.connection_killer_handler)
86 self.connection_killer.start()
87
89 if hasattr(self,'shutdown'):
90 self.shutdown = True
91 if hasattr(self,'connection_killer'):
92 if self.connection_killer != None:
93 self.connection_killer.kill()
94
96 if not isinstance(self.hostname,basestring):
97 raise IncorrectParameter("IncorrectParameter: hostname: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
98 if not isinstance(self.username,basestring):
99 raise IncorrectParameter("IncorrectParameter: username: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
100 if not isinstance(self.password,basestring):
101 raise IncorrectParameter("IncorrectParameter: password: %s. %s" % (_('not a string'),_('Please use setup_connection() properly'),))
102 if not isinstance(self.hostport,int):
103 raise IncorrectParameter("IncorrectParameter: port: %s. %s" % (_('not an int'),_('Please use setup_connection() properly'),))
104 if not isinstance(self.ssl_connection,bool):
105 raise IncorrectParameter("IncorrectParameter: ssl_connection: %s. %s" % (_('not a bool'),_('Please use setup_connection() properly'),))
106
108 if self.do_cache_session:
109 with self.SessionCacheLock:
110 return self.session_cache.get(cmd_tuple)
111
113 if self.do_cache_session:
114 with self.SessionCacheLock:
115 self.session_cache[cmd_tuple] = session_id
116
118 if self.do_cache_session:
119 with self.SessionCacheLock:
120 del self.session_cache[cmd_tuple]
121
123 return hash((self.hostname, self.hostport, self.username, self.password, self.ssl_connection,))
124
126 if self.do_cache_connection:
127 key = self.get_connection_cache_key()
128 srv = self.connection_cache.get(key)
129
130
131
132 return srv
133
135 if self.do_cache_connection:
136 key = self.get_connection_cache_key()
137 self.connection_cache[key] = {
138 'conn': srv,
139 'ts': self.get_ts(),
140 }
141
143 if self.do_cache_connection:
144 key = self.get_connection_cache_key()
145 if key not in self.connection_cache:
146 return
147 self.connection_cache[key]['ts'] = self.get_ts()
148
150 if self.do_cache_connection:
151 self.CacheLock.acquire()
152 try:
153 keys = self.connection_cache.keys()
154 for key in keys:
155 data = self.connection_cache.pop(key)
156 data['conn'].disconnect()
157 finally:
158 self.CacheLock.release()
159
161
162 if not self.do_cache_connection: return
163 if self.shutdown: return
164 if not self.connection_cache: return
165
166 keys = self.connection_cache.keys()
167 for key in keys:
168 curr_ts = self.get_ts()
169 ts = self.connection_cache[key]['ts']
170 delta = curr_ts - ts
171 if delta.seconds < 60:
172 continue
173 self.CacheLock.acquire()
174 try:
175 data = self.connection_cache.pop(key)
176 finally:
177 self.CacheLock.release()
178 srv = data['conn']
179 srv.disconnect()
180
182 return self.datetime.fromtimestamp(time.time())
183
185 self.hostname = hostname
186 self.hostport = port
187 self.username = username
188 self.password = password
189 self.ssl_connection = ssl
190 self._validate_credentials()
191
193 self._validate_credentials()
194 args = [self.Output, self.ClientCommandsInterface]
195 kwargs = {
196 'ssl': self.ssl_connection,
197 'quiet': self.quiet,
198 'show_progress': self.show_progress
199 }
200 if timeout != None: kwargs['socket_timeout'] = timeout
201 from entropy.services.ugc.interfaces import Client
202 srv = Client(*args,**kwargs)
203 srv.connect(self.hostname, self.hostport)
204 return srv
205
212
213 - def logout(self, srv, session_id):
214 self._validate_credentials()
215 return srv.CmdInterface.service_logout(self.username, session_id)
216
217 - def login(self, srv, session_id):
218 self._validate_credentials()
219 return srv.CmdInterface.service_login(self.username, self.password, session_id)
220
221
222 - def do_cmd(self, login_required, func, args, kwargs):
223
224 with self.CacheLock:
225
226 srv = self.get_connection_cache()
227 if srv == None:
228 srv = self.get_service_connection(timeout = 10)
229 if srv != None: self.cache_connection(srv)
230 else:
231 srv = srv['conn']
232
233 if srv == None:
234 return False, 'no connection'
235
236 cmd_tuple = (login_required, func,)
237 new_session = False
238 session = self.get_session_cache(cmd_tuple)
239 if session == None:
240 new_session = True
241 session = srv.open_session()
242 if session == None:
243 return False, 'no session'
244 else:
245 if not srv.is_session_alive(session):
246 new_session = True
247 session = srv.open_session()
248 if session == None:
249 return False, 'no session'
250 self.set_session_cache(cmd_tuple, session)
251
252 self.update_connection_ts()
253 args.insert(0,session)
254
255 if login_required and new_session:
256 logged, error = self.login(srv, session)
257 if not logged:
258 srv.close_session(session)
259 self.remove_session_cache(cmd_tuple)
260 if not self.do_cache_connection:
261 srv.disconnect()
262 return False, error
263
264 cmd_func = getattr(srv.CmdInterface, func)
265 rslt = cmd_func(*args, **kwargs)
266 if not self.do_cache_session:
267 if login_required:
268 self.logout(srv, session)
269 srv.close_session(session)
270 if not self.do_cache_connection:
271 srv.disconnect()
272 return rslt
273
276