1
2 """
3 Plugin for viewing and controlling active sessions for a local user.
4
5 Plugin read by omero.cli.Cli during initialization. The method(s)
6 defined here will be added to the Cli class for later use.
7
8 Copyright 2008 Glencoe Software, Inc. All rights reserved.
9 Use is subject to license terms supplied in LICENSE.txt
10
11 """
12
13
14 import os
15 import sys
16 import Ice
17 import time
18 import traceback
19 import exceptions
20 import subprocess
21 import getpass
22 import omero.java
23
24 from omero.util.sessions import SessionsStore
25 from omero.cli import BaseControl, CLI
26 from path import path
27
28 HELP = """Control and create user sessions
29
30 Sessions are stored locally on disk. Several can
31 be active simultaneously, but only one will be used
32 for a single invocation of bin/omero.
33
34 """
35
36 LONGHELP = """
37 Uses the login parameters from %(prog)s to login.
38
39 To list these options, use "%(prog)s -h"
40
41 Sample session:
42 $ bin/omero -s localhost sessions login
43 Username:
44 Password:
45 $ bin/omero -s localhost -u john sessions login
46 Password
47 $ bin/omero -s localhost -k 8afe443f-19fc-4cc4-bf4a-850ec94f4650 sessions login
48 $ bin/omero sessions login
49 Server:
50 Username:
51 Password:
52 $ bin/omero sessions login user@omero.example.com
53 Password:
54 $ bin/omero sessions logout
55 $ bin/omero sessions login
56 Reuse current session? [Y/n]
57 $ bin/omero sessions list
58 $ bin/omero sessions logout
59 $ bin/omero sessions login omero.example.com
60 Username:
61 Password:
62 $ bin/omero sessions logout
63 $ bin/omero -p 24064 sessions login
64 Server:
65 Username:
66 Password:
67 $ bin/omero sessions login my.email@example.com@omero.example.com
68 Password:
69 $ bin/omero -k 8afe443f-19fc-4cc4-bf4a-850ec94f4650 sessions login
70 $ bin/omero sessions clear
71 """
72
74
75 FACTORY = SessionsStore
76
80
99
104
107
108 - def help(self, args):
110
112 """
113 Goals:
114 If server and key, then don't ask any questions.
115 If nothing requested, and something's active, use it. (i.e. don't require port number)
116 Reconnect if possible (assuming parameters are the same)
117 """
118
119 if self.ctx.conn():
120 self.ctx.err("Active client found")
121 return
122
123 create = getattr(args, "create", None)
124 store = self.store(args)
125 previous = store.get_current()
126
127
128 props = {}
129 if args.port:
130 props["omero.port"] = args.port
131 if args.group:
132 props["omero.group"] = args.group
133
134
135
136
137
138
139 server = getattr(args, "connection", None)
140 name = None
141
142 if args.server:
143 if server:
144 self.ctx.die(3, "Server specified twice: %s and %s" % (server, args.server))
145 else:
146 server = args.server
147
148 if server: server, name = self._parse_conn(server)
149
150 if args.user:
151 if name:
152 self.ctx.die(4, "Username specified twice: %s and %s" % (name, args.user))
153 else:
154 name = args.user
155
156
157
158
159
160
161 pasw = args.password
162 if args.key:
163 if name:
164 self.ctx.err("Overriding name since session set")
165 name = args.key
166 if args.password:
167 self.ctx.err("Ignoring password since key set")
168 pasw = args.key
169
170
171
172
173
174
175 elif previous[0] and previous[1]:
176
177 server_differs = (server is not None and server != previous[0])
178 name_differs = (name is not None and name != previous[1])
179
180 if not create and not server_differs and not name_differs:
181 try:
182 conflicts = store.conflicts(previous[0], previous[1], previous[2], props, True)
183 if conflicts:
184 self.ctx.dbg("Not attaching because of conflicts: %s" % conflicts)
185 else:
186 rv = store.attach(*previous)
187 return self.handle(rv, "Using")
188 except exceptions.Exception, e:
189 self.ctx.dbg("Exception on attach: %s" % traceback.format_exc(e))
190 self.ctx.dbg("Exception on attach: %s" % e)
191
192 self.ctx.out("Previously logged in to %s as %s" % (previous[0], previous[1]))
193
194
195
196
197
198
199 if not server: server, name = self._get_server(store)
200 if not name: name = self._get_username()
201
202 props["omero.host"] = server
203 props["omero.user"] = name
204
205 rv = None
206 if not create:
207 available = store.available(server, name)
208 for uuid in available:
209 conflicts = store.conflicts(server, name, uuid, props)
210 if conflicts:
211 self.ctx.dbg("Skipping %s due to conflicts: %s" % (uuid, conflicts))
212 continue
213 try:
214 rv = store.attach(server, name, uuid)
215 store.set_current(server, name, uuid)
216 action = "Reconnected to"
217 break
218 except:
219 self.ctx.dbg("Removing %s" % uuid)
220 store.clear(server, name, uuid)
221 continue
222
223 if not rv:
224 if not pasw:
225 pasw = self.ctx.input("Password:", hidden = True, required = True)
226 try:
227 rv = store.create(name, pasw, props)
228 except Ice.ConnectionRefusedException:
229 self.ctx.die(554, "Ice.ConnectionRefusedException: %s isn't running" % server)
230 except Ice.DNSException:
231 self.ctx.die(555, "Ice.DNSException: bad host name: '%s'" % server)
232 except exceptions.Exception, e:
233 exc = traceback.format_exc()
234 self.ctx.dbg(exc)
235 self.ctx.die(556, "InternalException: Failed to connect: %s" % e)
236 action = "Created"
237
238 return self.handle(rv, action)
239
240 - def handle(self, rv, action):
241 """
242 Handles a new connection
243 """
244 client, uuid, idle, live = rv
245 self.ctx._client = client
246 ec = self.ctx._client.sf.getAdminService().getEventContext()
247 self.ctx._event_context = ec
248
249 msg = "%s session %s (%s@%s)." % (action, uuid, ec.userName, client.getProperty("omero.host"))
250 if idle:
251 msg = msg + " Idle timeout: %s min." % (float(idle)/60/1000)
252 if live:
253 msg = msg + " Expires in %s min." % (float(live)/60/1000)
254
255 msg += (" Current group: %s" % self.ctx._client.sf.getAdminService().getEventContext().groupName)
256
257 self.ctx.err(msg)
258
270
272 store = self.store(args)
273 client = self.ctx.conn(args)
274 sf = client.sf
275 admin = sf.getAdminService()
276
277 try:
278 group_id = long(args.target)
279 group_name = admin.getGroup(group_id).name.val
280 except ValueError, ve:
281 group_name = args.target
282 group_id = admin.lookupGroup(group_name).id.val
283
284 ec = admin.getEventContext()
285 old_id = ec.groupId
286 old_name = ec.groupName
287 if old_id == group_id:
288 self.ctx.err("Group '%s' (id=%s) is already active" % (group_name, group_id))
289 else:
290 sf.setSecurityContext(omero.model.ExperimenterGroupI(group_id, False))
291 self.ctx.out("Group '%s' (id=%s) switched to '%s' (id=%s)" % (old_name, old_id, group_name, group_id))
292
293 - def list(self, args):
294 import Glacier2
295 store = self.store(args)
296 s = store.contents()
297 previous = store.get_current()
298
299
300
301
302 headers = ("Server", "User", "Group", "Session", "Active", "Started")
303 results = dict([(x,[]) for x in headers])
304 for server, names in s.items():
305 for name, sessions in names.items():
306 for uuid, props in sessions.items():
307 rv = None
308 msg = "True"
309 grp = "Unknown"
310 started = "Unknown"
311 try:
312 rv = store.attach(server, name, uuid)
313 grp = rv[0].sf.getAdminService().getEventContext().groupName
314 started = rv[0].sf.getSessionService().getSession(uuid).started.val
315 started = time.ctime(started / 1000.0)
316 rv[0].closeSession()
317 except Glacier2.PermissionDeniedException, pde:
318 msg = pde.reason
319 except exceptions.Exception, e:
320 self.ctx.dbg("Exception on attach: %s" % e)
321 msg = "Unknown exception"
322 if rv is None and args.purge:
323 self.ctx.dbg("Purging %s / %s / %s" % (server, name, uuid))
324 store.remove(server, name, uuid)
325
326 if server == previous[0] and name == previous[1] and uuid == previous[2]:
327 msg = "Logged in"
328
329 results["Server"].append(server)
330 results["User"].append(name)
331 results["Group"].append(grp)
332 results["Session"].append(uuid)
333 results["Active"].append(msg)
334 results["Started"].append(started)
335
336 from omero.util.text import Table, Column
337 columns = tuple([Column(x, results[x]) for x in headers])
338 self.ctx.out(str(Table(*columns)))
339
345
358 t = T()
359 t.client = self.ctx.conn(args)
360 t.event = get_event()
361 t.start()
362 try:
363 self.ctx.out("Running keep alive every %s seconds" % args.frequency)
364 self.ctx.input("Press enter to cancel.")
365 finally:
366 t.client = None
367 t.event.set()
368
369 - def file(self, args):
374
375 - def conn(self, properties={}, profile=None, args=None):
376 """
377 Either creates or returns the exiting omero.client instance.
378 Uses the comm() method with the same signature.
379 """
380
381 if self._client:
382 return self._client
383
384 import omero
385 try:
386 data = self.initData(properties)
387 self._client = omero.client(sys.argv, id = data)
388 self._client.setAgent("OMERO.cli")
389 self._client.createSession()
390 return self._client
391 except Exc, exc:
392 self._client = None
393 raise
394
395
396
397
398
400 try:
401 idx = server.rindex("@")
402 return server[idx+1:], server[0:idx]
403 except ValueError:
404 return server, None
405
407 defserver = store.last_host()
408 rv = self.ctx.input("Server: [%s]" % defserver)
409 if not rv:
410 return defserver, None
411 else:
412 return self._parse_conn(rv)
413
415 defuser = getpass.getuser()
416 rv = self.ctx.input("Username: [%s]" % defuser)
417 if not rv:
418 return defuser
419 else:
420 return rv
421
422
423 try:
424 register("sessions", SessionsControl, HELP)
425 except NameError:
426 if __name__ == "__main__":
427 cli = CLI()
428 cli.register("sessions", SessionsControl, HELP)
429 cli.invoke(sys.argv[1:])
430