pgsql.patch

Jeroen Nijhof, 10/14/2010 11:50 AM

Download (41.5 KB)

View differences:

one/include/History.h 2010-10-14 09:32:47.596176002 +0200
189 189
    int drop(SqlDB * db);
190 190

  
191 191
    /**
192
     *  Execute an INSERT or REPLACE Sql query.
192
     *  Execute an INSERT or UPDATE Sql query.
193 193
     *    @param db The SQL DB
194
     *    @param replace Execute an INSERT or a REPLACE
194
     *    @param update Execute an INSERT or a UPDATE
195 195
     *    @return 0 on success
196 196
     */
197
    int insert_replace(SqlDB *db, bool replace);
197
    int insert_update(SqlDB *db, bool update);
198 198

  
199 199
    /**
200 200
     *  Callback function to unmarshall a history object (History::select)
one/include/Host.h 2010-10-14 09:33:44.786176002 +0200
431 431
    // *************************************************************************
432 432

  
433 433
    /**
434
     *  Execute an INSERT or REPLACE Sql query.
434
     *  Execute an INSERT or UPDATE Sql query.
435 435
     *    @param db The SQL DB
436
     *    @param replace Execute an INSERT or a REPLACE
436
     *    @param update Execute an INSERT or a UPDATE
437 437
     *    @return 0 one success
438 438
    */
439
    int insert_replace(SqlDB *db, bool replace);
439
    int insert_update(SqlDB *db, bool update);
440 440

  
441 441
    /**
442 442
     *  Callback function to unmarshall a Host object (Host::select)
one/include/HostShare.h 2010-10-14 09:32:30.856176002 +0200
199 199
    int drop(SqlDB * db);
200 200

  
201 201
    /**
202
     *  Execute an INSERT or REPLACE Sql query.
202
     *  Execute an INSERT or UPDATE Sql query.
203 203
     *    @param db The SQL DB
204
     *    @param replace Execute an INSERT or a REPLACE
204
     *    @param update Execute an INSERT or a UPDATE
205 205
     *    @return 0 one success
206 206
    */
207
    int insert_replace(SqlDB *db, bool replace);
207
    int insert_update(SqlDB *db, bool update);
208 208

  
209 209
    /**
210 210
     *  Callback function to unmarshall a HostShare object (HostShare::select)
one/include/Image.h 2010-10-14 09:35:13.596176001 +0200
415 415
    // *************************************************************************
416 416

  
417 417
    /**
418
     *  Execute an INSERT or REPLACE Sql query.
418
     *  Execute an INSERT or UPDATE Sql query.
419 419
     *    @param db The SQL DB
420
     *    @param replace Execute an INSERT or a REPLACE
420
     *    @param update Execute an INSERT or a UPDATE
421 421
     *    @return 0 on success
422 422
    */
423
    int insert_replace(SqlDB *db, bool replace);
423
    int insert_update(SqlDB *db, bool update);
424 424

  
425 425
    /**
426 426
     *  Callback function to unmarshall a Image object (Image::select)
one/include/PGSqlDB.h 2010-10-14 09:18:05.126176001 +0200
1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)             */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

  
17
#ifndef PGSQL_DB_H_
18
#define PGSQL_DB_H_
19

  
20
#include <string>
21
#include <sstream>
22
#include <stdexcept>
23

  
24
#include <sys/time.h>
25
#include <sys/types.h>
26
#include <unistd.h>
27

  
28
#include "NebulaLog.h"
29
#include "SqlDB.h"
30
#include "ObjectSQL.h"
31

  
32

  
33
using namespace std;
34

  
35
#ifdef PGSQL_DB
36

  
37
#include <libpq-fe.h>
38

  
39
/**
40
 * PQDB class. Provides a wrapper to the postgresql database interface.
41
 */
42
class PGSqlDB : public SqlDB
43
{
44
public:
45

  
46
    PGSqlDB(const string& server,
47
            const string& user,
48
            const string& password,
49
            const string& database);
50

  
51
    ~PGSqlDB();
52

  
53
    /**
54
     *  Wraps the PQexec function call
55
     *    @param cmd the SQL command
56
     *    @param obj Callbackable obj to call if the query succeeds
57
     *    @return 0 on success
58
     */
59
    int exec(ostringstream& cmd, Callbackable* obj=0);
60

  
61
    /**
62
     *  This function returns a legal SQL string that can be used in an SQL
63
     *  statement. The string is encoded to an escaped SQL string, taking into
64
     *  account the current character set of the connection.
65
     *    @param str the string to be escaped
66
     *    @return a valid SQL string or NULL in case of failure
67
     */
68
    char * escape_str(const string& str);
69

  
70
    /**
71
     *  Frees a previously scaped string
72
     *    @param str pointer to the str
73
     */
74
    void free_str(char * str);
75

  
76
private:
77

  
78
    /**
79
     * The PostgreSQL connection handler
80
     */
81
    PGconn *             db;
82

  
83
    /**
84
     *  Fine-grain mutex for DB access
85
     */
86
    pthread_mutex_t     mutex;
87

  
88
    /**
89
     *  Function to lock the DB
90
     */
91
    void lock()
92
    {
93
        pthread_mutex_lock(&mutex);
94
    };
95

  
96
    /**
97
     *  Function to unlock the DB
98
     */
99
    void unlock()
100
    {
101
        pthread_mutex_unlock(&mutex);
102
    };
103
};
104
#else
105
//CLass stub
106
class PGSqlDB : public SqlDB
107
{
108
public:
109

  
110
    PGSqlDB(
111
            string server,
112
            string user,
113
            string password,
114
            char * database)
115
    {
116
        throw runtime_error("Aborting oned, PostgreSQL support not compiled!");
117
    };
118

  
119
    ~PGSqlDB(){};
120

  
121
    int exec(ostringstream& cmd, Callbackable* obj=0){return -1;};
122

  
123
    char * escape_str(const string& str){return 0;};
124

  
125
    void free_str(char * str){};
126
};
127
#endif
128

  
129
#endif /*PGSQL_DB_H_*/
130

  
one/include/User.h 2010-10-14 09:34:36.536176001 +0200
165 165
    // *************************************************************************
166 166

  
167 167
    /**
168
     *  Execute an INSERT or REPLACE Sql query.
168
     *  Execute an INSERT or UPDATE Sql query.
169 169
     *    @param db The SQL DB
170
     *    @param replace Execute an INSERT or a REPLACE
170
     *    @param update Execute an INSERT or a UPDATE
171 171
     *    @return 0 one success
172 172
     */
173
    int insert_replace(SqlDB *db, bool replace);
173
    int insert_update(SqlDB *db, bool update);
174 174

  
175 175
    /**
176 176
     *  Callback function to unmarshall a User object (User::select)
one/include/VirtualMachine.h 2010-10-14 09:34:14.356176002 +0200
908 908
    int select_cb(void *nil, int num, char **names, char ** values);
909 909

  
910 910
    /**
911
     *  Execute an INSERT or REPLACE Sql query.
911
     *  Execute an INSERT or UPDATE Sql query.
912 912
     *    @param db The SQL DB
913
     *    @param replace Execute an INSERT or a REPLACE
913
     *    @param update Execute an INSERT or a UPDATE
914 914
     *    @return 0 one success
915 915
    */
916
    int insert_replace(SqlDB *db, bool replace);
916
    int insert_update(SqlDB *db, bool update);
917 917

  
918 918
    /**
919 919
     *  Updates the VM history record
one/include/VirtualNetwork.h 2010-10-14 09:35:33.226176002 +0200
300 300
    // *************************************************************************
301 301

  
302 302
    /**
303
     *  Execute an INSERT or REPLACE Sql query.
303
     *  Execute an INSERT or UPDATE Sql query.
304 304
     *    @param db The SQL DB
305
     *    @param replace Execute an INSERT or a REPLACE
305
     *    @param update Execute an INSERT or a UPDATE
306 306
     *    @return 0 on success
307 307
     */
308
    int insert_replace(SqlDB *db, bool replace);
308
    int insert_update(SqlDB *db, bool update);
309 309

  
310 310
    /**
311 311
     *  Bootstraps the database table(s) associated to the Virtual Network
one/SConstruct 2010-10-14 09:18:17.816176001 +0200
108 108
else:
109 109
    main_env.Append(mysql='no')
110 110

  
111
# PostgreSQL
112
pgsql=ARGUMENTS.get('pgsql', 'no')
113
if pgsql=='yes':
114
    main_env.Append(pgsql='yes')
115
    main_env.Append(CPPFLAGS=["-DPGSQL_DB"])
116
    main_env.Append(CPPPATH=["/usr/include/postgresql"])
117
else:
118
    main_env.Append(pgsql='no')
119

  
111 120

  
112 121
# xmlrpc
113 122
xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none')
one/share/etc/oned.conf 2010-10-14 09:18:23.086176002 +0200
45 45
#        user    = "oneadmin",
46 46
#        passwd  = "oneadmin",
47 47
#        db_name = "opennebula" ]
48
#
49
# Sample configuration for PostgreSQL
50
# DB = [ backend = "pgsql",
51
#        server  = "localhost",
52
#        user    = "oneadmin",
53
#        passwd  = "oneadmin",
54
#        db_name = "opennebula" ]
48 55

  
49 56
VNC_BASE_PORT = 5000
50 57

  
one/src/host/ClusterPool.cc 2010-10-13 15:30:14.876176002 +0200
22 22
const char * ClusterPool::db_names = "oid, cluster_name";
23 23

  
24 24
const char * ClusterPool::db_bootstrap =
25
    "CREATE TABLE IF NOT EXISTS cluster_pool ("
25
    "CREATE TABLE cluster_pool ("
26 26
    "oid INTEGER PRIMARY KEY, cluster_name VARCHAR(128), "
27 27
    "UNIQUE(cluster_name) )";
28 28

  
one/src/host/Host.cc 2010-10-14 10:38:14.096176002 +0200
55 55
const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
56 56
                              "tm_mad,last_mon_time, cluster, template)";
57 57

  
58
const char * Host::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_pool ("
58
const char * Host::db_bootstrap = "CREATE TABLE host_pool ("
59 59
    "oid INTEGER PRIMARY KEY,host_name VARCHAR(256), state INTEGER,"
60 60
    "im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128),"
61 61
    "last_mon_time INTEGER, cluster VARCHAR(128), template TEXT, "
......
162 162
    }
163 163

  
164 164
    //Insert the Host
165
    rc = insert_replace(db, false);
165
    rc = insert_update(db, false);
166 166

  
167 167
    if ( rc != 0 )
168 168
    {
......
190 190
        return rc;
191 191
    }
192 192

  
193
    rc = insert_replace(db, true);
193
    rc = insert_update(db, true);
194 194

  
195 195
    if ( rc != 0 )
196 196
    {
......
205 205
/* ------------------------------------------------------------------------ */
206 206
/* ------------------------------------------------------------------------ */
207 207

  
208
int Host::insert_replace(SqlDB *db, bool replace)
208
int Host::insert_update(SqlDB *db, bool update)
209 209
{
210 210
    ostringstream   oss;
211 211

  
......
264 264
        goto error_template;
265 265
    }
266 266

  
267
    if(replace)
267
    if(update)
268 268
    {
269
        oss << "REPLACE";
269
        oss << "UPDATE " << table << " SET "
270
        << "host_name='" << sql_hostname << "',"
271
        << "state=" << state << ","
272
        << "im_mad='" << sql_im_mad_name << "',"
273
        << "vm_mad='" << sql_vmm_mad_name << "',"
274
        << "tm_mad='" << sql_tm_mad_name << "',"
275
        << "last_mon_time=" << last_monitored << ","
276
        << "cluster='" << sql_cluster << "',"
277
        << "template='" << sql_template << "' "
278
        << "WHERE oid=" << oid;
270 279
    }
271 280
    else
272 281
    {
273
        oss << "INSERT";
282
        oss << "INSERT"
283
        << " INTO " << table << " " << db_names << " VALUES ("
284
        << oid << ","
285
        << "'" << sql_hostname << "',"
286
        << state << ","
287
        << "'" << sql_im_mad_name << "',"
288
        << "'" << sql_vmm_mad_name << "',"
289
        << "'" << sql_tm_mad_name << "',"
290
        << last_monitored << ","
291
        << "'" << sql_cluster << "',"
292
        << "'" << sql_template << "')";
274 293
    }
275 294

  
276
    // Construct the SQL statement to Insert or Replace
277

  
278
    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
279
        <<          oid                 << ","
280
        << "'" <<   sql_hostname        << "',"
281
        <<          state               << ","
282
        << "'" <<   sql_im_mad_name     << "',"
283
        << "'" <<   sql_vmm_mad_name    << "',"
284
        << "'" <<   sql_tm_mad_name     << "',"
285
        <<          last_monitored      << ","
286
        << "'" <<   sql_cluster         << "',"
287
        << "'" <<   sql_template        << "')";
288

  
289 295
    rc = db->exec(oss);
290 296

  
291 297
    db->free_str(sql_hostname);
one/src/host/HostShare.cc 2010-10-14 10:43:12.896176002 +0200
63 63
    "used_disk,  used_mem,  used_cpu,"
64 64
    "running_vms)";
65 65

  
66
const char * HostShare::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_shares("
66
const char * HostShare::db_bootstrap = "CREATE TABLE host_shares("
67 67
    "hid INTEGER PRIMARY KEY,"
68 68
    "disk_usage INTEGER, mem_usage INTEGER, cpu_usage INTEGER,"
69 69
    "max_disk  INTEGER,  max_mem   INTEGER, max_cpu   INTEGER,"
......
201 201
{
202 202
    int rc;
203 203

  
204
    rc = insert_replace(db, false);
204
    rc = insert_update(db, false);
205 205

  
206 206
    if ( rc == -1 )
207 207
    {
......
218 218
{
219 219
    int             rc;
220 220

  
221
    rc = insert_replace(db, true);
221
    rc = insert_update(db, true);
222 222

  
223 223
    return rc;
224 224
}
......
226 226
/* ------------------------------------------------------------------------ */
227 227
/* ------------------------------------------------------------------------ */
228 228

  
229
int HostShare::insert_replace(SqlDB *db, bool replace)
229
int HostShare::insert_update(SqlDB *db, bool update)
230 230
{
231 231
    ostringstream   oss;
232 232
    int             rc;
233 233

  
234
    if(replace)
234
    if(update)
235 235
    {
236
        oss << "REPLACE";
236
        oss << "UPDATE " << table << " SET "
237
        << "disk_usage=" << disk_usage << ","
238
        << "mem_usage=" << mem_usage << ","
239
        << "cpu_usage=" << cpu_usage << ","
240
        << "max_disk=" << max_disk << ","
241
        << "max_mem=" << max_mem << ","
242
        << "max_cpu=" << max_cpu << ","
243
        << "free_disk=" << free_disk << ","
244
        << "free_mem=" << free_mem << ","
245
        << "free_cpu=" << free_cpu << ","
246
        << "used_disk=" << used_disk << ","
247
        << "used_mem=" << used_mem << ","
248
        << "used_cpu=" << used_cpu << " "
249
        << "WHERE hid=" << hsid;
237 250
    }
238 251
    else
239 252
    {
240
        oss << "INSERT";
241
    }
242

  
243
    oss << " INTO " << table << " "<< db_names <<" VALUES ("
253
        oss << "INSERT"
254
        << " INTO " << table << " "<< db_names <<" VALUES ("
244 255
        << hsid << ","
245 256
        << disk_usage <<","<< mem_usage <<","<< cpu_usage<< ","
246 257
        << max_disk   <<","<< max_mem   <<","<< max_cpu  << ","
247 258
        << free_disk  <<","<< free_mem  <<","<< free_cpu << ","
248 259
        << used_disk  <<","<< used_mem  <<","<< used_cpu << ","
249 260
        << running_vms<< ")";
261
    }
250 262

  
251 263
    rc = db->exec(oss);
252 264

  
one/src/image/Image.cc 2010-10-14 10:34:32.296176001 +0200
69 69
const char * Image::db_names = "(oid, uid, name, type, public, persistent, regtime, "
70 70
                               "source, state, running_vms, template)";
71 71

  
72
const char * Image::db_bootstrap = "CREATE TABLE IF NOT EXISTS image_pool ("
72
const char * Image::db_bootstrap = "CREATE TABLE image_pool ("
73 73
    "oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(128), "
74 74
    "type INTEGER, public INTEGER, persistent INTEGER, regtime INTEGER, source TEXT, state INTEGER, "
75 75
    "running_vms INTEGER, template TEXT, UNIQUE(name) )";
......
244 244
    // Insert the Image
245 245
    //--------------------------------------------------------------------------
246 246

  
247
    rc = insert_replace(db, false);
247
    rc = insert_update(db, false);
248 248

  
249 249
    if ( rc == -1 )
250 250
    {
......
275 275

  
276 276
int Image::update(SqlDB *db)
277 277
{
278
    return insert_replace(db, true);;
278
    return insert_update(db, true);;
279 279
}
280 280

  
281 281
/* ------------------------------------------------------------------------ */
282 282
/* ------------------------------------------------------------------------ */
283 283

  
284
int Image::insert_replace(SqlDB *db, bool replace)
284
int Image::insert_update(SqlDB *db, bool update)
285 285
{
286 286
    ostringstream   oss;
287 287

  
......
317 317
        goto error_template;
318 318
    }
319 319

  
320
    if(replace)
320
    if(update)
321 321
    {
322
        oss << "REPLACE";
322
        oss << "UPDATE " << table << " SET "
323
        << "uid=" << uid << ","
324
        << "name='" << sql_name << "',"
325
        << "type=" << type << ","
326
        << "public=" << public_img << ","
327
        << "persistent=" << persistent_img << ","
328
        << "regtime=" << regtime << ","
329
        << "source='" << sql_source << "',"
330
        << "state=" << state << ","
331
        << "running_vms=" << running_vms << ","
332
        << "template='" << sql_template << "' "
333
        << "WHERE oid=" << oid;
323 334
    }
324 335
    else
325 336
    {
326
        oss << "INSERT";
337
        oss << "INSERT"
338
        <<" INTO " << table << " " << db_names << " VALUES ("
339
        << oid << ","
340
        << uid << ","
341
        << "'" << sql_name << "',"
342
        << type << ","
343
        << public_img << ","
344
        << persistent_img << ","
345
        << regtime << ","
346
        << "'" << sql_source << "',"
347
        << state << ","
348
        << running_vms << ","
349
        << "'" << sql_template << "')";
327 350
    }
328 351

  
329
    // Construct the SQL statement to Insert or Replace
330

  
331
    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
332
        <<          oid             << ","
333
        <<          uid             << ","
334
        << "'" <<   sql_name        << "',"
335
        <<          type            << ","
336
        <<          public_img      << ","
337
        <<          persistent_img  << ","
338
        <<          regtime         << ","
339
        << "'" <<   sql_source      << "',"
340
        <<          state           << ","
341
        <<          running_vms     << ","
342
        << "'" <<   sql_template    << "')";
343

  
344 352
    rc = db->exec(oss);
345 353

  
346 354
    db->free_str(sql_name);
one/src/nebula/Nebula.cc 2010-10-14 10:51:44.986176001 +0200
19 19
#include "VirtualMachine.h"
20 20
#include "SqliteDB.h"
21 21
#include "MySqlDB.h"
22
#include "PGSqlDB.h"
22 23

  
23 24
#include <stdlib.h>
24 25
#include <stdexcept>
......
139 140
        int  rc;
140 141

  
141 142
        bool   db_is_sqlite = true;
143
        bool   db_is_mysql = false;
144
        bool   db_is_pgsql = false;
142 145

  
143 146
        string server  = "localhost";
144 147
        string user    = "oneadmin";
......
154 157
                                              (dbs[0]);
155 158
            value = db->vector_value("BACKEND");
156 159

  
157
            if (value == "mysql")
160
            if (value == "mysql"||value == "pgsql")
158 161
            {
159 162
                db_is_sqlite = false;
163
                if (value == "mysql")
164
                    db_is_mysql = true;
165
                if (value == "pgsql")
166
                    db_is_pgsql = true;
160 167

  
161 168
                value = db->vector_value("SERVER");
162 169
                if (!value.empty())
......
186 193

  
187 194
        if ( db_is_sqlite )
188 195
        {
189
            string  db_name = var_location + "one.db";
196
            string db_name = var_location + "one.db";
190 197

  
191 198
            db = new SqliteDB(db_name);
192 199
        }
193
        else
200
        if ( db_is_mysql )
194 201
        {
195 202
            ostringstream   oss;
196 203

  
......
212 219
                throw runtime_error("Could not open database.");
213 220
            }
214 221
        }
222
        if ( db_is_pgsql )
223
        {
224
            db = new PGSqlDB(server,user,passwd,db_name);
225
        }
215 226

  
216
        NebulaLog::log("ONE",Log::INFO,"Bootstraping OpenNebula database.");
227
        ostringstream oss;
228
        oss << "SELECT oid FROM vm_pool";
229
        rc = db->exec(oss);
230
        if ( rc != 0 )
231
        {
232
            NebulaLog::log("ONE",Log::INFO,"Table not found, running for the first time?");
233
            NebulaLog::log("ONE",Log::INFO,"Bootstraping OpenNebula database.");
217 234

  
218
        VirtualMachinePool::bootstrap(db);
219
        HostPool::bootstrap(db);
220
        VirtualNetworkPool::bootstrap(db);
221
        UserPool::bootstrap(db);
222
        ImagePool::bootstrap(db);
235
            VirtualMachinePool::bootstrap(db);
236
            HostPool::bootstrap(db);
237
            VirtualNetworkPool::bootstrap(db);
238
            UserPool::bootstrap(db);
239
            ImagePool::bootstrap(db);
240
        }
223 241
    }
224 242
    catch (exception&)
225 243
    {
one/src/nebula/SConstruct 2010-10-13 15:26:57.396176002 +0200
61 61
if env['mysql']=='yes':
62 62
    env.Append(LIBS=['mysqlclient'])
63 63

  
64
if env['pgsql']=='yes':
65
    env.Append(LIBS=['pq'])
66

  
64 67

  
65 68
if not env.GetOption('clean'):
66 69
    env.ParseConfig('../../share/scons/get_xmlrpc_config server')
one/src/pool/PoolSQL.cc 2010-10-13 18:17:19.946176002 +0200
23 23
#include "PoolSQL.h"
24 24

  
25 25
#include <errno.h>
26
#include <cstring>
26 27

  
27 28
/* ************************************************************************** */
28 29
/* PoolSQL constructor/destructor                                             */
......
40 41
{
41 42
    lastOID = -1;
42 43

  
43
    if ( values[0] != 0 )
44
    if ( values[0] != 0 && strcmp(values[0], "") != 0)
44 45
    {
45 46
        lastOID = atoi(values[0]);
46 47
    }
one/src/pool/test/TestPoolSQL.cc 2010-10-14 10:32:31.166176001 +0200
117 117

  
118 118
    sql_text   = db->escape_str(text.c_str());
119 119

  
120
    oss << "REPLACE INTO " << table << " "<< db_names <<" VALUES ("
121
        << oid << ","
122
        << number << ","
123
        << "'" << sql_text << "')";
120
    oss << "UPDATE " << table << " SET "
121
        << "number="<< number << ","
122
        << "text='" << sql_text << "' "
123
        << "WHERE oid=" << oid;
124 124

  
125 125
    rc = db->exec(oss);
126 126

  
one/src/sql/PGSqlDB.cc 2010-10-14 09:18:30.976176002 +0200
1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)             */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

  
17
#include "PGSqlDB.h"
18

  
19
/*********
20
 * Doc: http://www.postgresql.org/docs/8.3/static/libpq.html
21
 ********/
22

  
23
/* -------------------------------------------------------------------------- */
24

  
25
PGSqlDB::PGSqlDB(
26
        const string& server,
27
        const string& user,
28
        const string& password,
29
        const string& database)
30
{
31

  
32
    // Initialize a connection handler and connect to the server
33
    ostringstream oss;
34
    oss << "dbname=" << database << " host=" << server.c_str()
35
            << " user=" << user.c_str() << " password=" << password.c_str();
36

  
37
    string str = oss.str();
38
    const char *conninfo = str.c_str();
39

  
40
    db = PQconnectdb(conninfo);
41

  
42
    // Connect to the server
43
    if (PQstatus(db) != CONNECTION_OK)
44
    {
45
        PQfinish(db);
46
        throw runtime_error("Could not open database.");
47
    }
48

  
49
    pthread_mutex_init(&mutex,0);
50
}
51

  
52
/* -------------------------------------------------------------------------- */
53

  
54
PGSqlDB::~PGSqlDB()
55
{
56
    // Close the connection to the PostgreSQL server
57
    PQfinish(db);
58

  
59
    pthread_mutex_destroy(&mutex);
60
}
61

  
62
/* -------------------------------------------------------------------------- */
63

  
64
int PGSqlDB::exec(ostringstream& cmd, Callbackable* obj)
65
{
66
    PGresult * res;
67
    ExecStatusType status;
68

  
69
    const char * c_str;
70
    string       str;
71

  
72

  
73
    int   (*callback)(void*,int,char**,char**);
74
    void * arg;
75

  
76
    str   = cmd.str();
77
    c_str = str.c_str();
78

  
79
    callback = 0;
80
    arg      = 0;
81

  
82
    lock();
83

  
84
    res = PQexec(db, c_str);
85
    status = PQresultStatus(res);
86

  
87
    if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK)
88
    {
89
        ostringstream   oss;
90
        const char *    err_msg = PQerrorMessage(db);
91

  
92
        oss << "SQL command was: " << c_str;
93
        oss << ", error " << err_msg;
94

  
95
        NebulaLog::log("ONE",Log::ERROR,oss);
96

  
97
        PQclear(res);
98

  
99
        unlock();
100

  
101
        return -1;
102
    }
103

  
104

  
105
    if ( (obj != 0) && (obj->isCallBackSet()) )
106
    {
107
        int        num_fields;
108

  
109
        if (status != PGRES_TUPLES_OK)
110
        {
111
            ostringstream   oss;
112
            const char *    err_msg = PQerrorMessage(db);
113

  
114
            oss << "SQL command was: " << c_str;
115
            oss << ", error " << err_msg;
116

  
117
            NebulaLog::log("ONE",Log::ERROR,oss);
118

  
119
            PQclear(res);
120

  
121
            unlock();
122

  
123
            return -1;
124
        }
125

  
126
        // Fetch the names of the fields
127
        num_fields  = PQnfields(res);
128
        char ** names = new char*[num_fields];
129

  
130
        for(int i = 0; i < num_fields; i++)
131
        {
132
            names[i] = PQfname(res, i);
133
        }
134

  
135
        // Fetch each row, and call-back the object waiting for them
136
        char ** row = new char*[num_fields];
137

  
138
        for (int r = 0; r < PQntuples(res); r++)
139
        {
140
            for (int i = 0; i < num_fields; i++)
141
                row[i] = PQgetvalue(res, r, i);
142
            obj->do_callback(num_fields, row, names);
143
        }
144

  
145
        // Free the result object
146
        PQclear(res);
147

  
148
        delete[] names;
149
    }
150

  
151
    unlock();
152

  
153
    return 0;
154
}
155

  
156
/* -------------------------------------------------------------------------- */
157

  
158
char * PGSqlDB::escape_str(const string& str)
159
{
160
    char * result = new char[str.size()*2+1];
161

  
162
    PQescapeStringConn(db, result, str.c_str(), str.size(), NULL);
163

  
164
    return result;
165
}
166

  
167
/* -------------------------------------------------------------------------- */
168

  
169
void PGSqlDB::free_str(char * str)
170
{
171
    delete[] str;
172
}
173

  
174
/* -------------------------------------------------------------------------- */
one/src/sql/SConstruct 2010-10-13 15:22:18.356176001 +0200
29 29
if env['mysql']=='yes':
30 30
    source_files.append('MySqlDB.cc')
31 31

  
32
if env['pgsql']=='yes':
33
    source_files.append('PGSqlDB.cc')
34

  
32 35
# Build library
33
env.StaticLibrary(lib_name, source_files)
36
env.StaticLibrary(lib_name, source_files)
one/src/um/User.cc 2010-10-14 10:30:11.926176001 +0200
52 52

  
53 53
const char * User::db_names = "(oid,user_name,password,enabled)";
54 54

  
55
const char * User::db_bootstrap = "CREATE TABLE IF NOT EXISTS user_pool ("
55
const char * User::db_bootstrap = "CREATE TABLE user_pool ("
56 56
    "oid INTEGER PRIMARY KEY, user_name VARCHAR(256), password TEXT,"
57 57
    "enabled INTEGER, UNIQUE(user_name))";
58 58

  
......
115 115
{
116 116
    int rc;
117 117

  
118
    rc = insert_replace(db, false);
118
    rc = insert_update(db, false);
119 119

  
120 120
    if ( rc != 0 )
121 121
    {
......
133 133
{
134 134
    int rc;
135 135

  
136
    rc = insert_replace(db, true);
136
    rc = insert_update(db, true);
137 137

  
138 138
    if ( rc != 0 )
139 139
    {
......
146 146
/* -------------------------------------------------------------------------- */
147 147
/* -------------------------------------------------------------------------- */
148 148

  
149
int User::insert_replace(SqlDB *db, bool replace)
149
int User::insert_update(SqlDB *db, bool update)
150 150
{
151 151
    ostringstream   oss;
152 152

  
......
174 174
    }
175 175

  
176 176
    // Construct the SQL statement to Insert or Replace
177
    if(replace)
177
    if(update)
178 178
    {
179
        oss << "REPLACE";
179
        oss << "UPDATE " << table << " SET "
180
        << "user_name='" << sql_username << "',"
181
        << "password='" << sql_password << "',"
182
        << "enabled='" << str_enabled << "' "
183
        << "WHERE oid=" << oid;
180 184
    }
181 185
    else
182 186
    {
183
        oss << "INSERT";
184
    }
185

  
186
    oss << " INTO " << table << " "<< db_names <<" VALUES ("
187
        oss << "INSERT"
188
        << " INTO " << table << " "<< db_names <<" VALUES ("
187 189
        << oid << ","
188 190
        << "'" << sql_username << "',"
189 191
        << "'" << sql_password << "',"
190 192
        << str_enabled << ")";
193
    }
191 194

  
192 195
    rc = db->exec(oss);
193 196

  
one/src/vm/History.cc 2010-10-14 10:23:46.276176002 +0200
28 28
const char * History::db_names = "(vid,seq,host_name,vm_dir,hid,vm_mad,tm_mad,stime,"
29 29
    "etime,pstime,petime,rstime,retime,estime,eetime,reason)";
30 30

  
31
const char * History::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
31
const char * History::db_bootstrap = "CREATE TABLE "
32 32
    "history (vid INTEGER,"
33 33
    "seq INTEGER,host_name TEXT,vm_dir TEXT,hid INTEGER,vm_mad TEXT,tm_mad TEXT,"
34 34
    "stime INTEGER,etime INTEGER,pstime INTEGER,petime INTEGER,rstime INTEGER,"
......
139 139
{
140 140
    int             rc;
141 141

  
142
    rc = insert_replace(db, false);
142
    rc = insert_update(db, false);
143 143

  
144 144
    return rc;
145 145
}
......
151 151
{
152 152
    int             rc;
153 153

  
154
    rc = insert_replace(db, true);
154
    rc = insert_update(db, true);
155 155

  
156 156
    return rc;
157 157
}
......
159 159
/* -------------------------------------------------------------------------- */
160 160
/* -------------------------------------------------------------------------- */
161 161

  
162
int History::insert_replace(SqlDB *db, bool replace)
162
int History::insert_update(SqlDB *db, bool update)
163 163
{
164 164
    ostringstream   oss;
165 165

  
......
203 203
        goto error_tm;
204 204
    }
205 205

  
206
    if(replace)
206
    if(update)
207 207
    {
208
        oss << "REPLACE";
208
        oss << "UPDATE " << table << " SET "
209
        << "seq=" << seq << ","
210
        << "host_name='" << sql_hostname << "',"
211
        << "vm_dir='" << sql_vm_dir << "',"
212
        << "hid=" << hid << ","
213
        << "vm_mad='" << sql_vmm_mad_name << "',"
214
        << "tm_mad='" << sql_tm_mad_name << "',"
215
        << "stime=" << stime << ","
216
        << "etime=" << etime << ","
217
        << "pstime=" << prolog_stime << ","
218
        << "petime=" << prolog_etime << ","
219
        << "rstime=" << running_stime << ","
220
        << "retime=" << running_etime << ","
221
        << "estime=" << epilog_stime << ","
222
        << "eetime=" << epilog_etime << ","
223
        << "reason=" << reason << " "
224
        << "WHERE vid=" << oid;
209 225
    }
210 226
    else
211 227
    {
212
        oss << "INSERT";
228
        oss << "INSERT"
229
        << " INTO " << table << " "<< db_names <<" VALUES ("
230
        << oid << ","
231
        << seq << ","
232
        << "'" << sql_hostname << "',"
233
        << "'" << sql_vm_dir << "',"
234
        << hid << ","
235
        << "'" << sql_vmm_mad_name << "',"
236
        << "'" << sql_tm_mad_name  << "',"
237
        << stime << ","
238
        << etime << ","
239
        << prolog_stime  << ","
240
        << prolog_etime  << ","
241
        << running_stime << ","
242
        << running_etime << ","
243
        << epilog_stime  << ","
244
        << epilog_etime  << ","
245
        << reason << ")";
213 246
    }
214 247

  
215
    oss << " INTO " << table << " "<< db_names <<" VALUES ("<<
216
        oid << "," <<
217
        seq << "," <<
218
        "'" << sql_hostname << "',"<<
219
        "'" << sql_vm_dir << "'," <<
220
        hid << "," <<
221
        "'" << sql_vmm_mad_name << "'," <<
222
        "'" << sql_tm_mad_name  << "'," <<
223
        stime << "," <<
224
        etime << "," <<
225
        prolog_stime  << "," <<
226
        prolog_etime  << "," <<
227
        running_stime << "," <<
228
        running_etime << "," <<
229
        epilog_stime  << "," <<
230
        epilog_etime  << "," <<
231
        reason << ")";
232

  
233 248
    rc = db->exec(oss);
234 249

  
235 250
    db->free_str(sql_hostname);
one/src/vm/VirtualMachine.cc 2010-10-14 10:39:44.286176001 +0200
98 98
    "(oid,uid,name,last_poll, state,lcm_state,stime,etime,deploy_id"
99 99
    ",memory,cpu,net_tx,net_rx,last_seq, template)";
100 100

  
101
const char * VirtualMachine::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
101
const char * VirtualMachine::db_bootstrap = "CREATE TABLE "
102 102
        "vm_pool ("
103 103
        "oid INTEGER PRIMARY KEY,uid INTEGER,name TEXT,"
104 104
        "last_poll INTEGER, state INTEGER,lcm_state INTEGER,"
......
338 338
    // Insert the VM
339 339
    // ------------------------------------------------------------------------
340 340

  
341
    rc = insert_replace(db, false);
341
    rc = insert_update(db, false);
342 342

  
343 343
    if ( rc != 0 )
344 344
    {
......
550 550

  
551 551
int VirtualMachine::update(SqlDB * db)
552 552
{
553
    return insert_replace(db, true);
553
    return insert_update(db, true);
554 554
}
555 555

  
556 556
/* ------------------------------------------------------------------------ */
557 557
/* ------------------------------------------------------------------------ */
558 558

  
559
int VirtualMachine::insert_replace(SqlDB *db, bool replace)
559
int VirtualMachine::insert_update(SqlDB *db, bool update)
560 560
{
561 561
    ostringstream   oss;
562 562
    int             rc;
......
589 589
    }
590 590

  
591 591

  
592
    if(replace)
592
    if(update)
593 593
    {
594
        oss << "REPLACE";
594
        oss << "UPDATE " << table << " SET "
595
        << "uid=" << uid << ","
596
        << "name='" << sql_name << "',"
597
        << "last_poll=" << last_poll << ","
598
        << "state=" << state << ","
599
        << "lcm_state=" << lcm_state << ","
600
        << "stime=" << stime << ","
601
        << "etime=" << etime << ","
602
        << "deploy_id='" << sql_deploy_id << "',"
603
        << "memory=" << memory << ","
604
        << "cpu=" << cpu << ","
605
        << "net_tx=" << net_tx << ","
606
        << "net_rx=" << net_rx << ","
607
        << "last_seq=" << last_seq << ","
608
        << "template='" << sql_template << "' "
609
        << "WHERE oid=" << oid;
595 610
    }
596 611
    else
597 612
    {
598
        oss << "INSERT";
613
        oss << "INSERT"
614
        << " INTO " << table << " " << db_names << " VALUES ("
615
        << oid << ","
616
        << uid << ","
617
        << "'" << sql_name        << "',"
618
        << last_poll << ","
619
        << state << ","
620
        << lcm_state << ","
621
        << stime << ","
622
        << etime << ","
623
        << "'" << sql_deploy_id << "',"
624
        << memory << ","
625
        << cpu << ","
626
        << net_tx << ","
627
        << net_rx << ","
628
        << last_seq << ","
629
        << "'" << sql_template << "')";
599 630
    }
600 631

  
601
    oss << " INTO " << table << " "<< db_names <<" VALUES ("
602
        <<          oid             << ","
603
        <<          uid             << ","
604
        << "'" <<   sql_name        << "',"
605
        <<          last_poll       << ","
606
        <<          state           << ","
607
        <<          lcm_state       << ","
608
        <<          stime           << ","
609
        <<          etime           << ","
610
        << "'" <<   sql_deploy_id   << "',"
611
        <<          memory          << ","
612
        <<          cpu             << ","
613
        <<          net_tx          << ","
614
        <<          net_rx          << ","
615
        <<          last_seq        << ","
616
        << "'" <<   sql_template    << "')";
617

  
618 632
    db->free_str(sql_deploy_id);
619 633
    db->free_str(sql_name);
620 634
    db->free_str(sql_template);
one/src/vnm/Leases.cc 2010-10-13 15:29:33.916176001 +0200
250 250

  
251 251
const char * Leases::db_names     = "(oid,ip,mac_prefix,mac_suffix,vid,used)";
252 252

  
253
const char * Leases::db_bootstrap = "CREATE TABLE IF NOT EXISTS leases ("
253
const char * Leases::db_bootstrap = "CREATE TABLE leases ("
254 254
                "oid INTEGER, ip BIGINT, mac_prefix BIGINT, mac_suffix BIGINT,"
255 255
                "vid INTEGER, used INTEGER, PRIMARY KEY(oid,ip))";
256 256

  
one/src/vnm/VirtualNetwork.cc 2010-10-14 10:32:12.656176002 +0200
72 72
const char * VirtualNetwork::db_names     =
73 73
                                "(oid,uid,name,type,bridge,public,template)";
74 74

  
75
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS"
76
    " network_pool ("
77
     "oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(256), type INTEGER, "
78
     "bridge TEXT, public INTEGER, template TEXT, UNIQUE(name))";
75
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE "
76
    "network_pool ("
77
    "oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(256), type INTEGER, "
78
    "bridge TEXT, public INTEGER, template TEXT, UNIQUE(name))";
79 79

  
80 80
/* -------------------------------------------------------------------------- */
81 81
/* -------------------------------------------------------------------------- */
......
397 397
    //--------------------------------------------------------------------------
398 398
    // Insert the Virtual Network
399 399
    //--------------------------------------------------------------------------
400
    rc = insert_replace(db, false);
400
    rc = insert_update(db, false);
401 401

  
402 402
    if ( rc != 0 )
403 403
    {
......
443 443

  
444 444
int VirtualNetwork::update(SqlDB * db)
445 445
{
446
    return insert_replace(db, true);
446
    return insert_update(db, true);
447 447
}
448 448

  
449
int VirtualNetwork::insert_replace(SqlDB *db, bool replace)
449
int VirtualNetwork::insert_update(SqlDB *db, bool update)
450 450
{
451 451
    ostringstream   oss;
452 452
    int             rc;
......
483 483

  
484 484

  
485 485
    // Construct the SQL statement to Insert or Replace
486
    if(replace)
486
    if(update)
487 487
    {
488
        oss << "REPLACE";
488
        oss << "UPDATE " << table << " SET "
489
        << "uid=" << uid << ","
490
        << "name='" << sql_name << "',"
491
        << "type=" << type << ","
492
        << "bridge='" << sql_bridge << "',"
493
        << "public=" << public_vnet << ","
494
        << "template='" << sql_template << "' "
495
        << "WHERE oid=" << oid;
489 496
    }
490 497
    else
491 498
    {
492
        oss << "INSERT";
499
        oss << "INSERT"
500
        << " INTO " << table << " " << db_names << " VALUES ("
501
        << oid << ","
502
        << uid << ","
503
        << "'" <<   sql_name << "',"
504
        << type << ","
505
        << "'" << sql_bridge << "',"
506
        << public_vnet << ","
507
        << "'" << sql_template << "')";
493 508
    }
494 509

  
495
    oss << " INTO " << table << " "<< db_names <<" VALUES ("
496
        <<          oid         << ","
497
        <<          uid         << ","
498
        << "'" <<   sql_name    << "',"
499
        <<          type        << ","
500
        << "'" <<   sql_bridge  << "',"
501
        <<          public_vnet << ","
502
        << "'" <<   sql_template<< "')";
503

  
504 510
    rc = db->exec(oss);
505 511

  
506 512
    db->free_str(sql_name);
one/src/vnm/VirtualNetworkPool.cc 2010-10-13 22:07:29.006176001 +0200
187 187
    }
188 188

  
189 189
    cmd << " GROUP BY " << VirtualNetwork::table << ".oid";
190
    cmd << "," << VirtualNetwork::table << ".uid";
191
    cmd << "," << VirtualNetwork::table << ".name";
192
    cmd << "," << VirtualNetwork::table << ".type";
193
    cmd << "," << VirtualNetwork::table << ".bridge";
194
    cmd << "," << VirtualNetwork::table << ".public";
195
    cmd << "," << VirtualNetwork::table << ".template";
196
    cmd << ",user_pool.user_name";
190 197

  
191 198
    rc = db->exec(cmd,this);
192 199