Package omero :: Package util :: Module sessions
[hide private]
[frames] | no frames]

Source Code for Module omero.util.sessions

  1  #!/usr/bin/env python 
  2  """ 
  3     Library for managing user sessions. 
  4   
  5     Copyright 2010 Glencoe Software, Inc. All rights reserved. 
  6     Use is subject to license terms supplied in LICENSE.txt 
  7   
  8  """ 
  9   
 10  """ 
 11   * Track last used 
 12   * provide single library (with lock) which does all of this 
 13     - save session 
 14     - clear session 
 15     - check session # detachOnDestroy 
 16     - list previous sessions 
 17   * Use an environment variable for changing directories 
 18   
 19  import subprocess, optparse, os, sys 
 20  import getpass, pickle 
 21  import omero.java 
 22  from omero.cli import Arguments, BaseControl, VERSION 
 23  from path import path 
 24   
 25  """ 
 26   
 27  from omero.util import get_user_dir, make_logname 
 28  from path import path 
 29   
 30  import logging 
 31  import exceptions 
 32   
 33   
34 -class SessionsStore(object):
35 """ 36 The store is a file-based repository of user sessions. 37 By default, stores use $HOME/omero/sessions as their 38 repository path. 39 40 Use add() to add items to the repository 41 """ 42
43 - def __init__(self, dir = None):
44 """ 45 """ 46 self.logger = logging.getLogger(make_logname(self)) 47 if dir == None: 48 dir = get_user_dir() 49 self.dir = path(dir) / "omero" / "sessions" 50 if not self.dir.exists(): 51 self.dir.makedirs() 52 try: 53 self.dir.chmod(0700) 54 except: 55 print "WARN: failed to chmod %s" % self.dir
56 57 # 58 # File-only methods 59 # 60
61 - def report(self):
62 """ 63 Simple dump utility 64 """ 65 for host in self.dir.dirs(): 66 print "[%s]" % host 67 for name in host.dirs(): 68 print " -> %s : " % name 69 for sess in name.files(): 70 print " %s" % sess
71
72 - def add(self, host, name, id, props):
73 """ 74 Stores a file containing the properties at 75 REPO/host/name/id 76 """ 77 78 props["omero.host"] = host 79 props["omero.user"] = name 80 props["omero.sess"] = id 81 82 lines = [] 83 for k,v in props.items(): 84 lines.append("%s=%s" % (k, v)) 85 86 dhn = self.dir / host / name 87 if not dhn.exists(): 88 dhn.makedirs() 89 90 (dhn / id).write_lines(lines)
91
92 - def conflicts(self, host, name, id, new_props, ignore_nulls = False):
93 """ 94 Compares if the passed properties are compatible with 95 with those for the host, name, id tuple 96 97 If ignore_nulls is True, then a null in new_props means matches 98 anything. 99 """ 100 conflicts = "" 101 old_props = self.get(host, name, id) 102 for key in ("omero.group", "omero.port"): 103 old = old_props.get(key, None) 104 new = new_props.get(key, None) 105 if ignore_nulls and new is None: 106 continue 107 elif old != new: 108 conflicts += (key + (":%s!=%s;" % (old, new))) 109 return conflicts
110
111 - def remove(self, host, name, uuid):
112 """ 113 Removes the given session file from the store 114 and removes the sess_file() if it is equal to 115 the session we just removed. 116 """ 117 if uuid is None: 118 self.logger.debug("No uuid provided") 119 return 120 d = self.dir / host / name 121 f = self.dir / host / name / uuid 122 if d.exists(): 123 if f.exists(): 124 f.remove() 125 self.logger.debug("Removed %s" % f) 126 s = self.sess_file(host, name) 127 if s and s.exists() and s.text().strip() == uuid: 128 s.remove() 129 self.logger.debug("Removed %s" % s)
130
131 - def exists(self, host, name, uuid):
132 """ 133 Checks if the given file exists. 134 """ 135 d = self.dir 136 for x in (host, name, uuid): 137 d = d / x 138 if not d.exists(): 139 return False 140 return True
141
142 - def get(self, host, name, uuid):
143 """ 144 Returns the properties stored in the given session file 145 """ 146 return self.props(self.dir / host / name / uuid)
147
148 - def available(self, host, name):
149 """ 150 Returns the path to property files which are stored. 151 Internal accounting files are not returned. 152 """ 153 d = self.dir / host / name 154 if not d.exists(): 155 return [] 156 return [x.basename() for x in self.non_dot(d)]
157
158 - def set_current(self, host, name = None, uuid = None):
159 """ 160 Sets the current session, user, and host files 161 These are used as defaults by other methods. 162 """ 163 if host is not None: self.host_file().write_text(host) 164 if name is not None: self.user_file(host).write_text(name) 165 if uuid is not None: self.sess_file(host, name).write_text(uuid)
166
167 - def get_current(self):
168 host = None 169 name = None 170 uuid = None 171 if self.host_file().exists(): 172 host = self.host_file().text().strip() 173 if host: 174 try: 175 name = self.user_file(host).text().strip() 176 except IOError: 177 pass 178 if name: 179 try: 180 uuid = self.sess_file(host, name).text().strip() 181 except IOError: 182 pass 183 return (host, name, uuid)
184
185 - def last_host(self):
186 """ 187 Prints either the last saved host (see get_current()) 188 or "localhost" 189 """ 190 f = self.host_file() 191 if not f.exists(): 192 return "localhost" 193 text = f.text().strip() 194 if not text: 195 return "localhost" 196 return text
197
198 - def find_name_by_key(self, server, uuid):
199 """ 200 Returns the name of a user for which the 201 session key exists. This value is taken 202 from the path rather than from the properties 203 file since that value may have been overwritten. 204 An exception is raised if there is more than one 205 name since keys should be UUIDs. A None may be 206 returned. 207 """ 208 s = self.dir / server 209 if not s.exists(): 210 return None 211 else: 212 n = [x.basename() for x in s.dirs() if (x/uuid).exists()] 213 if not n: 214 return None 215 elif len(n) == 1: 216 return n[0] 217 else: 218 raise exceptions.Exception("Multiple names found for uuid=%s: %s" % (uuid, ", ".join(n)))
219
220 - def contents(self):
221 """ 222 Returns a map of maps with all the contents 223 of the store. Internal accounting files are 224 skipped. 225 """ 226 rv = {} 227 Dhosts = self.dir.dirs() 228 for Dhost in Dhosts: 229 host = str(Dhost.basename()) 230 if host not in rv: 231 rv[host] = {} 232 Dnames = Dhost.dirs() 233 for Dname in Dnames: 234 name = str(Dname.basename()) 235 if name not in rv[host]: 236 rv[host][name] = {} 237 Dids = self.non_dot(Dname) 238 for Did in Dids: 239 id = str(Did.basename()) 240 props = self.props(Did) 241 props["active"] = "unknown" 242 rv[host][name][id] = props 243 return rv
244
245 - def count(self, host=None, name=None):
246 """ 247 Returns the sum of all files visited by walk() 248 """ 249 def f(h, n, s): 250 f.i += 1
251 f.i = 0 252 self.walk(f, host, name) 253 return f.i
254
255 - def walk(self, func, host=None, name=None, sess=None):
256 """ 257 Applies func to all host, name, and session path-objects. 258 """ 259 for h in self.dir.dirs(): 260 if host is None or str(h.basename()) == host: 261 for n in h.dirs(): 262 if name is None or str(n.basename()) == name: 263 for s in self.non_dot(n): 264 if sess is None or str(s.basename()) == sess: 265 func(h, n, s)
266 267 268 # 269 # Server-requiring methods 270 # 271
272 - def attach(self, server, name, sess, set_current = True):
273 """ 274 Simple helper. Delegates to create() using the session 275 as both the username and the password. This reproduces 276 the logic of client.joinSession() 277 """ 278 props = self.get(server, name, sess) 279 return self.create(sess, sess, props, new = False, set_current = set_current)
280
281 - def create(self, name, pasw, props, new = True, set_current = True):
282 """ 283 Creates a new omero.client object, and returns: 284 (cilent, session_id, timeToIdle, timeToLive) 285 """ 286 import omero.clients 287 props = dict(props) 288 host = props["omero.host"] 289 client = omero.client(props) 290 client.setAgent("OMERO.sessions") 291 sf = client.createSession(name, pasw) 292 ec = sf.getAdminService().getEventContext() 293 uuid = sf.ice_getIdentity().name 294 sf.detachOnDestroy() 295 sess = sf.getSessionService().getSession(uuid) 296 timeToIdle = sess.getTimeToIdle().getValue() 297 timeToLive = sess.getTimeToLive().getValue() 298 if new: 299 self.add(host, ec.userName, uuid, props) 300 if set_current: 301 self.set_current(host, ec.userName, uuid) 302 303 return client, uuid, timeToIdle, timeToLive
304
305 - def clear(self, host = None, name = None, sess = None):
306 """ 307 Walks through all sessions and calls killSession. 308 Regardless of exceptions, it will remove the session files 309 from the store. 310 """ 311 removed = [] 312 def f(h, n, s): 313 hS = str(h.basename()) 314 nS = str(n.basename()) 315 sS = str(s.basename()) 316 try: 317 client = self.attach(hS, nS, sS) 318 client.killSession() 319 except exceptions.Exception, e: 320 self.logger.debug("Exception on killSession: %s" % e) 321 s.remove() 322 removed.append(s)
323 self.walk(f, host, name, sess) 324 return removed 325 326 ## 327 ## Helpers. Do not modify or rely on mutable state. 328 ## 329
330 - def host_file(self):
331 """ Returns the path-object which stores the last active host """ 332 return self.dir / "._LASTHOST_"
333
334 - def user_file(self, host):
335 """ Returns the path-object which stores the last active user """ 336 d = self.dir / host 337 if not d.exists(): 338 d.makedirs() 339 return d / "._LASTUSER_"
340
341 - def sess_file(self, host, user):
342 """ Returns the path-object which stores the last active session """ 343 d = self.dir / host / user 344 if not d.exists(): 345 d.makedirs() 346 return d / "._LASTSESS_"
347
348 - def non_dot(self, d):
349 """ Only returns the files (not directories) contained in d that don't start with a dot """ 350 return [f for f in d.files("*") if not str(f.basename()).startswith(".")]
351
352 - def props(self, f):
353 """ 354 Parses the path-object into properties 355 """ 356 txt = f.text() 357 lines = txt.split("\n") 358 props = {} 359 for line in lines: 360 if not line: 361 continue 362 parts = line.split("=",1) 363 if len(parts) == 1: 364 parts.append("") 365 props[parts[0]] = parts[1] 366 return props
367 368 if __name__ == "__main__": 369 SessionsStore().report() 370