Removing useless prints and correcting attribute in api.
[sfa.git] / sfa / iotlab / iotlabpostgres.py
1 from sqlalchemy import create_engine
2 from sqlalchemy.orm import sessionmaker
3 from sfa.util.config import Config
4 from sfa.util.sfalogging import logger
5
6 from sqlalchemy import Column, Integer, String
7 from sqlalchemy import Table, MetaData
8 from sqlalchemy.ext.declarative import declarative_base
9
10 from sqlalchemy.dialects import postgresql
11
12 from sqlalchemy.exc import NoSuchTableError
13
14
15 #Dict holding the columns names of the table as keys
16 #and their type, used for creation of the table
17 slice_table = {'record_id_user': 'integer PRIMARY KEY references X ON DELETE \
18 CASCADE ON UPDATE CASCADE','oar_job_id':'integer DEFAULT -1',  \
19 'record_id_slice':'integer', 'slice_hrn':'text NOT NULL'}
20
21 #Dict with all the specific iotlab tables
22 tablenames_dict = {'iotlab_xp': slice_table}
23
24
25 IotlabBase = declarative_base()
26
27
28
29 class IotlabXP (IotlabBase):
30     """ SQL alchemy class to manipulate slice_iotlab table in
31     iotlab_sfa database.
32
33     """
34     __tablename__ = 'iotlab_xp'
35
36
37     slice_hrn = Column(String)
38     job_id = Column(Integer, primary_key = True)
39     end_time = Column(Integer, nullable = False)
40
41
42     #oar_job_id = Column( Integer,default = -1)
43     #node_list = Column(postgresql.ARRAY(String), nullable =True)
44
45     def __init__ (self, slice_hrn =None, job_id=None,  end_time=None):
46         """
47         Defines a row of the slice_iotlab table
48         """
49         if slice_hrn:
50             self.slice_hrn = slice_hrn
51         if job_id :
52             self.job_id = job_id
53         if end_time:
54             self.end_time = end_time
55
56
57     def __repr__(self):
58         """Prints the SQLAlchemy record to the format defined
59         by the function.
60         """
61         result = "<iotlab_xp : slice_hrn = %s , job_id %s end_time = %s" \
62             %(self.slice_hrn, self.job_id, self.end_time)
63         result += ">"
64         return result
65
66
67
68 class IotlabDB(object):
69     """ SQL Alchemy connection class.
70     From alchemy.py
71     """
72     # Stores the unique Singleton instance-
73     _connection_singleton = None
74     _dbname = "iotlab_sfa"
75
76
77     class Singleton:
78         """
79         Class used with this Python singleton design pattern
80             @todo Add all variables, and methods needed for the
81             Singleton class below
82         """
83
84         def __init__(self, config, debug = False):
85             self.iotlab_engine = None
86             self.iotlab_session = None
87             self.create_engine(config, debug)
88             self.session()
89
90         def create_engine(self, config, debug = False):
91
92
93             if debug == True:
94                 l_echo_pool = True
95                 l_echo = True
96             else:
97                 l_echo_pool = False
98                 l_echo = False
99              # the former PostgreSQL.py used the psycopg2 directly and was doing
100             #self.connection.set_client_encoding("UNICODE")
101             # it's unclear how to achieve this in sqlalchemy, nor if it's needed
102             # at all
103             # http://www.sqlalchemy.org/docs/dialects/postgresql.html#unicode
104             # we indeed have /var/lib/pgsql/data/postgresql.conf where
105             # this setting is unset, it might be an angle to tweak that if need
106             # be try a unix socket first
107             #  - omitting the hostname does the trick
108             unix_url = "postgresql+psycopg2://%s:%s@:%s/%s"% \
109                 (config.SFA_DB_USER, config.SFA_DB_PASSWORD, \
110                                         config.SFA_DB_PORT, IotlabDB._dbname)
111
112             # the TCP fallback method
113             tcp_url = "postgresql+psycopg2://%s:%s@%s:%s/%s"% \
114                 (config.SFA_DB_USER, config.SFA_DB_PASSWORD, config.SFA_DB_HOST, \
115                                         config.SFA_DB_PORT, IotlabDB._dbname)
116
117             for url in [ unix_url, tcp_url ] :
118                 try:
119                     self.iotlab_engine = create_engine (url, echo_pool =
120                                                 l_echo_pool, echo = l_echo)
121                     self.check()
122                     self.url = url
123                     return
124                 except:
125                     pass
126                 self.iotlab_engine = None
127
128
129             raise Exception, "Could not connect to database"
130
131         def check (self):
132             """ Check if a table exists by trying a selection
133             on the table.
134
135             """
136             self.iotlab_engine.execute ("select 1").scalar()
137
138
139         def session (self):
140             """
141             Creates a SQLalchemy session. Once the session object is created
142             it should be used throughout the code for all the operations on
143             tables for this given database.
144
145             """
146             if self.iotlab_session is None:
147                 Session = sessionmaker()
148                 self.iotlab_session = Session(bind = self.iotlab_engine)
149             return self.iotlab_session
150
151         def close_session(self):
152             """
153             Closes connection to database.
154
155             """
156             if self.iotlab_session is None:
157                 return
158             self.iotlab_session.close()
159             self.iotlab_session = None
160
161
162
163
164     def __init__(self, config, debug = False):
165         self.sl_base = IotlabBase
166
167          # Check whether we already have an instance
168         if IotlabDB._connection_singleton is None:
169             IotlabDB._connection_singleton = IotlabDB.Singleton(config, debug)
170
171         # Store instance reference as the only member in the handle
172         self._EventHandler_singleton = IotlabDB._connection_singleton
173
174
175
176     def __getattr__(self, aAttr):
177         """
178         Delegate access to implementation.
179
180         :param attr: Attribute wanted.
181         :return: Attribute
182         """
183         return getattr(self._connection_singleton, aAttr)
184
185
186
187     # def __setattr__(self, aAttr, aValue):
188     #     """Delegate access to implementation.
189
190     #      :param attr: Attribute wanted.
191     #      :param value: Vaule to be set.
192     #      :return: Result of operation.
193     #      """
194     #     return setattr(self._connection_singleton, aAttr, aValue)
195
196
197
198
199
200     def exists(self, tablename):
201         """
202         Checks if the table specified as tablename exists.
203
204         """
205
206         try:
207             metadata = MetaData (bind=self.iotlab_engine)
208             table = Table (tablename, metadata, autoload=True)
209             return True
210
211         except NoSuchTableError:
212             logger.log_exc("SLABPOSTGRES tablename %s does not exists" \
213                             %(tablename))
214             return False
215
216
217     def createtable(self):
218         """
219         Creates all the table sof the engine.
220         Uses the global dictionnary holding the tablenames and the table schema.
221
222         """
223
224         logger.debug("SLABPOSTGRES createtable IotlabBase.metadata.sorted_tables \
225             %s \r\n engine %s" %(IotlabBase.metadata.sorted_tables , self.iotlab_engine))
226         IotlabBase.metadata.create_all(self.iotlab_engine)
227         return
228
229
230
231 # iotlab_alchemy = IotlabDB(Config())
232 # iotlab_engine = iotlab_alchemy.iotlab_engine
233 # iotlab_dbsession = iotlab_alchemy.session()