4e3c6df425ac468b57b48fed0d1afedbf06b6d92
[sfa.git] / sfa / iotlab / iotlabpostgres.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 iotlab tables
23 tablenames_dict = {'iotlab_xp': slice_table}
24
25
26 IotlabBase = declarative_base()
27
28
29
30 class IotlabXP (IotlabBase):
31     """ SQL alchemy class to manipulate slice_iotlab table in
32     iotlab_sfa database.
33
34     """
35     __tablename__ = 'iotlab_xp'
36
37
38     slice_hrn = Column(String)
39     job_id = Column(Integer, primary_key = True)
40     end_time = Column(Integer, nullable = False)
41
42
43     #oar_job_id = Column( Integer,default = -1)
44     #node_list = Column(postgresql.ARRAY(String), nullable =True)
45
46     def __init__ (self, slice_hrn =None, job_id=None,  end_time=None):
47         """
48         Defines a row of the slice_iotlab table
49         """
50         if slice_hrn:
51             self.slice_hrn = slice_hrn
52         if job_id :
53             self.job_id = job_id
54         if end_time:
55             self.end_time = end_time
56
57
58     def __repr__(self):
59         """Prints the SQLAlchemy record to the format defined
60         by the function.
61         """
62         result = "<iotlab_xp : slice_hrn = %s , job_id %s end_time = %s" \
63             %(self.slice_hrn, self.job_id, self.end_time)
64         result += ">"
65         return result
66
67
68
69 class IotlabDB:
70     """ SQL Alchemy connection class.
71     From alchemy.py
72     """
73     def __init__(self, config, debug = False):
74         self.sl_base = IotlabBase
75         dbname = "iotlab_sfa"
76         if debug == True :
77             l_echo_pool = True
78             l_echo = True
79         else :
80             l_echo_pool = False
81             l_echo = False
82
83         self.iotlab_session = None
84         # the former PostgreSQL.py used the psycopg2 directly and was doing
85         #self.connection.set_client_encoding("UNICODE")
86         # it's unclear how to achieve this in sqlalchemy, nor if it's needed
87         # at all
88         # http://www.sqlalchemy.org/docs/dialects/postgresql.html#unicode
89         # we indeed have /var/lib/pgsql/data/postgresql.conf where
90         # this setting is unset, it might be an angle to tweak that if need be
91         # try a unix socket first - omitting the hostname does the trick
92         unix_url = "postgresql+psycopg2://%s:%s@:%s/%s"% \
93             (config.SFA_DB_USER, config.SFA_DB_PASSWORD, \
94                                     config.SFA_DB_PORT, dbname)
95
96         # the TCP fallback method
97         tcp_url = "postgresql+psycopg2://%s:%s@%s:%s/%s"% \
98             (config.SFA_DB_USER, config.SFA_DB_PASSWORD, config.SFA_DB_HOST, \
99                                     config.SFA_DB_PORT, dbname)
100         for url in [ unix_url, tcp_url ] :
101             try:
102                 self.iotlab_engine = create_engine (url, echo_pool = \
103                                             l_echo_pool, echo = l_echo)
104                 self.check()
105                 self.url = url
106                 return
107             except:
108                 pass
109         self.iotlab_engine = None
110         raise Exception, "Could not connect to database"
111
112
113
114     def check (self):
115         """ Cehck if a table exists by trying a selection
116         on the table.
117
118         """
119         self.iotlab_engine.execute ("select 1").scalar()
120
121
122     def session (self):
123         """
124         Creates a SQLalchemy session. Once the session object is created
125         it should be used throughout the code for all the operations on
126         tables for this given database.
127
128         """
129         if self.iotlab_session is None:
130             Session = sessionmaker()
131             self.iotlab_session = Session(bind = self.iotlab_engine)
132         return self.iotlab_session
133
134     def close_session(self):
135         """
136         Closes connection to database.
137
138         """
139         if self.iotlab_session is None: return
140         self.iotlab_session.close()
141         self.iotlab_session = None
142
143
144     def exists(self, tablename):
145         """
146         Checks if the table specified as tablename exists.
147
148         """
149
150         try:
151             metadata = MetaData (bind=self.iotlab_engine)
152             table = Table (tablename, metadata, autoload=True)
153             return True
154
155         except NoSuchTableError:
156             logger.log_exc("SLABPOSTGRES tablename %s does not exists" \
157                             %(tablename))
158             return False
159
160
161     def createtable(self):
162         """
163         Creates all the table sof the engine.
164         Uses the global dictionnary holding the tablenames and the table schema.
165
166         """
167
168         logger.debug("SLABPOSTGRES createtable IotlabBase.metadata.sorted_tables \
169             %s \r\n engine %s" %(IotlabBase.metadata.sorted_tables , iotlab_engine))
170         IotlabBase.metadata.create_all(iotlab_engine)
171         return
172
173
174
175 iotlab_alchemy = IotlabDB(Config())
176 iotlab_engine = iotlab_alchemy.iotlab_engine
177 iotlab_dbsession = iotlab_alchemy.session()