Statistics
| Branch: | Tag: | Revision:

one / src / vm / VirtualMachineDisk.cc @ 8576ae69

History | View | Annotate | Download (41.9 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2017, OpenNebula Project, OpenNebula Systems                */
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 "VirtualMachineDisk.h"
18
#include "NebulaUtil.h"
19
#include "Nebula.h"
20

    
21

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

    
25
bool VirtualMachineDisk::is_volatile() const
26
{
27
    std::string type = vector_value("TYPE");
28

    
29
    one_util::toupper(type);
30

    
31
    return ( type == "SWAP" || type == "FS");
32
}
33

    
34
/* -------------------------------------------------------------------------- */
35

    
36
string VirtualMachineDisk::get_tm_target() const
37
{
38
    bool   clone;
39
    std::string target;
40

    
41
    if (vector_value("CLONE", clone) != 0)
42
    {
43
        return "";
44
    }
45

    
46
    if (clone)
47
    {
48
        target = vector_value("CLONE_TARGET");
49
    }
50
    else
51
    {
52
        target = vector_value("LN_TARGET");
53
    }
54

    
55
    return one_util::toupper(target);
56
}
57

    
58
/* -------------------------------------------------------------------------- */
59

    
60
int VirtualMachineDisk::get_uid(int _uid)
61
{
62
    istringstream  is;
63

    
64
    string uid_s ;
65
    string uname;
66
    int    uid;
67

    
68
    if (!(uid_s = vector_value("IMAGE_UID")).empty())
69
    {
70
        is.str(uid_s);
71
        is >> uid;
72

    
73
        if( is.fail() )
74
        {
75
            return -1;
76
        }
77
    }
78
    else if (!(uname = vector_value("IMAGE_UNAME")).empty())
79
    {
80
        User *     user;
81
        Nebula&    nd    = Nebula::instance();
82
        UserPool * upool = nd.get_upool();
83

    
84
        user = upool->get(uname,true);
85

    
86
        if ( user == 0 )
87
        {
88
            return -1;
89
        }
90

    
91
        uid = user->get_oid();
92

    
93
        user->unlock();
94
    }
95
    else
96
    {
97
        uid = _uid;
98
    }
99

    
100
    return uid;
101
}
102

    
103
/* -------------------------------------------------------------------------- */
104

    
105
int VirtualMachineDisk::get_image_id(int &id, int uid)
106
{
107
    int    iid;
108
    string iname;
109

    
110
    if ( vector_value("IMAGE_ID", iid) == 0 )
111
    {
112
        id = iid;
113
        return 0;
114
    }
115
    else if ( vector_value("IMAGE", iname) == 0 )
116
    {
117
        ImagePool * ipool = Nebula::instance().get_ipool();
118
        int uiid = get_uid(uid);
119

    
120
        if ( uiid == -1)
121
        {
122
            return -1;
123
        }
124

    
125
        Image * image = ipool->get(iname, uiid, true);
126

    
127
        if ( image != 0 )
128
        {
129
            id = image->get_oid();
130

    
131
            image->unlock();
132
        }
133

    
134
        return 0;
135
    }
136

    
137
    return -1;
138
}
139

    
140
/* -------------------------------------------------------------------------- */
141
/* -------------------------------------------------------------------------- */
142

    
143
void VirtualMachineDisk::extended_info(int uid)
144
{
145
    ImagePool * ipool  = Nebula::instance().get_ipool();
146

    
147
    ipool->disk_attribute(this, get_id(), uid);
148
}
149

    
150
/* -------------------------------------------------------------------------- */
151
/* -------------------------------------------------------------------------- */
152

    
153
void VirtualMachineDisk::authorize(int uid, AuthRequest* ar)
154
{
155
    string  source;
156
    Image * img = 0;
157

    
158
    int iid;
159

    
160
    PoolObjectAuth perm;
161

    
162
    ImagePool * ipool = Nebula::instance().get_ipool();
163

    
164
    if ( vector_value("IMAGE", source) == 0 )
165
    {
166
        int uiid = get_uid(uid);
167

    
168
        if ( uiid == -1)
169
        {
170
            return;
171
        }
172

    
173
        img = ipool->get(source , uiid, true);
174

    
175
        if ( img != 0 )
176
        {
177
            replace("IMAGE_ID", img->get_oid());
178
        }
179
    }
180
    else if ( vector_value("IMAGE_ID", iid) == 0 )
181
    {
182
        img = ipool->get(iid, true);
183
    }
184

    
185
    if (img == 0)
186
    {
187
        return;
188
    }
189

    
190
    img->get_permissions(perm);
191

    
192
    img->unlock();
193

    
194
    ar->add_auth(AuthRequest::USE, perm);
195
}
196

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

    
200
int VirtualMachineDisk::create_snapshot(const string& name, string& error)
201
{
202
    long long size_mb, snap_size;
203
    int snap_id;
204

    
205
    bool ro;
206

    
207
    if (is_volatile())
208
    {
209
        error = "Cannot make snapshots on volatile disks";
210
        return -1;
211
    }
212

    
213
    if ( vector_value("SIZE", size_mb) != 0 )
214
    {
215
        error = "Wrong size in disk";
216
        return -1;
217
    }
218

    
219
    if ((vector_value("READONLY", ro) == 0) && ro == true )
220
    {
221
        error = "Cannot make snapshots on readonly disks";
222
        return -1;
223
    }
224

    
225
    if ( snapshots == 0 )
226
    {
227
        snapshots = new Snapshots(get_id(), allow_orphans());
228

    
229
        snap_id   = snapshots->create_snapshot(name, size_mb);
230
        snap_size = size_mb;
231

    
232
        if (snap_id == -1)
233
        {
234
            snapshots = 0;
235
            delete snapshots;
236
        }
237
    }
238
    else
239
    {
240
        snap_id   = snapshots->create_snapshot(name, size_mb);
241
        snap_size = snapshots->get_total_size();
242
    }
243

    
244
    if (snap_id != -1)
245
    {
246
        replace("DISK_SNAPSHOT_ACTIVE", "YES");
247
        replace("DISK_SNAPSHOT_ID", snap_id);
248
        replace("DISK_SNAPSHOT_TOTAL_SIZE", snap_size);
249
    }
250

    
251
    return snap_id;
252
}
253

    
254
/* -------------------------------------------------------------------------- */
255
/* -------------------------------------------------------------------------- */
256

    
257
int VirtualMachineDisk::revert_snapshot(int snap_id)
258
{
259
    if ( snapshots == 0 )
260
    {
261
        return -1;
262
    }
263

    
264
    return snapshots->active_snapshot(snap_id);
265
}
266

    
267
/* -------------------------------------------------------------------------- */
268
/* -------------------------------------------------------------------------- */
269
//  +--------+-------------------------------------+
270
//  |LN/CLONE|     PERSISTENT    |   NO PERSISTENT |
271
//  |        |---------+---------+-----------------+
272
//  | TARGET | created |  quota  | created | quota |
273
//  +--------+---------+---------+-----------------+
274
//  | SYSTEM | system  | VM + DS | system  | VM    |
275
//  | SELF   | image   | DS      | image   | DS    |
276
//  | NONE   | image   | DS      | image   | DS    |
277
//  +----------------------------------------------+
278
/* -------------------------------------------------------------------------- */
279

    
280
void VirtualMachineDisk::delete_snapshot(int snap_id, Template **ds_quotas,
281
        Template **vm_quotas, bool& img_owner, bool& vm_owner)
282
{
283
    vm_owner  = false;
284
    img_owner = false;
285

    
286
    if ( snapshots == 0 )
287
    {
288
        return;
289
    }
290

    
291
    long long ssize = snapshots->get_snapshot_size(snap_id);
292

    
293
    snapshots->delete_snapshot(snap_id);
294

    
295
    long long snap_size = snapshots->get_total_size();
296

    
297
    replace("DISK_SNAPSHOT_TOTAL_SIZE", snap_size);
298

    
299
    if (snapshots->size() == 0)
300
    {
301
        delete snapshots;
302

    
303
        snapshots = 0;
304
    }
305

    
306
    string tm_target = get_tm_target();
307

    
308
    vm_owner  = tm_target == "SELF";
309
    img_owner = is_persistent() || tm_target == "NONE";
310

    
311
        if ( img_owner || vm_owner )
312
        {
313
        *ds_quotas = new Template();
314

    
315
        (*ds_quotas)->add("DATASTORE", vector_value("DATASTORE_ID"));
316
        (*ds_quotas)->add("SIZE", ssize);
317
        (*ds_quotas)->add("IMAGES",0 );
318
        }
319

    
320
    if (tm_target == "SYSTEM")
321
    {
322
        *vm_quotas = new Template();
323

    
324
        VectorAttribute * delta_disk = new VectorAttribute("DISK");
325
        delta_disk->replace("TYPE", "FS");
326
        delta_disk->replace("SIZE", ssize);
327

    
328
        (*vm_quotas)->add("VMS", 0);
329
        (*vm_quotas)->set(delta_disk);
330
    }
331
}
332

    
333
/* -------------------------------------------------------------------------- */
334
/* -------------------------------------------------------------------------- */
335

    
336
long long VirtualMachineDisk::system_ds_size()
337
{
338
        long long disk_sz, snapshot_sz = 0;
339

    
340
        if ( vector_value("SIZE", disk_sz) != 0 )
341
        {
342
                return 0;
343
        }
344

    
345
        //Volatile disks don't have snapshots
346
        if (vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_sz) == 0)
347
        {
348
                disk_sz += snapshot_sz;
349
        }
350

    
351
        if ( is_volatile() || get_tm_target() == "SYSTEM" )
352
        {
353
                return disk_sz;
354
        }
355

    
356
        return 0;
357
}
358

    
359
/* -------------------------------------------------------------------------- */
360
/* -------------------------------------------------------------------------- */
361

    
362
long long VirtualMachineDisk::image_ds_size()
363
{
364
        long long disk_sz, snapshot_sz = 0;
365

    
366
    string tm_target = get_tm_target();
367

    
368
    if (  get_tm_target() != "SELF" )
369
    {
370
        return 0;
371
    }
372

    
373
        if ( vector_value("SIZE", disk_sz) != 0 )
374
        {
375
                return 0;
376
        }
377

    
378
        if ( vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_sz) == 0 )
379
        {
380
                disk_sz += snapshot_sz;
381
        }
382

    
383
    return disk_sz;
384
}
385

    
386
/* -------------------------------------------------------------------------- */
387
/* -------------------------------------------------------------------------- */
388

    
389
/* -------------------------------------------------------------------------- */
390
//  Owner to update ds usage quotas
391
//
392
//  +--------+-------------------------------------+
393
//  |LN/CLONE|     PERSISTENT    |   NO PERSISTENT |
394
//  |        |---------+---------+-----------------+
395
//  | TARGET | created |  quota  | created | quota |
396
//  +--------+---------+---------+-----------------+
397
//  | SYSTEM | system  | IMG     | system  | -     |
398
//  | SELF   | image   | IMG+VM  | image   | VM    |
399
//  | NONE   | image   | IMG     | image   | IMG   |
400
//  +----------------------------------------------+
401
/* -------------------------------------------------------------------------- */
402
void VirtualMachineDisk::resize_quotas(long long new_size, Template& ds_deltas,
403
        Template& vm_deltas, bool& do_img_owner, bool& do_vm_owner)
404
{
405
    long long current_size, delta_size;
406

    
407
    do_vm_owner = false;
408
    do_img_owner= false;
409

    
410
        if ( vector_value("SIZE", current_size) != 0 )
411
    {
412
        return;
413
    }
414

    
415
    delta_size = new_size - current_size;
416

    
417
    //Quotas uses del operation to substract counters, delta needs to be > 0
418
    if ( delta_size < 0 )
419
    {
420
        delta_size = - delta_size;
421
    }
422

    
423
    string tm       = get_tm_target();
424
    do_vm_owner     = !is_volatile() && tm == "SELF";
425
    do_img_owner    = !is_volatile() && (is_persistent() || tm == "NONE");
426
    bool is_system  = tm == "SYSTEM";
427
    string ds_id    = vector_value("DATASTORE_ID");
428

    
429
    if ( do_vm_owner || do_img_owner )
430
    {
431
        ds_deltas.add("DATASTORE", ds_id);
432
        ds_deltas.add("SIZE", delta_size);
433
        ds_deltas.add("IMAGES", 0);
434
    }
435

    
436
    if ( is_volatile() || is_system )
437
    {
438
        VectorAttribute * delta_disk = new VectorAttribute("DISK");
439
        delta_disk->replace("TYPE", "FS");
440
        delta_disk->replace("SIZE", delta_size);
441

    
442
        vm_deltas.add("VMS", 0);
443
        vm_deltas.set(delta_disk);
444
    }
445
}
446

    
447
/* -------------------------------------------------------------------------- */
448
/* -------------------------------------------------------------------------- */
449

    
450
void VirtualMachineDisk::datastore_sizes(int& ds_id, long long& image_sz,
451
        long long& system_sz)
452
{
453
        long long tmp_size, snapshot_size;
454

    
455
        image_sz  = 0;
456
        system_sz = 0;
457
        ds_id     = -1;
458

    
459
        if ( vector_value("SIZE", tmp_size) != 0 )
460
        {
461
                return;
462
        }
463

    
464
        if ( vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_size) == 0 )
465
        {
466
                tmp_size += snapshot_size;
467
        }
468

    
469
        if ( is_volatile() )
470
        {
471
                system_sz = tmp_size;
472
                return;
473
        }
474
        else
475
        {
476
                string target = get_tm_target();
477

    
478
                if ( target  == "SYSTEM" )
479
                {
480
                        system_sz = tmp_size;
481
                }
482
                else if ( target == "SELF" )
483
                {
484
            vector_value("DATASTORE_ID", ds_id);
485

    
486
                        image_sz = tmp_size;
487
                }// else if ( target == "NONE" )
488
        }
489
}
490

    
491
/* -------------------------------------------------------------------------- */
492
/* -------------------------------------------------------------------------- */
493

    
494
void VirtualMachineDisk::clear_resize(bool restore)
495
{
496
    string size, size_prev;
497

    
498
    if ( restore && vector_value("SIZE_PREV", size_prev) == 0 )
499
    {
500
        replace("SIZE", size_prev);
501
    }
502

    
503
    remove("SIZE_PREV");
504
    clear_resize();
505
}
506

    
507
/* -------------------------------------------------------------------------- */
508
/* -------------------------------------------------------------------------- */
509
/* -------------------------------------------------------------------------- */
510
/* -------------------------------------------------------------------------- */
511
/* -------------------------------------------------------------------------- */
512
/* VIRTUALMACHINEDISKS                                                        */
513
/* -------------------------------------------------------------------------- */
514
/* -------------------------------------------------------------------------- */
515
/* -------------------------------------------------------------------------- */
516
/* -------------------------------------------------------------------------- */
517
/* -------------------------------------------------------------------------- */
518

    
519
const char * VirtualMachineDisks::DISK_NAME = "DISK";
520

    
521
const char * VirtualMachineDisks::DISK_ID_NAME = "DISK_ID";
522

    
523
/* -------------------------------------------------------------------------- */
524
/* -------------------------------------------------------------------------- */
525

    
526
long long VirtualMachineDisks::system_ds_size()
527
{
528
    long long size = 0;
529

    
530
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
531
    {
532
                size += (*disk)->system_ds_size();
533
    }
534

    
535
    return size;
536
}
537

    
538
long long VirtualMachineDisks::system_ds_size(Template * ds_tmpl)
539
{
540
    VirtualMachineDisks disks(ds_tmpl, false);
541

    
542
    return disks.system_ds_size();
543
}
544

    
545

    
546
/* -------------------------------------------------------------------------- */
547
/* -------------------------------------------------------------------------- */
548

    
549
void VirtualMachineDisks::image_ds_quotas(Template * tmpl,
550
        vector<Template *>& ds_quotas)
551
{
552
    VirtualMachineDisks disks(tmpl, false);
553

    
554
    for (disk_iterator it = disks.begin(); it != disks.end() ; ++it)
555
    {
556
        long long ds_size = (*it)->image_ds_size();
557

    
558
        if ( ds_size != 0 )
559
        {
560
            Template * d_ds = new Template();
561

    
562
            d_ds->add("DATASTORE", (*it)->vector_value("DATASTORE_ID"));
563
            d_ds->add("SIZE", ds_size);
564
            d_ds->add("IMAGES", 0);
565

    
566
            ds_quotas.push_back(d_ds);
567
        }
568
    }
569
}
570

    
571
/* -------------------------------------------------------------------------- */
572
/* -------------------------------------------------------------------------- */
573

    
574
void VirtualMachineDisks::extended_info(int uid)
575
{
576
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
577
    {
578
        (*disk)->extended_info(uid);
579
    }
580
}
581

    
582
void VirtualMachineDisks::extended_info(int uid, Template * tmpl)
583
{
584
    VirtualMachineDisks disks(tmpl, false);
585

    
586
    return disks.extended_info(uid);
587
}
588

    
589
/* -------------------------------------------------------------------------- */
590
/* -------------------------------------------------------------------------- */
591

    
592
bool VirtualMachineDisks::volatile_info(int ds_id)
593
{
594
    DatastorePool * ds_pool = Nebula::instance().get_dspool();
595

    
596
    bool found = false;
597

    
598
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
599
    {
600
        if ( !(*disk)->is_volatile() )
601
        {
602
            continue;
603
        }
604

    
605
        ds_pool->disk_attribute(ds_id, *disk);
606

    
607
        found = true;
608
    }
609

    
610
    return found;
611
}
612

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

    
616
void VirtualMachineDisks::get_image_ids(set<int>& ids, int uid)
617
{
618
    int id;
619

    
620
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
621
    {
622
        if ( (*disk)->get_image_id(id, uid) == 0 )
623
        {
624
            ids.insert(id);
625
        }
626
    }
627
}
628

    
629
/* -------------------------------------------------------------------------- */
630
/* -------------------------------------------------------------------------- */
631

    
632
void VirtualMachineDisks::assign_disk_targets(
633
        std::queue<pair <string, VirtualMachineDisk *> >& dqueue,
634
        std::set<string>& used_targets)
635

    
636
{
637
    int    index = 0;
638
    string target;
639

    
640
    pair <string, VirtualMachineDisk *> disk_pair;
641

    
642
    while (dqueue.size() > 0 )
643
    {
644
        disk_pair = dqueue.front();
645
        index     = 0;
646

    
647
        do
648
        {
649
            target = disk_pair.first + static_cast<char>(('a'+ index));
650
            index++;
651
        }
652
        while ( used_targets.count(target) > 0 && index < 26 );
653

    
654
        disk_pair.second->replace("TARGET", target);
655

    
656
        used_targets.insert(target);
657

    
658
        dqueue.pop();
659
    }
660
}
661

    
662
/* -------------------------------------------------------------------------- */
663
/* -------------------------------------------------------------------------- */
664

    
665
int VirtualMachineDisks::get_images(int vm_id, int uid,
666
        vector<Attribute *> disks, VectorAttribute * vcontext,
667
        std::string& error_str)
668
{
669
    Nebula&    nd    = Nebula::instance();
670
    ImagePool* ipool = nd.get_ipool();
671

    
672
    vector<Attribute*>::iterator it;
673

    
674
    int         disk_id, image_id;
675
    std::string dev_prefix, target;
676

    
677
    Image::ImageType image_type;
678

    
679
    std::vector<int>      acquired_images;
680
    std::set<std::string> used_targets;
681

    
682
    std::queue<pair <std::string, VirtualMachineDisk *> > os_disk;
683
    std::queue<pair <std::string, VirtualMachineDisk *> > cdrom_disks;
684
    std::queue<pair <std::string, VirtualMachineDisk *> > datablock_disks;
685

    
686
    std::ostringstream oss;
687

    
688
    for(it = disks.begin(), disk_id = 0; it != disks.end(); ++it, ++disk_id)
689
    {
690
        Snapshots*       snapshots;
691
        VectorAttribute* vdisk = static_cast<VectorAttribute * >(*it);
692

    
693
        // ---------------------------------------------------------------------
694
        // Initialize DISK attribute information and acquire associated IMAGE
695
        // ---------------------------------------------------------------------
696
        VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, disk_id);
697

    
698
        if ( ipool->acquire_disk(vm_id, disk, disk_id, image_type, dev_prefix,
699
                uid, image_id, &snapshots, error_str) != 0 )
700
        {
701
            oss << "DISK " << disk_id << ": " << error_str;
702
            error_str = oss.str();
703

    
704
            goto error_common;
705
        }
706

    
707
        add_attribute(disk, disk_id);
708

    
709
        if (snapshots != 0)
710
        {
711
            if (image_type == Image::OS || image_type == Image::DATABLOCK)
712
            {
713
                disk->set_snapshots(snapshots);
714
            }
715
            else
716
            {
717
                delete snapshots;
718
            }
719
        }
720

    
721
        acquired_images.push_back(image_id);
722

    
723
        // ---------------------------------------------------------------------
724
        // Check TARGET and add disk to target assigment queue
725
        // ---------------------------------------------------------------------
726
        target = disk->vector_value("TARGET");
727

    
728
        if ( !target.empty() )
729
        {
730
            if (  used_targets.insert(target).second == false )
731
            {
732
                goto error_duplicated_target;
733
            }
734
        }
735
        else
736
        {
737
            switch(image_type)
738
            {
739
                case Image::OS:
740
                    if (os_disk.empty())//First OS disk gets the first device(a)
741
                    {
742
                        os_disk.push(make_pair(dev_prefix, disk));
743
                    }
744
                    else
745
                    {
746
                        datablock_disks.push(make_pair(dev_prefix, disk));
747
                    }
748
                    break;
749

    
750
                case Image::CDROM:
751
                    cdrom_disks.push(make_pair(dev_prefix, disk));
752
                    break;
753

    
754
                case Image::DATABLOCK:
755
                    datablock_disks.push(make_pair(dev_prefix, disk));
756
                    break;
757

    
758
                default:
759
                    break;
760
            }
761
        }
762
    }
763

    
764
    // -------------------------------------------------------------------------
765
    // Targets for OS Disks
766
    // -------------------------------------------------------------------------
767
    assign_disk_targets(os_disk, used_targets);
768

    
769
    // -------------------------------------------------------------------------
770
    // Target for CDROMs and Context disk (the last of the cdroms)
771
    // -------------------------------------------------------------------------
772
    if ( vcontext != 0 )
773
    {
774
        VirtualMachineDisk context(vcontext, disk_id);
775

    
776
        target = context.vector_value("TARGET");
777

    
778
        if ( !target.empty() )
779
        {
780
            if (  used_targets.insert(target).second == false )
781
            {
782
                goto error_duplicated_target;
783
            }
784
        }
785
        else
786
        {
787
            dev_prefix = context.vector_value("DEV_PREFIX");
788

    
789
            if (dev_prefix.empty())
790
            {
791
                dev_prefix = ipool->default_cdrom_dev_prefix();
792
            }
793

    
794
            cdrom_disks.push(make_pair(dev_prefix, &context));
795
        }
796

    
797
        // Disk IDs are 0..num-1, context disk is num
798
        vcontext->replace("DISK_ID", disk_id);
799

    
800
        assign_disk_targets(cdrom_disks, used_targets);
801
    }
802
    else
803
    {
804
        assign_disk_targets(cdrom_disks, used_targets);
805
    }
806

    
807
    // -------------------------------------------------------------------------
808
    // Targets for DATABLOCK Disks
809
    // -------------------------------------------------------------------------
810
    assign_disk_targets(datablock_disks, used_targets);
811

    
812
    return 0;
813

    
814
error_duplicated_target:
815
    oss << "Two disks have defined the same target " << target;
816
    error_str = oss.str();
817

    
818
error_common:
819
    ImageManager *  imagem = nd.get_imagem();
820

    
821
    for ( std::vector<int>::iterator img_it = acquired_images.begin() ;
822
            img_it != acquired_images.end(); ++img_it )
823
    {
824
        imagem->release_image(vm_id, *img_it, false);
825
    }
826

    
827
    return -1;
828
}
829

    
830
/* -------------------------------------------------------------------------- */
831
/* -------------------------------------------------------------------------- */
832

    
833
void VirtualMachineDisks::release_images(int vmid, bool image_error,
834
        vector<Template *>& ds_quotas)
835
{
836
    Nebula& nd = Nebula::instance();
837
    ImageManager * imagem = nd.get_imagem();
838

    
839
    for (disk_iterator it = begin(); it != end() ; ++it)
840
    {
841
        int iid;
842

    
843
        if ( (*it)->vector_value("IMAGE_ID", iid) == 0 )
844
        {
845
            long long original_size, size;
846

    
847
            int rc;
848

    
849
            /* ---------- Update size on source image if needed ------------- */
850
            rc  = (*it)->vector_value("SIZE", size);
851
            rc += (*it)->vector_value("ORIGINAL_SIZE", original_size);
852

    
853
            if ( size > original_size )
854
            {
855
                imagem->set_image_size(iid, size);
856
            }
857

    
858
            /* ------- Update snapshots on source image if needed ----------- */
859
            if ( (*it)->has_snapshots() )
860
            {
861
                imagem->set_image_snapshots(iid, *(*it)->get_snapshots());
862
            }
863

    
864
            /* --------- Compute space to free on image datastore ----------- */
865
            if ( (*it)->get_tm_target() == "SELF" )
866
            {
867
                long long delta_size = size + (*it)->get_total_snapshot_size();
868

    
869
                Template * d_ds = new Template();
870

    
871
                d_ds->add("DATASTORE", (*it)->vector_value("DATASTORE_ID"));
872
                d_ds->add("SIZE", delta_size);
873
                d_ds->add("IMAGES", 0);
874

    
875
                ds_quotas.push_back(d_ds);
876
            }
877

    
878
            imagem->release_image(vmid, iid, image_error);
879
        }
880
    }
881
}
882

    
883
/* -------------------------------------------------------------------------- */
884
/* -------------------------------------------------------------------------- */
885
/* DISK cloning functions                                                     */
886
/* -------------------------------------------------------------------------- */
887
/* -------------------------------------------------------------------------- */
888

    
889
bool VirtualMachineDisks::has_cloning()
890
{
891
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
892
    {
893
        if ( (*disk)->is_cloning() )
894
        {
895
            return true;
896
        }
897
    }
898

    
899
    return false;
900
}
901

    
902
/* -------------------------------------------------------------------------- */
903
/* -------------------------------------------------------------------------- */
904

    
905
void VirtualMachineDisks::get_cloning_image_ids(std::set<int>& ids)
906
{
907
    int image_id;
908

    
909
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
910
    {
911
        if ( (*disk)->is_cloning() &&
912
                ((*disk)->vector_value("IMAGE_ID", image_id) == 0) )
913
        {
914
            ids.insert(image_id);
915
        }
916
    }
917
}
918

    
919
/* -------------------------------------------------------------------------- */
920
/* -------------------------------------------------------------------------- */
921

    
922
void VirtualMachineDisks::clear_cloning_image_id(int iid, const string& source)
923
{
924
    int image_id;
925

    
926
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
927
    {
928
        if (((*disk)->vector_value("IMAGE_ID", image_id)== 0) && image_id == iid)
929
        {
930
            (*disk)->clear_cloning();
931
            (*disk)->replace("SOURCE", source);
932

    
933
            break;
934
        }
935
    }
936
}
937

    
938
/* -------------------------------------------------------------------------- */
939
/* -------------------------------------------------------------------------- */
940
/* ATTACH DISK INTERFACE                                                      */
941
/* -------------------------------------------------------------------------- */
942
/* -------------------------------------------------------------------------- */
943

    
944
int VirtualMachineDisks::set_attach(int id)
945
{
946
    VirtualMachineDisk * disk = get_disk(id);
947

    
948
    if ( disk == 0 )
949
    {
950
        return -1;
951
    }
952

    
953
    disk->set_attach();
954

    
955
    return 0;
956
}
957

    
958
/* -------------------------------------------------------------------------- */
959
/* -------------------------------------------------------------------------- */
960

    
961
VirtualMachineDisk * VirtualMachineDisks::set_up_attach(int vmid, int uid,
962
        int cluster_id, VectorAttribute * vdisk, VectorAttribute * vcontext,
963
        string& error)
964
{
965
    set<string> used_targets;
966
    int         max_disk_id = -1;
967

    
968
    // -------------------------------------------------------------------------
969
    // Get the list of used targets and max_disk_id
970
    // -------------------------------------------------------------------------
971
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
972
    {
973
        string target = (*disk)->vector_value("TARGET");
974

    
975
        if ( !target.empty() )
976
        {
977
            used_targets.insert(target);
978
        }
979

    
980
        int disk_id = (*disk)->get_disk_id();
981

    
982
        if ( disk_id > max_disk_id )
983
        {
984
            max_disk_id = disk_id;
985
        }
986
    }
987

    
988
    if ( vcontext != 0 )
989
    {
990
        string target = vcontext->vector_value("TARGET");
991

    
992
        if ( !target.empty() )
993
        {
994
            used_targets.insert(target);
995
        }
996

    
997
        int disk_id;
998

    
999
        vcontext->vector_value("DISK_ID", disk_id);
1000

    
1001
        if ( disk_id > max_disk_id )
1002
        {
1003
            max_disk_id = disk_id;
1004
        }
1005
    }
1006

    
1007
    // -------------------------------------------------------------------------
1008
    // Acquire the new disk image
1009
    // -------------------------------------------------------------------------
1010
    Nebula&       nd     = Nebula::instance();
1011
    ImagePool *   ipool  = nd.get_ipool();
1012
    ImageManager* imagem = nd.get_imagem();
1013

    
1014
    Snapshots * snap = 0;
1015

    
1016
    string           dev_prefix;
1017
    Image::ImageType img_type;
1018

    
1019
    int image_id;
1020

    
1021
    VirtualMachineDisk * disk = new VirtualMachineDisk(vdisk, max_disk_id + 1);
1022

    
1023
    int rc = ipool->acquire_disk(vmid, disk, max_disk_id + 1, img_type,
1024
                         dev_prefix, uid, image_id, &snap, error);
1025
    if ( rc != 0 )
1026
    {
1027
        return 0;
1028
    }
1029

    
1030
    disk->set_snapshots(snap);
1031

    
1032
    string target = disk->vector_value("TARGET");
1033

    
1034
    if ( !target.empty() )
1035
    {
1036
        if (  used_targets.insert(target).second == false )
1037
        {
1038
            error = "Target " + target + " is already in use.";
1039

    
1040
            imagem->release_image(vmid, image_id, false);
1041

    
1042
            delete disk;
1043
            return 0;
1044
        }
1045
    }
1046
    else
1047
    {
1048
        queue<pair <string, VirtualMachineDisk *> > disks_queue;
1049

    
1050
        disks_queue.push(make_pair(dev_prefix, disk));
1051

    
1052
        assign_disk_targets(disks_queue, used_targets);
1053
    }
1054

    
1055
    // -------------------------------------------------------------------------
1056
    // Check that we don't have a cluster incompatibility.
1057
    // -------------------------------------------------------------------------
1058
    string disk_cluster_ids = disk->vector_value("CLUSTER_ID");
1059

    
1060
    if ( !disk_cluster_ids.empty() )
1061
    {
1062
        set<int> cluster_ids;
1063
        one_util::split_unique(disk_cluster_ids, ',', cluster_ids);
1064

    
1065
        if (cluster_ids.count(cluster_id) == 0)
1066
        {
1067
            ostringstream oss;
1068

    
1069
            oss << "Image [" << image_id << "] is not part of cluster ["
1070
                << cluster_id << "]";
1071

    
1072
            error = oss.str();
1073

    
1074
            imagem->release_image(vmid, image_id, false);
1075

    
1076
            delete disk;
1077
            return 0;
1078
        }
1079
    }
1080

    
1081
    // -------------------------------------------------------------------------
1082
    // Add disk to the set
1083
    // -------------------------------------------------------------------------
1084

    
1085
    disk->set_attach();
1086

    
1087
    add_attribute(disk, disk->get_disk_id());
1088

    
1089
    return disk;
1090
}
1091

    
1092
/* -------------------------------------------------------------------------- */
1093
/* -------------------------------------------------------------------------- */
1094
/* RESIZE DISK INTERFACE                                                      */
1095
/* -------------------------------------------------------------------------- */
1096
/* -------------------------------------------------------------------------- */
1097

    
1098
int VirtualMachineDisks::set_resize(int id)
1099
{
1100
    VirtualMachineDisk * disk = get_disk(id);
1101

    
1102
    if ( disk == 0 )
1103
    {
1104
        return -1;
1105
    }
1106

    
1107
    disk->set_resize();
1108

    
1109
    return 0;
1110
}
1111

    
1112
/* -------------------------------------------------------------------------- */
1113

    
1114
int VirtualMachineDisks::set_up_resize(int disk_id, long size, string& err)
1115
{
1116
    VirtualMachineDisk * disk = get_disk(disk_id);
1117
    long size_prev;
1118

    
1119
    if ( disk == 0 )
1120
    {
1121
        err = "Disk not found";
1122
        return -1;
1123
    }
1124

    
1125
    if ( disk->vector_value("SIZE", size_prev) != 0 )
1126
    {
1127
        err = "Wrong format for disk SIZE";
1128
        return -1;
1129
    }
1130

    
1131
    if ( size <= size_prev )
1132
    {
1133
        err = "New size has to be bigger than current one";
1134
        return -1;
1135
    }
1136

    
1137
    disk->replace("SIZE_PREV", size_prev);
1138

    
1139
    disk->replace("SIZE", size);
1140

    
1141
    disk->set_resize();
1142

    
1143
    return 0;
1144
}
1145

    
1146
/* -------------------------------------------------------------------------- */
1147
/* -------------------------------------------------------------------------- */
1148
/* SNAPSHOT INTERFACE                                                         */
1149
/* -------------------------------------------------------------------------- */
1150
/* -------------------------------------------------------------------------- */
1151

    
1152
void VirtualMachineDisks::set_snapshots(int id, Snapshots * snapshots)
1153
{
1154
    VirtualMachineDisk * disk = get_disk(id);
1155

    
1156
    if ( disk != 0 )
1157
    {
1158
        disk->set_snapshots(snapshots);
1159
    }
1160
}
1161

    
1162
/* -------------------------------------------------------------------------- */
1163

    
1164
int VirtualMachineDisks::set_active_snapshot(int id, int snap_id)
1165
{
1166
    VirtualMachineDisk * disk = get_disk(id);
1167

    
1168
    if ( disk == 0 )
1169
    {
1170
        return -1;
1171
    }
1172

    
1173
    disk->set_active_snapshot();
1174
    disk->replace("DISK_SNAPSHOT_ID", snap_id);
1175

    
1176
    return 0;
1177
}
1178

    
1179
/* -------------------------------------------------------------------------- */
1180

    
1181
void VirtualMachineDisks::clear_active_snapshot()
1182
{
1183
    VirtualMachineDisk * disk = get_active_snapshot();
1184

    
1185
    if ( disk != 0 )
1186
    {
1187
        disk->clear_active_snapshot();
1188
        disk->remove("DISK_SNAPSHOT_ID");
1189
    }
1190
}
1191

    
1192
/* -------------------------------------------------------------------------- */
1193
/* -------------------------------------------------------------------------- */
1194

    
1195
int VirtualMachineDisks::get_active_snapshot(int& ds_id, string& tm_mad,
1196
        int& disk_id, int& snap_id)
1197
{
1198
    int rc;
1199
    VirtualMachineDisk * disk =
1200
        static_cast<VirtualMachineDisk *>(get_attribute("DISK_SNAPSHOT_ACTIVE"));
1201

    
1202
    if ( disk == 0 )
1203
    {
1204
        return -1;
1205
    }
1206

    
1207
    if ( !disk->has_snapshots() )
1208
    {
1209
        return -1;
1210
    }
1211

    
1212
    tm_mad  = disk->vector_value("TM_MAD");
1213
    disk_id = disk->get_disk_id();
1214

    
1215
    rc = disk->vector_value("DATASTORE_ID", ds_id);
1216
    rc += disk->vector_value("DISK_SNAPSHOT_ID", snap_id);
1217

    
1218
    if ( rc != 0 || tm_mad.empty() )
1219
    {
1220
        return -1;
1221
    }
1222

    
1223
    return 0;
1224
}
1225

    
1226
/* -------------------------------------------------------------------------- */
1227
/* -------------------------------------------------------------------------- */
1228

    
1229
int VirtualMachineDisks::create_snapshot(int disk_id, const string& name,
1230
        string& error)
1231
{
1232
    VirtualMachineDisk * disk =
1233
        static_cast<VirtualMachineDisk *>(get_attribute(disk_id));
1234

    
1235
    if ( disk == 0 )
1236
    {
1237
        error = "VM disk does not exist";
1238
        return -1;
1239
    }
1240

    
1241
    return disk->create_snapshot(name, error);
1242
}
1243

    
1244
/* -------------------------------------------------------------------------- */
1245
/* -------------------------------------------------------------------------- */
1246

    
1247
const Snapshots * VirtualMachineDisks::get_snapshots(int id, string& error) const
1248
{
1249
    VirtualMachineDisk * disk =
1250
        static_cast<VirtualMachineDisk *>(get_attribute(id));
1251

    
1252
    if ( disk == 0 )
1253
    {
1254
        error = "VM disk does not exist";
1255
        return 0;
1256
    }
1257

    
1258
    const Snapshots * snapshots = disk->get_snapshots();
1259

    
1260
    if ( snapshots == 0 )
1261
    {
1262
        error = "Snapshot does not exist";
1263
    }
1264

    
1265
    return snapshots;
1266
}
1267

    
1268
/* -------------------------------------------------------------------------- */
1269
/* -------------------------------------------------------------------------- */
1270

    
1271
int VirtualMachineDisks::revert_snapshot(int id, int snap_id)
1272
{
1273
    VirtualMachineDisk * disk =
1274
        static_cast<VirtualMachineDisk *>(get_attribute(id));
1275

    
1276
    if ( disk == 0 )
1277
    {
1278
        return -1;
1279
    }
1280

    
1281
    return disk->revert_snapshot(snap_id);
1282
}
1283

    
1284
/* -------------------------------------------------------------------------- */
1285
/* -------------------------------------------------------------------------- */
1286

    
1287
void VirtualMachineDisks::delete_snapshot(int disk_id, int snap_id,
1288
        Template **ds_quota, Template **vm_quota,bool& img_owner, bool& vm_owner)
1289
{
1290
    VirtualMachineDisk * disk =
1291
        static_cast<VirtualMachineDisk *>(get_attribute(disk_id));
1292

    
1293
    *ds_quota = 0;
1294
    *vm_quota = 0;
1295

    
1296
    if ( disk == 0 )
1297
    {
1298
        return;
1299
    }
1300

    
1301
    disk->delete_snapshot(snap_id, ds_quota, vm_quota, img_owner, vm_owner);
1302
}
1303

    
1304
/* -------------------------------------------------------------------------- */
1305
/* -------------------------------------------------------------------------- */
1306

    
1307
void VirtualMachineDisks::delete_non_persistent_snapshots(Template **vm_quotas,
1308
        vector<Template *> &ds_quotas)
1309
{
1310
    long long system_disk = 0;
1311

    
1312
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
1313
    {
1314
        string tm_target = (*disk)->get_tm_target();
1315

    
1316
        if ( !(*disk)->has_snapshots() || tm_target == "NONE" )
1317
        {
1318
            continue;
1319
        }
1320

    
1321
        bool vm_owner  = tm_target == "SELF";
1322
        bool img_owner = (*disk)->is_persistent();
1323

    
1324
        // Decrement DS quota on disks that do not modify the original image
1325
        if ( vm_owner || img_owner )
1326
        {
1327
            int image_id;
1328

    
1329
            if ( (*disk)->vector_value("IMAGE_ID", image_id) != 0 )
1330
            {
1331
                continue;
1332
            }
1333

    
1334
            Template * d_ds = new Template();
1335

    
1336
            d_ds->add("DATASTORE", (*disk)->vector_value("DATASTORE_ID"));
1337
            d_ds->add("SIZE", (*disk)->get_total_snapshot_size());
1338
            d_ds->add("IMAGES", 0);
1339
            d_ds->add("IMAGE_ID", image_id);
1340
            d_ds->add("VM_QUOTA", vm_owner);
1341
            d_ds->add("IMG_QUOTA", img_owner);
1342

    
1343
            ds_quotas.push_back(d_ds);
1344
        }
1345

    
1346
        if ( tm_target == "SYSTEM" )
1347
        {
1348
            system_disk += (*disk)->get_total_snapshot_size();
1349
        }
1350

    
1351
        (*disk)->clear_snapshots();
1352

    
1353
        (*disk)->remove("DISK_SNAPSHOT_ACTIVE");
1354
        (*disk)->remove("DISK_SNAPSHOT_ID");
1355
        (*disk)->remove("DISK_SNAPSHOT_TOTAL_SIZE");
1356
    }
1357

    
1358
    if ( system_disk > 0 )
1359
    {
1360
        *vm_quotas = new Template();
1361

    
1362
        VectorAttribute * delta_disk = new VectorAttribute("DISK");
1363

    
1364
        delta_disk->replace("TYPE", "FS");
1365
        delta_disk->replace("SIZE", system_disk);
1366

    
1367
        (*vm_quotas)->add("VMS", 0);
1368
        (*vm_quotas)->set(delta_disk);
1369
    }
1370
}
1371

    
1372
/* -------------------------------------------------------------------------- */
1373
/* -------------------------------------------------------------------------- */
1374

    
1375
int VirtualMachineDisks::set_saveas(int disk_id, int snap_id, int &iid,
1376
        long long &size, string& err_str)
1377
{
1378
    iid = -1;
1379

    
1380
    VirtualMachineDisk * disk =
1381
        static_cast<VirtualMachineDisk *>(get_attribute(disk_id));
1382

    
1383
    if (disk == 0)
1384
    {
1385
        err_str = "DISK does not exist.";
1386
        return -1;
1387
    }
1388

    
1389
    if (disk->vector_value("IMAGE_ID", iid) != 0)
1390
    {
1391
        iid = -1;
1392
        err_str = "DISK does not have a valid IMAGE_ID.";
1393
        return -1;
1394
    }
1395

    
1396
    const Snapshots * snaps = disk->get_snapshots();
1397

    
1398
    if (snap_id != -1)
1399
    {
1400
        if (snaps == 0 || !snaps->exists(snap_id))
1401
        {
1402
            err_str = "Snapshot does not exist.";
1403
            return -1;
1404
        }
1405
    }
1406

    
1407
    disk->set_saveas();
1408
    disk->replace("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id);
1409

    
1410
    size = 0;
1411
    disk->vector_value("SIZE", size);
1412

    
1413
    return 0;
1414
}
1415

    
1416
/* -------------------------------------------------------------------------- */
1417
/* -------------------------------------------------------------------------- */
1418

    
1419
int VirtualMachineDisks::set_saveas(int disk_id, const string& source, int iid)
1420
{
1421
    VirtualMachineDisk * disk = get_saveas();
1422

    
1423
    if ( disk == 0 )
1424
    {
1425
        return -1;
1426
    }
1427

    
1428
    disk->replace("HOTPLUG_SAVE_AS", iid);
1429
    disk->replace("HOTPLUG_SAVE_AS_SOURCE", source);
1430

    
1431
    return 0;
1432
}
1433

    
1434
/* -------------------------------------------------------------------------- */
1435
/* -------------------------------------------------------------------------- */
1436

    
1437
int VirtualMachineDisks::clear_saveas()
1438
{
1439
    VirtualMachineDisk * disk = get_saveas();
1440

    
1441
    if ( disk == 0 )
1442
    {
1443
        return -1;
1444
    }
1445

    
1446
    int  image_id;
1447

    
1448
    disk->clear_saveas();
1449

    
1450
    disk->vector_value("HOTPLUG_SAVE_AS", image_id);
1451

    
1452
    disk->remove("HOTPLUG_SAVE_AS");
1453
    disk->remove("HOTPLUG_SAVE_AS_SOURCE");
1454
    disk->remove("HOTPLUG_SAVE_AS_SNAPSHOT_ID");
1455

    
1456
    return image_id;
1457
}
1458

    
1459
/* -------------------------------------------------------------------------- */
1460
/* -------------------------------------------------------------------------- */
1461

    
1462
int VirtualMachineDisks::get_saveas_info(int& disk_id, string& source,
1463
        int& image_id, string& snap_id, string& tm_mad, string& ds_id)
1464
{
1465
    int rc;
1466

    
1467
    VirtualMachineDisk * disk = get_saveas();
1468

    
1469
    if ( disk == 0 )
1470
    {
1471
        return -1;
1472
    }
1473

    
1474
    rc  = disk->vector_value("HOTPLUG_SAVE_AS_SOURCE", source);
1475
    rc += disk->vector_value("HOTPLUG_SAVE_AS", image_id);
1476
    rc += disk->vector_value("HOTPLUG_SAVE_AS_SNAPSHOT_ID", snap_id);
1477
    rc += disk->vector_value("DISK_ID",  disk_id);
1478
    rc += disk->vector_value("DATASTORE_ID", ds_id);
1479
    rc += disk->vector_value("TM_MAD", tm_mad);
1480

    
1481
    return rc;
1482
}
1483

    
1484
/* -------------------------------------------------------------------------- */
1485
/* -------------------------------------------------------------------------- */
1486

    
1487
void VirtualMachineDisks::delete_non_persistent_resizes(Template **vm_quotas,
1488
        vector<Template *>& ds_quotas)
1489
{
1490
    long long original_size, size, delta_size, system_disk = 0;
1491

    
1492
    string tm_target;
1493
    int    rc;
1494

    
1495
    for ( disk_iterator disk = begin() ; disk != end() ; ++disk )
1496
    {
1497
        tm_target = (*disk)->get_tm_target();
1498

    
1499
        rc  = (*disk)->vector_value("SIZE", size);
1500
        rc += (*disk)->vector_value("ORIGINAL_SIZE", original_size);
1501

    
1502
        if ( rc != 0 || original_size >= size || tm_target == "NONE" )
1503
        {
1504
            continue;
1505
        }
1506

    
1507
        delta_size = original_size - size;
1508

    
1509
        //Quotas uses del operation to substract counters, delta needs to be > 0
1510
        if ( delta_size < 0 )
1511
        {
1512
            delta_size = - delta_size;
1513
        }
1514

    
1515
        bool vm_owner  = tm_target == "SELF";
1516
        bool img_owner = (*disk)->is_persistent();
1517

    
1518
        // Decrement DS quota on disks that do not modify the original image
1519
        if ( vm_owner || img_owner )
1520
        {
1521
            int image_id;
1522

    
1523
            if ( (*disk)->vector_value("IMAGE_ID", image_id) != 0 )
1524
            {
1525
                continue;
1526
            }
1527

    
1528
            Template * d_ds = new Template();
1529

    
1530
            d_ds->add("DATASTORE", (*disk)->vector_value("DATASTORE_ID"));
1531
            d_ds->add("SIZE", delta_size);
1532
            d_ds->add("IMAGES", 0);
1533
            d_ds->add("IMAGE_ID", image_id);
1534
            d_ds->add("VM_QUOTA", vm_owner);
1535
            d_ds->add("IMG_QUOTA", img_owner);
1536

    
1537
            ds_quotas.push_back(d_ds);
1538
        }
1539

    
1540
        if ( tm_target == "SYSTEM" )
1541
        {
1542
            system_disk += delta_size;
1543
        }
1544

    
1545
        (*disk)->replace("SIZE", original_size);
1546
    }
1547

    
1548
    if ( system_disk > 0 )
1549
    {
1550
        *vm_quotas = new Template();
1551

    
1552
        VectorAttribute * delta_disk = new VectorAttribute("DISK");
1553

    
1554
        delta_disk->replace("TYPE", "FS");
1555
        delta_disk->replace("SIZE", system_disk);
1556

    
1557
        (*vm_quotas)->add("VMS", 0);
1558
        (*vm_quotas)->set(delta_disk);
1559
    }
1560
}
1561

    
1562
/* -------------------------------------------------------------------------- */
1563
/* -------------------------------------------------------------------------- */