Statistics
| Branch: | Tag: | Revision:

one / src / vnm / VirtualNetwork.cc @ 9429b033

History | View | Annotate | Download (16.7 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

    
18
#include "VirtualNetwork.h"
19
#include "VirtualNetworkPool.h"
20
#include "VirtualNetworkTemplate.h"
21

    
22
#include "NebulaLog.h"
23
#include "RangedLeases.h"
24
#include "FixedLeases.h"
25

    
26
#include "AuthManager.h"
27
#include "UserPool.h"
28

    
29
/* ************************************************************************** */
30
/* Virtual Network :: Constructor/Destructor                                  */
31
/* ************************************************************************** */
32

    
33
VirtualNetwork::VirtualNetwork(int uid,
34
                               string _user_name,
35
                               VirtualNetworkTemplate *_vn_template):
36
                PoolObjectSQL(-1,"",uid,table),
37
                user_name(_user_name),
38
                bridge(""),
39
                type(UNINITIALIZED),
40
                leases(0)
41
{
42
    if (_vn_template != 0)
43
    {
44
        obj_template = _vn_template;
45
    }
46
    else
47
    {
48
        obj_template = new VirtualNetworkTemplate;
49
    }
50
};
51

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

    
55
VirtualNetwork::~VirtualNetwork()
56
{
57
    if (leases != 0)
58
    {
59
        delete leases;
60
    }
61

    
62
    if (obj_template != 0)
63
    {
64
        delete obj_template;
65
    }
66
}
67

    
68
/* ************************************************************************** */
69
/* Virtual Network :: Database Access Functions                               */
70
/* ************************************************************************** */
71

    
72
const char * VirtualNetwork::table        = "network_pool";
73

    
74
const char * VirtualNetwork::db_names     = "oid, name, body, uid, public";
75

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

    
80
/* -------------------------------------------------------------------------- */
81
/* -------------------------------------------------------------------------- */
82

    
83
int VirtualNetwork::select(SqlDB * db)
84
{
85
    int             rc;
86

    
87
    rc = PoolObjectSQL::select(db);
88

    
89
    if ( rc != 0 )
90
    {
91
        return rc;
92
    }
93

    
94
    return select_leases(db);
95
}
96

    
97
/* -------------------------------------------------------------------------- */
98

    
99
int VirtualNetwork::select(SqlDB * db, const string& name, int uid)
100
{
101
    int             rc;
102

    
103
    rc = PoolObjectSQL::select(db,name,uid);
104

    
105
    if ( rc != 0 )
106
    {
107
        return rc;
108
    }
109

    
110
    return select_leases(db);
111
}
112

    
113
/* -------------------------------------------------------------------------- */
114

    
115
int VirtualNetwork::select_leases(SqlDB * db)
116
{
117
    ostringstream   oss;
118
    ostringstream   ose;
119

    
120
    string          network_address;
121

    
122
    unsigned int default_size = VirtualNetworkPool::default_size();
123
    unsigned int mac_prefix   = VirtualNetworkPool::mac_prefix();
124

    
125
    //Get the leases
126
    if (type == RANGED)
127
    {
128
        string  nclass = "";
129
        int     size = 0;
130

    
131
        // retrieve specific information from the template
132
        get_template_attribute("NETWORK_ADDRESS",network_address);
133

    
134
        if (network_address.empty())
135
        {
136
            goto error_addr;
137
        }
138

    
139
        get_template_attribute("NETWORK_SIZE",nclass);
140

    
141
        if ( nclass == "B" || nclass == "b" )
142
        {
143
            size = 65534;
144
        }
145
        else if ( nclass == "C" || nclass == "c" )
146
        {
147
            size = 254;
148
        }
149
        else if (!nclass.empty()) //Assume it's a number
150
        {
151
            istringstream iss(nclass);
152
            iss >> size;
153
        }
154

    
155
        if (size == 0)
156
        {
157
            size = default_size;
158
        }
159

    
160
        leases = new RangedLeases(db,
161
                                  oid,
162
                                  size,
163
                                  mac_prefix,
164
                                  network_address);
165
    }
166
    else if(type == FIXED)
167
    {
168
        leases = new  FixedLeases(db,
169
                                  oid,
170
                                  mac_prefix);
171
    }
172
    else
173
    {
174
        goto error_type;
175
    }
176

    
177
    if (leases == 0)
178
    {
179
        goto error_leases;
180
    }
181

    
182
    return leases->select(db);
183

    
184

    
185
error_leases:
186
    ose << "Error getting Virtual Network leases nid: " << oid;
187
    goto error_common;
188

    
189
error_type:
190
    ose << "Wrong type of Virtual Network: " << type;
191
    goto error_common;
192

    
193
error_addr:
194
    ose << "Network address is not defined nid: " << oid;
195

    
196
error_common:
197
    NebulaLog::log("VNM", Log::ERROR, ose);
198
    return -1;
199
}
200

    
201
/* -------------------------------------------------------------------------- */
202
/* -------------------------------------------------------------------------- */
203

    
204
int VirtualNetwork::insert(SqlDB * db, string& error_str)
205
{
206
    ostringstream   ose;
207
    int             rc;
208

    
209
    string          pub;
210
    string          s_type;
211

    
212
    unsigned int default_size = VirtualNetworkPool::default_size();
213
    unsigned int mac_prefix   = VirtualNetworkPool::mac_prefix();
214

    
215
    //--------------------------------------------------------------------------
216
    // VirtualNetwork Attributes from the template
217
    //--------------------------------------------------------------------------
218

    
219
    // ------------ TYPE ----------------------
220
    get_template_attribute("TYPE",s_type);
221

    
222
    transform(s_type.begin(),s_type.end(),s_type.begin(),(int(*)(int))toupper);
223

    
224
    if (s_type == "RANGED")
225
    {
226
        type = VirtualNetwork::RANGED;
227
    }
228
    else if ( s_type == "FIXED")
229
    {
230
        type = VirtualNetwork::FIXED;
231
    }
232
    else if ( s_type.empty() )
233
    {
234
        goto error_type_defined;
235
    }
236
    else
237
    {
238
        goto error_wrong_type;
239
    }
240

    
241
    // ------------ NAME ----------------------
242

    
243
    get_template_attribute("NAME",name);
244

    
245
    if (name.empty())
246
    {
247
        goto error_name;
248
    }
249

    
250
    // ------------ BRIDGE --------------------
251

    
252
    get_template_attribute("BRIDGE",bridge);
253

    
254
    if (bridge.empty())
255
    {
256
        goto error_bridge;
257
    }
258

    
259
    // ------------ PUBLIC --------------------
260

    
261
    get_template_attribute("PUBLIC", pub);
262

    
263
    transform (pub.begin(), pub.end(), pub.begin(), (int(*)(int))toupper);
264

    
265
    public_vnet = (pub == "YES");
266

    
267
    obj_template->erase("PUBLIC");
268

    
269
    //--------------------------------------------------------------------------
270
    // Get the leases
271
    //--------------------------------------------------------------------------
272
    if (type == VirtualNetwork::RANGED)
273
    {
274
        string nclass = "";
275
        string naddr  = "";
276
        int    size   = 0;
277

    
278
        // retrieve specific information from template
279
        get_template_attribute("NETWORK_ADDRESS",naddr);
280

    
281
        if (naddr.empty())
282
        {
283
            goto error_addr;
284
        }
285

    
286
        get_template_attribute("NETWORK_SIZE",nclass);
287

    
288
        if ( nclass == "B" || nclass == "b"  )
289
        {
290
            size = 65534;
291
        }
292
        else if ( nclass == "C" || nclass == "c"  )
293
        {
294
            size = 254;
295
        }
296
        else if (!nclass.empty())//Assume its a number
297
        {
298
            istringstream iss(nclass);
299

    
300
            iss >> size;
301
        }
302

    
303
        if (size == 0)
304
        {
305
            SingleAttribute * attribute;
306
            ostringstream     oss;
307

    
308
            oss << default_size;
309

    
310
            attribute = new SingleAttribute("NETWORK_SIZE",oss.str());
311
            obj_template->set(attribute);
312

    
313
            size = default_size;
314
        }
315

    
316
        leases = new RangedLeases(db,
317
                                  oid,
318
                                  size,
319
                                  mac_prefix,
320
                                  naddr);
321
    }
322
    else // VirtualNetwork::FIXED
323
    {
324
        vector<const Attribute *>   vector_leases;
325

    
326
        get_template_attribute("LEASES",vector_leases);
327

    
328
        leases = new FixedLeases(db,
329
                                 oid,
330
                                 mac_prefix,
331
                                 vector_leases);
332
    }
333

    
334
    if (leases == 0)
335
    {
336
        goto error_null_leases;
337
    }
338

    
339
    //--------------------------------------------------------------------------
340
    // Insert the Virtual Network
341
    //--------------------------------------------------------------------------
342
    rc = insert_replace(db, false);
343

    
344
    if ( rc != 0 )
345
    {
346
        goto error_update;
347
    }
348

    
349
    return 0;
350

    
351
error_type_defined:
352
    ose << "No TYPE in template for Virtual Network.";
353
    goto error_common;
354

    
355
error_wrong_type:
356
    ose << "Wrong type \""<< s_type <<"\" in template for Virtual Network.";
357
    goto error_common;
358

    
359
error_name:
360
    ose << "No NAME in template for Virtual Network.";
361
    goto error_common;
362

    
363
error_bridge:
364
    ose << "No BRIDGE in template for Virtual Network.";
365
    goto error_common;
366

    
367
error_update:
368
    ose << "Can not update Virtual Network.";
369
    goto error_common;
370

    
371
error_addr:
372
    ose << "No NETWORK_ADDRESS in template for Virtual Network.";
373
    goto error_common;
374

    
375
error_null_leases:
376
    ose << "Error getting Virtual Network leases.";
377

    
378
error_common:
379
    error_str = ose.str();
380
    NebulaLog::log("VNM", Log::ERROR, ose);
381
    return -1;
382
}
383

    
384
/* -------------------------------------------------------------------------- */
385
/* -------------------------------------------------------------------------- */
386

    
387
int VirtualNetwork::insert_replace(SqlDB *db, bool replace)
388
{
389
    ostringstream   oss;
390
    int             rc;
391

    
392

    
393
    string xml_body;
394

    
395
    char * sql_name;
396
    char * sql_xml;
397

    
398

    
399
    sql_name = db->escape_str(name.c_str());
400

    
401
    if ( sql_name == 0 )
402
    {
403
        goto error_name;
404
    }
405

    
406
    sql_xml = db->escape_str(to_xml(xml_body).c_str());
407

    
408
    if ( sql_xml == 0 )
409
    {
410
        goto error_body;
411
    }
412

    
413
    // Construct the SQL statement to Insert or Replace
414
    if(replace)
415
    {
416
        oss << "REPLACE";
417
    }
418
    else
419
    {
420
        oss << "INSERT";
421
    }
422

    
423
    oss << " INTO " << table << " (" << db_names << ") VALUES ("
424
        <<          oid         << ","
425
        << "'" <<   sql_name    << "',"
426
        << "'" <<   sql_xml     << "',"
427
        <<          uid         << ","
428
        <<          public_vnet << ")";
429

    
430
    rc = db->exec(oss);
431

    
432
    db->free_str(sql_name);
433
    db->free_str(sql_xml);
434

    
435
    return rc;
436

    
437

    
438
error_body:
439
    db->free_str(sql_name);
440
error_name:
441
    return -1;
442
}
443

    
444
/* -------------------------------------------------------------------------- */
445
/* -------------------------------------------------------------------------- */
446

    
447
int VirtualNetwork::drop(SqlDB * db)
448
{
449
    int rc;
450

    
451
    rc = PoolObjectSQL::drop(db);
452

    
453
    if ( rc == 0 && leases != 0 )
454
    {
455
        rc += leases->drop(db);
456
    }
457

    
458
    return rc;
459
}
460

    
461
/* ************************************************************************** */
462
/* Virtual Network :: Misc                                                    */
463
/* ************************************************************************** */
464

    
465
ostream& operator<<(ostream& os, VirtualNetwork& vn)
466
{
467
    string vnet_xml;
468

    
469
    os << vn.to_xml_extended(vnet_xml,true);
470

    
471
    return os;
472
};
473

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

    
477
string& VirtualNetwork::to_xml(string& xml) const
478
{
479
    return to_xml_extended(xml,false);
480
}
481

    
482
/* -------------------------------------------------------------------------- */
483
/* -------------------------------------------------------------------------- */
484

    
485
string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const
486
{
487
    ostringstream os;
488

    
489
    string template_xml;
490
    string leases_xml;
491

    
492
    // Total leases is the number of used leases.
493
    int total_leases = 0;
494

    
495
    if (leases != 0)
496
    {
497
        total_leases = leases->n_used;
498
    }
499

    
500
    os <<
501
        "<VNET>" <<
502
            "<ID>"          << oid          << "</ID>"          <<
503
            "<UID>"         << uid          << "</UID>"         <<
504
            "<USERNAME>"    << user_name    << "</USERNAME>"    <<
505
            "<NAME>"        << name         << "</NAME>"        <<
506
            "<TYPE>"        << type         << "</TYPE>"        <<
507
            "<BRIDGE>"      << bridge       << "</BRIDGE>"      <<
508
            "<PUBLIC>"      << public_vnet  << "</PUBLIC>"      <<
509
            "<TOTAL_LEASES>"<< total_leases << "</TOTAL_LEASES>"<<
510
            obj_template->to_xml(template_xml);
511

    
512
    if (extended && leases != 0)
513
    {
514
        os << leases->to_xml(leases_xml);
515
    }
516

    
517
    os << "</VNET>";
518

    
519
    xml = os.str();
520

    
521
    return xml;
522
}
523

    
524
/* -------------------------------------------------------------------------- */
525
/* -------------------------------------------------------------------------- */
526

    
527
int VirtualNetwork::from_xml(const string &xml_str)
528
{
529
    vector<xmlNodePtr> content;
530

    
531
    int rc = 0;
532
    int int_type;
533

    
534
    // Initialize the internal XML object
535
    update_from_str(xml_str);
536

    
537
    // Get class base attributes
538
    rc += xpath(oid,        "/VNET/ID",         -1);
539
    rc += xpath(uid,        "/VNET/UID",        -1);
540
    rc += xpath(user_name,  "/VNET/USERNAME",   "not_found");
541
    rc += xpath(name,       "/VNET/NAME",       "not_found");
542
    rc += xpath(int_type,   "/VNET/TYPE",       -1);
543
    rc += xpath(bridge,     "/VNET/BRIDGE",     "not_found");
544
    rc += xpath(public_vnet,"/VNET/PUBLIC",     0);
545

    
546
    type = static_cast<NetworkType>( int_type );
547

    
548
    // Get associated classes
549
    ObjectXML::get_nodes("/VNET/TEMPLATE", content);
550

    
551
    if( content.size() < 1 )
552
    {
553
        return -1;
554
    }
555

    
556
    // Virtual Network template
557
    rc += obj_template->from_xml_node( content[0] );
558

    
559
    if (rc != 0)
560
    {
561
        return -1;
562
    }
563

    
564
    return 0;
565
}
566

    
567
/* -------------------------------------------------------------------------- */
568
/* -------------------------------------------------------------------------- */
569

    
570
int VirtualNetwork::nic_attribute(VectorAttribute *nic, int vid)
571
{
572
    int rc;
573

    
574
    string  ip;
575
    string  mac;
576

    
577
    ostringstream  vnid;
578

    
579
    ip      = nic->vector_value("IP");
580
    vnid   << oid;
581

    
582
    //--------------------------------------------------------------------------
583
    //                       GET NETWORK LEASE
584
    //--------------------------------------------------------------------------
585

    
586
    if (ip.empty())
587
    {
588
        rc = leases->get(vid,ip,mac);
589
    }
590
    else
591
    {
592
        rc = leases->set(vid,ip,mac);
593
    }
594

    
595
    if ( rc != 0 )
596
    {
597
        return -1;
598
    }
599

    
600
    //--------------------------------------------------------------------------
601
    //                       NEW NIC ATTRIBUTES
602
    //--------------------------------------------------------------------------
603

    
604
    nic->replace("NETWORK"   ,name);
605
    nic->replace("NETWORK_ID",vnid.str());
606
    nic->replace("BRIDGE"    ,bridge);
607
    nic->replace("MAC"       ,mac);
608
    nic->replace("IP"        ,ip);
609

    
610
    return 0;
611
}
612

    
613
/* -------------------------------------------------------------------------- */
614
/* -------------------------------------------------------------------------- */
615

    
616
int VirtualNetwork::add_leases(VirtualNetworkTemplate * leases_template,
617
                               string&                  error_msg)
618
{
619
    vector<const Attribute *> vector_leases;
620

    
621
    leases_template->get("LEASES", vector_leases);
622

    
623
    return leases->add_leases(vector_leases, error_msg);
624
}
625

    
626
/* -------------------------------------------------------------------------- */
627
/* -------------------------------------------------------------------------- */
628

    
629
int VirtualNetwork::remove_leases(VirtualNetworkTemplate * leases_template,
630
                                  string&                  error_msg)
631
{
632
    vector<const Attribute *> vector_leases;
633

    
634
    leases_template->get("LEASES", vector_leases);
635

    
636
    return leases->remove_leases(vector_leases, error_msg);
637
}
638

    
639
/* -------------------------------------------------------------------------- */
640
/* -------------------------------------------------------------------------- */