Statistics
| Branch: | Tag: | Revision:

one / src / vm_template / test / VMTemplatePoolTest.cc @ b7febc83

History | View | Annotate | Download (17.5 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2011, 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 <string>
18
#include <iostream>
19
#include <stdlib.h>
20

    
21
#include "VMTemplatePool.h"
22
#include "PoolTest.h"
23

    
24
using namespace std;
25

    
26
const int uids[] = {0,1,2};
27
const string user_names[] = {"A user","B user","C user"};
28

    
29
const string names[] = {"Template one", "Second Template", "Third Template"};
30

    
31
const string templates[] =
32
{
33
    "NAME   = \"Template one\"\n"
34
    "MEMORY = 128\n"
35
    "CPU    = 1",
36

    
37
    "NAME   = \"Second Template\"\n"
38
    "MEMORY = 256\n"
39
    "CPU    = 2",
40

    
41
    "NAME   = \"Third Template\"\n"
42
    "MEMORY = 1024\n"
43
    "CPU    = 3"
44
};
45

    
46

    
47
const string xmls[] =
48
{
49
    "<VMTEMPLATE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Template one</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[1]]></CPU><MEMORY><![CDATA[128]]></MEMORY><NAME><![CDATA[Template one]]></NAME></TEMPLATE></VMTEMPLATE>",
50

    
51
    "<VMTEMPLATE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Template</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[2]]></CPU><MEMORY><![CDATA[256]]></MEMORY><NAME><![CDATA[Second Template]]></NAME></TEMPLATE></VMTEMPLATE>",
52

    
53
    "<VMTEMPLATE><ID>2</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>Third Template</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[3]]></CPU><MEMORY><![CDATA[1024]]></MEMORY><NAME><![CDATA[Third Template]]></NAME></TEMPLATE></VMTEMPLATE>"
54
};
55

    
56

    
57
// This xml dump result has the STIMEs modified to 0000000000
58
const string xml_dump =
59
    "<VMTEMPLATE_POOL><VMTEMPLATE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Template one</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[1]]></CPU><MEMORY><![CDATA[128]]></MEMORY><NAME><![CDATA[Template one]]></NAME></TEMPLATE></VMTEMPLATE><VMTEMPLATE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Template</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[2]]></CPU><MEMORY><![CDATA[256]]></MEMORY><NAME><![CDATA[Second Template]]></NAME></TEMPLATE></VMTEMPLATE><VMTEMPLATE><ID>2</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>Third Template</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[3]]></CPU><MEMORY><![CDATA[1024]]></MEMORY><NAME><![CDATA[Third Template]]></NAME></TEMPLATE></VMTEMPLATE></VMTEMPLATE_POOL>";
60
const string xml_dump_where =
61
    "<VMTEMPLATE_POOL><VMTEMPLATE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Template one</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[1]]></CPU><MEMORY><![CDATA[128]]></MEMORY><NAME><![CDATA[Template one]]></NAME></TEMPLATE></VMTEMPLATE><VMTEMPLATE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Template</NAME><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><TEMPLATE><CPU><![CDATA[2]]></CPU><MEMORY><![CDATA[256]]></MEMORY><NAME><![CDATA[Second Template]]></NAME></TEMPLATE></VMTEMPLATE></VMTEMPLATE_POOL>";
62

    
63
const string replacement = "0000000000";
64

    
65
class VMTemplatePoolFriend : public VMTemplatePool
66
{
67
public:
68
    VMTemplatePoolFriend(SqlDB * db) : VMTemplatePool(db){};
69

    
70
    int allocate(int    uid,
71
                 const  string& stemplate,
72
                 int *  oid)
73
     {
74
        VirtualMachineTemplate *    template_contents;
75
        char *                      error_msg = 0;
76
        int                         rc;
77
        string                      err;
78

    
79
        template_contents = new VirtualMachineTemplate();
80
        rc = template_contents->parse(stemplate,&error_msg);
81

    
82
        if( rc == 0 )
83
        {
84
            return VMTemplatePool::allocate(uid, user_names[uid], template_contents, oid, err);
85
        }
86
        else
87
        {
88
            if (error_msg != 0 )
89
            {
90
                free(error_msg);
91
            }
92

    
93
            delete template_contents;
94
            return -2;
95
        }
96
    };
97
};
98

    
99
/* ************************************************************************* */
100
/* ************************************************************************* */
101

    
102
class VMTemplatePoolTest : public PoolTest
103
{
104
    CPPUNIT_TEST_SUITE (VMTemplatePoolTest);
105

    
106
    ALL_POOLTEST_CPPUNIT_TESTS();
107

    
108
    CPPUNIT_TEST ( names_initialization );
109
    CPPUNIT_TEST ( clone_template );
110
    CPPUNIT_TEST ( update );
111
    CPPUNIT_TEST ( get_using_name );
112
    CPPUNIT_TEST ( wrong_get_name );
113
    CPPUNIT_TEST ( duplicates );
114
    CPPUNIT_TEST ( public_attribute );
115
    CPPUNIT_TEST ( dump );
116
    CPPUNIT_TEST ( dump_where );
117

    
118
    CPPUNIT_TEST_SUITE_END ();
119

    
120
protected:
121

    
122
    void bootstrap(SqlDB* db)
123
    {
124
        VMTemplatePool::bootstrap(db);
125
    };
126

    
127
    PoolSQL* create_pool(SqlDB* db)
128
    {
129
        return new VMTemplatePoolFriend(db);
130
    };
131

    
132
    int allocate(int index)
133
    {
134
        int oid;
135
        return ((VMTemplatePoolFriend*)pool)->allocate(uids[index],
136
                                               templates[index],
137
                                               &oid);
138

    
139
    };
140

    
141
    void check(int index, PoolObjectSQL* obj)
142
    {
143
        CPPUNIT_ASSERT( obj != 0 );
144

    
145
        string xml_str = "";
146

    
147
        // Get the xml and replace the REGTIME to 0, so we can compare
148
        // it.
149
        ((VMTemplate*)obj)->to_xml(xml_str);
150
        xml_str.replace( xml_str.find("<REGTIME>")+9, 10, replacement);
151

    
152
/*
153
        if( xml_str != xmls[index] )
154
        {
155
            cout << endl << xml_str << endl << xmls[index] << endl;
156
        }
157
//*/
158

    
159
        CPPUNIT_ASSERT( obj->get_name() == names[index] );
160
        CPPUNIT_ASSERT( xml_str == xmls[index]);
161
    };
162

    
163
public:
164
    VMTemplatePoolTest(){xmlInitParser();};
165

    
166
    ~VMTemplatePoolTest(){xmlCleanupParser();};
167

    
168

    
169
    /* ********************************************************************* */
170

    
171
    void names_initialization()
172
    {
173
        VMTemplatePoolFriend *  tpool;
174
        VMTemplate *            temp;
175

    
176
        // Allocate 2 Templates, so they are written to the DB.
177
        allocate(0);
178
        allocate(2);
179

    
180
        // Create a new pool, using the same DB. This new pool should read the
181
        // allocated Templates.
182
        tpool = new VMTemplatePoolFriend(db);
183

    
184
        temp = tpool->get(names[0], uids[0], false);
185
        CPPUNIT_ASSERT( temp != 0 );
186

    
187
        temp = tpool->get(names[1], uids[1], false);
188
        CPPUNIT_ASSERT( temp == 0 );
189

    
190
        temp = tpool->get(names[2], uids[2], false);
191
        CPPUNIT_ASSERT( temp != 0 );
192

    
193

    
194
        delete tpool;
195
    }
196

    
197
/* -------------------------------------------------------------------------- */
198
/* -------------------------------------------------------------------------- */
199

    
200
    void clone_template()
201
    {
202
        string      attr_temp;
203
        string      attr_vmt;
204

    
205
        string      name1 = "NAME";
206
        string      name2 = "MEMORY";
207

    
208
        VMTemplatePoolFriend *   tpool;
209
        VMTemplate *             temp;
210
        VirtualMachineTemplate * vmt;
211

    
212
        int                     oid_1;
213

    
214
        tpool = static_cast<VMTemplatePoolFriend *>(pool);
215
        oid_1 = allocate(0);
216

    
217
        temp = tpool->get(oid_1, true);
218
        CPPUNIT_ASSERT( temp != 0 );
219

    
220
        vmt = temp->clone_template();
221

    
222
        vmt->get(name1,attr_vmt);
223
        CPPUNIT_ASSERT( attr_vmt == "Template one");
224

    
225
        temp->get_template_attribute(name1.c_str(), attr_temp);
226
        CPPUNIT_ASSERT( attr_temp == "Template one");
227

    
228
        temp->replace_template_attribute(name2.c_str(), "1024");
229

    
230
        vmt->get(name2,attr_vmt);
231
        CPPUNIT_ASSERT( attr_vmt == "128");
232

    
233
        temp->get_template_attribute(name2.c_str(), attr_temp);
234
        CPPUNIT_ASSERT( attr_temp == "1024");
235

    
236
        delete vmt;
237

    
238
        temp->get_template_attribute(name2.c_str(), attr_temp);
239
        CPPUNIT_ASSERT( attr_temp == "1024");
240

    
241
        tpool->update(temp);
242

    
243
        temp->unlock();
244
    };
245
/* -------------------------------------------------------------------------- */
246
/* -------------------------------------------------------------------------- */
247

    
248
    void update()
249
    {
250
        string      description_name    = "DESCRIPTION";
251
        string      description_val     = "";
252
        string      new_description     = "A new description";
253

    
254
        string      attr_name       = "NEW_ATTRIBUTE";
255
        string      attr_val        = "";
256
        string      new_attr_value  = "New value";
257

    
258
        string      no_value        = "Some random value";
259

    
260
        VMTemplatePoolFriend *  tpool;
261
        VMTemplate *            temp;
262
        int                     oid_1;
263

    
264
        tpool = static_cast<VMTemplatePoolFriend *>(pool);
265
        oid_1 = allocate(0);
266

    
267
        temp = tpool->get(oid_1, true);
268
        CPPUNIT_ASSERT( temp != 0 );
269

    
270
        // Object should be cached. Let's change some template attributes
271
        temp->replace_template_attribute(description_name, new_description);
272
        temp->replace_template_attribute(attr_name,        new_attr_value);
273
        temp->remove_template_attribute("ORIGINAL_PATH");
274

    
275
        tpool->update(temp);
276

    
277
        temp->unlock();
278

    
279
        temp = tpool->get(oid_1,false);
280
        CPPUNIT_ASSERT( temp != 0 );
281

    
282

    
283
        temp->get_template_attribute("DESCRIPTION",   description_val);
284
        temp->get_template_attribute("NEW_ATTRIBUTE", attr_val);
285
        temp->get_template_attribute("ORIGINAL_PATH", no_value);
286

    
287
        CPPUNIT_ASSERT( description_val == new_description );
288
        CPPUNIT_ASSERT( attr_val        == new_attr_value );
289
        CPPUNIT_ASSERT( no_value        == "" );
290

    
291
        //Now force access to DB
292

    
293
        pool->clean();
294
        temp = tpool->get(oid_1,false);
295

    
296
        CPPUNIT_ASSERT( temp != 0 );
297

    
298
        description_val = "";
299
        attr_val        = "";
300
        no_value        = "Random value";
301
        temp->get_template_attribute("DESCRIPTION",   description_val);
302
        temp->get_template_attribute("NEW_ATTRIBUTE", attr_val);
303
        temp->get_template_attribute("ORIGINAL_PATH", no_value);
304

    
305
        CPPUNIT_ASSERT( description_val == new_description );
306
        CPPUNIT_ASSERT( attr_val        == new_attr_value );
307
        CPPUNIT_ASSERT( no_value        == "" );
308
    };
309

    
310
/* -------------------------------------------------------------------------- */
311
/* -------------------------------------------------------------------------- */
312

    
313
    void get_using_name()
314
    {
315
        int oid_0, oid_1;
316

    
317
        // Allocate two objects
318
        oid_0 = allocate(0);
319
        oid_1 = allocate(1);
320

    
321
        // ---------------------------------
322
        // Get first object and check its integrity
323
        obj = pool->get(oid_0, false);
324
        CPPUNIT_ASSERT( obj != 0 );
325
        check(0, obj);
326

    
327
        // Get using its name
328
        obj = pool->get(names[1], uids[1], true);
329
        CPPUNIT_ASSERT( obj != 0 );
330
        obj->unlock();
331

    
332
        check(1, obj);
333

    
334

    
335
        // ---------------------------------
336
        // Clean the cache, forcing the pool to read the objects from the DB
337
        pool->clean();
338

    
339
        // Get first object and check its integrity
340
        obj = pool->get(names[0], uids[0], false);
341
        check(0, obj);
342

    
343
        // Get using its name
344
        obj = pool->get(oid_1, false);
345
        check(1, obj);
346
    };
347

    
348
/* -------------------------------------------------------------------------- */
349
/* -------------------------------------------------------------------------- */
350

    
351
    void wrong_get_name()
352
    {
353
        // The pool is empty
354
        // Non existing name
355
        obj = pool->get("Wrong name", 0, true);
356
        CPPUNIT_ASSERT( obj == 0 );
357

    
358
        // Allocate an object
359
        allocate(0);
360

    
361
        // Ask again for a non-existing name
362
        obj = pool->get("Non existing name",uids[0], true);
363
        CPPUNIT_ASSERT( obj == 0 );
364
    }
365

    
366
/* -------------------------------------------------------------------------- */
367
/* -------------------------------------------------------------------------- */
368

    
369
    void duplicates()
370
    {
371
        int rc, oid;
372
        VMTemplatePoolFriend * tpool = static_cast<VMTemplatePoolFriend*>(pool);
373

    
374
        // Allocate a template
375
        rc = tpool->allocate(uids[0], templates[0], &oid);
376
        CPPUNIT_ASSERT( oid == 0 );
377
        CPPUNIT_ASSERT( oid == rc );
378

    
379
        // Try to allocate twice the same template, should fail
380
        rc = tpool->allocate(uids[0], templates[0], &oid);
381
        CPPUNIT_ASSERT( rc  == -1 );
382
        CPPUNIT_ASSERT( oid == rc );
383

    
384
        // Try again, this time with different uid. Should be allowed
385
        rc = tpool->allocate(uids[1], templates[0], &oid);
386
        CPPUNIT_ASSERT( rc  >= 0 );
387
        CPPUNIT_ASSERT( oid == rc );
388
    }
389

    
390
/* -------------------------------------------------------------------------- */
391
/* -------------------------------------------------------------------------- */
392

    
393
    void public_attribute()
394
    {
395
        int oid;
396
        VMTemplatePoolFriend *  tpool = static_cast<VMTemplatePoolFriend *>(pool);
397
        VMTemplate *            temp;
398

    
399
        string templates[] =
400
        {
401
            // false
402
            "NAME           = \"name A\"\n",
403

    
404
            // true
405
            "NAME           = \"name B\"\n"
406
            "PUBLIC         = YES",
407

    
408
            // false
409
            "NAME           = \"name C\"\n"
410
            "PUBLIC         = NO",
411

    
412
            // false
413
            "NAME           = \"name D\"\n"
414
            "PUBLIC         = 1",
415

    
416
            // true
417
            "NAME           = \"name E\"\n"
418
            "PUBLIC         = Yes",
419

    
420
            // false
421
            "NAME           = \"name F\"\n"
422
            "PUBLIC         = TRUE",
423

    
424
            // true
425
            "NAME           = \"name G\"\n"
426
            "PUBLIC         = yes",
427

    
428
            // false
429
            "NAME           = \"name H\"\n"
430
            "PUBLIC         = 'YES'",
431

    
432
            // true
433
            "NAME           = \"name I\"\n"
434
            "PUBLIC         = \"YES\"",
435

    
436
            "END"
437
        };
438

    
439
        bool results[] = {  false, true, false, false,
440
                            true, false, true, false, true };
441

    
442
        int i = 0;
443
        while( templates[i] != "END" )
444
        {
445

    
446
            tpool->allocate(0, templates[i], &oid);
447

    
448
            CPPUNIT_ASSERT( oid >= 0 );
449

    
450
            temp = tpool->get( oid, false );
451
            CPPUNIT_ASSERT( temp != 0 );
452
//cout << endl << i << " : exp. " << results[i] << " got " << temp->is_public();
453

    
454
            CPPUNIT_ASSERT( temp->isPublic() == results[i] );
455

    
456
            i++;
457
        }
458

    
459
        bool success;
460

    
461
        // temp 0 is not public.
462
        temp = tpool->get( 0, false );
463
        CPPUNIT_ASSERT( temp != 0 );
464

    
465
        success = temp->publish(false);
466
        CPPUNIT_ASSERT( success == true );
467
        CPPUNIT_ASSERT( temp->isPublic() == false );
468

    
469
        success = temp->publish(true);
470
        CPPUNIT_ASSERT( success == true );
471
        CPPUNIT_ASSERT( temp->isPublic() == true );
472
    }
473

    
474
/* -------------------------------------------------------------------------- */
475
/* -------------------------------------------------------------------------- */
476

    
477
    void dump()
478
    {
479
        VMTemplatePool * tpool = static_cast<VMTemplatePool*>(pool);
480

    
481
        ostringstream   oss;
482
        int             rc;
483
        string          nan;
484

    
485
        allocate(0);
486
        allocate(1);
487
        allocate(2);
488

    
489
        rc = tpool->dump(oss,nan);
490
        CPPUNIT_ASSERT(rc == 0);
491

    
492
        string result = oss.str();
493

    
494
        result.replace(130, 10, replacement);
495
        result.replace(393, 10, replacement);
496
        result.replace(658, 10, replacement);
497

    
498
/*
499
        if( result != xml_dump )
500
        {
501
            cout << endl << result << endl << xml_dump << endl;
502
        }
503
//*/
504

    
505
        CPPUNIT_ASSERT( result == xml_dump );
506
    }
507

    
508
/* -------------------------------------------------------------------------- */
509
/* -------------------------------------------------------------------------- */
510

    
511
    void dump_where()
512
    {
513
        VMTemplatePool * tpool = static_cast<VMTemplatePool*>(pool);
514

    
515
        int             rc;
516
        ostringstream   oss;
517
        ostringstream   where;
518

    
519
        allocate(0);
520
        allocate(1);
521
        allocate(2);
522

    
523
        where << "uid < 2";
524

    
525
        rc = tpool->dump(oss, where.str());
526
        CPPUNIT_ASSERT(rc == 0);
527

    
528
        string result = oss.str();
529

    
530
        result.replace(130, 10, replacement);
531
        result.replace(393, 10, replacement);
532

    
533
/*
534
        if( result != xml_dump_where )
535
        {
536
            cout << endl << result << endl << xml_dump_where << endl;
537
        }
538
//*/
539

    
540
        CPPUNIT_ASSERT( result == xml_dump_where );
541
    }
542

    
543
    /* ********************************************************************* */
544

    
545
};
546

    
547
/* ************************************************************************* */
548
/* ************************************************************************* */
549

    
550
int main(int argc, char ** argv)
551
{
552
    return PoolTest::main(argc, argv, VMTemplatePoolTest::suite());
553
}