Cleaning slabslices and slapostgres.
[sfa.git] / sfa / senslab / slabpostgres.py
1 from sqlalchemy import create_engine
2 from sqlalchemy.orm import sessionmaker
3
4 from sfa.util.config import Config
5 from sfa.util.sfalogging import logger
6
7 from sqlalchemy import Column, Integer, String
8 from sqlalchemy import Table, MetaData
9 from sqlalchemy.ext.declarative import declarative_base
10
11 from sqlalchemy.dialects import postgresql
12
13 from sqlalchemy.exc import NoSuchTableError
14
15
16 #Dict holding the columns names of the table as keys
17 #and their type, used for creation of the table
18 slice_table = {'record_id_user': 'integer PRIMARY KEY references X ON DELETE \
19 CASCADE ON UPDATE CASCADE','oar_job_id':'integer DEFAULT -1',  \
20 'record_id_slice':'integer', 'slice_hrn':'text NOT NULL'}
21
22 #Dict with all the specific senslab tables
23 tablenames_dict = {'slice_senslab': slice_table}
24
25
26 SlabBase = declarative_base()
27
28 class SliceSenslab (SlabBase):
29     """ SQL alchemy class to manipulate slice_senslab table in 
30     slab_sfa database.
31     
32     """
33     __tablename__ = 'slice_senslab' 
34     #record_id_user = Column(Integer, primary_key=True)
35
36     slice_hrn = Column(String, primary_key=True)
37     peer_authority = Column(String, nullable = True)
38     record_id_slice = Column(Integer)    
39     record_id_user = Column(Integer) 
40
41     #oar_job_id = Column( Integer,default = -1)
42     #node_list = Column(postgresql.ARRAY(String), nullable =True)
43     
44     def __init__ (self, slice_hrn =None, record_id_slice=None, \
45                                     record_id_user= None,peer_authority=None):
46         """
47         Defines a row of the slice_senslab table
48         """
49         if record_id_slice: 
50             self.record_id_slice = record_id_slice
51         if slice_hrn:
52             self.slice_hrn = slice_hrn
53         if record_id_user: 
54             self.record_id_user = record_id_user
55         if peer_authority:
56             self.peer_authority = peer_authority
57             
58             
59     def __repr__(self):
60         """Prints the SQLAlchemy record to the format defined
61         by the function.
62         """
63         result="<Record id user =%s, slice hrn=%s, Record id slice =%s , \
64                 peer_authority =%s"% (self.record_id_user, self.slice_hrn, \
65                 self.record_id_slice, self.peer_authority)
66         result += ">"
67         return result
68           
69     def dump_sqlalchemyobj_to_dict(self):
70         """Transforms a SQLalchemy record object to a python dictionary.
71         Returns the dictionary.
72         """
73         
74         dict = {'slice_hrn':self.slice_hrn,
75         'peer_authority':self.peer_authority,
76         'record_id':self.record_id_slice, 
77         'record_id_user':self.record_id_user,
78         'record_id_slice':self.record_id_slice, }
79         return dict 
80           
81           
82 class SlabDB:
83     """ SQL Aclehmy connection class.
84     From alchemy.py
85     """
86     def __init__(self,config, debug = False):
87         self.sl_base = SlabBase
88         dbname = "slab_sfa"
89         if debug == True :
90             l_echo_pool = True
91             l_echo=True 
92         else :
93             l_echo_pool = False
94             l_echo = False 
95
96         self.slab_session = None
97         # the former PostgreSQL.py used the psycopg2 directly and was doing
98         #self.connection.set_client_encoding("UNICODE")
99         # it's unclear how to achieve this in sqlalchemy, nor if it's needed 
100         # at all
101         # http://www.sqlalchemy.org/docs/dialects/postgresql.html#unicode
102         # we indeed have /var/lib/pgsql/data/postgresql.conf where
103         # this setting is unset, it might be an angle to tweak that if need be
104         # try a unix socket first - omitting the hostname does the trick
105         unix_url = "postgresql+psycopg2://%s:%s@:%s/%s"%\
106             (config.SFA_DB_USER, config.SFA_DB_PASSWORD, \
107                                     config.SFA_DB_PORT, dbname)
108
109         # the TCP fallback method
110         tcp_url = "postgresql+psycopg2://%s:%s@%s:%s/%s"%\
111             (config.SFA_DB_USER, config.SFA_DB_PASSWORD, config.SFA_DB_HOST, \
112                                     config.SFA_DB_PORT, dbname)
113         for url in [ unix_url, tcp_url ] :
114             try:
115                 self.slab_engine = create_engine (url, echo_pool = \
116                                             l_echo_pool, echo = l_echo)
117                 self.check()
118                 self.url = url
119                 return
120             except:
121                 pass
122         self.slab_engine = None
123         raise Exception, "Could not connect to database"
124     
125     
126     
127     def check (self):
128         """ Cehck if a table exists by trying a selection
129         on the table. 
130         
131         """
132         self.slab_engine.execute ("select 1").scalar()
133         
134         
135     def session (self):
136         """
137         Creates a SQLalchemy session. Once the session object is created
138         it should be used throughout the code for all the operations on 
139         tables for this given database.
140         
141         """ 
142         if self.slab_session is None:
143             Session = sessionmaker()
144             self.slab_session = Session(bind = self.slab_engine)
145         return self.slab_session
146         
147        
148     def close(self):
149         """
150         Closes connection to database. 
151         
152         """
153         if self.connection is not None:
154             self.connection.close()
155             self.connection = None
156             
157
158     def exists(self, tablename):
159         """
160         Checks if the table specified as tablename exists.
161     
162         """
163        
164         try:
165             metadata = MetaData (bind=self.slab_engine)
166             table = Table (tablename, metadata, autoload=True)
167             return True
168         
169         except NoSuchTableError:
170             logger.log_exc("SLABPOSTGRES tablename %s does not exists" \
171                             %(tablename))
172             return False
173        
174     
175     def createtable(self, tablename ):
176         """
177         Creates the specifed table. Uses the global dictionnary holding the 
178         tablenames and the table schema.
179     
180         """
181
182         logger.debug("SLABPOSTGRES createtable SlabBase.metadata.sorted_tables \
183             %s \r\n engine %s" %(SlabBase.metadata.sorted_tables , slab_engine))
184         SlabBase.metadata.create_all(slab_engine)
185         return
186     
187
188 from sfa.util.config import Config
189
190 slab_alchemy = SlabDB(Config())
191 slab_engine = slab_alchemy.slab_engine
192 slab_dbsession = slab_alchemy.session()