Statistics
| Branch: | Tag: | Revision:

one / src / dm / DispatchManagerActions.cc @ b401abe7

History | View | Annotate | Download (52.4 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 "DispatchManager.h"
18
#include "NebulaLog.h"
19

    
20
#include "VirtualMachineManager.h"
21
#include "TransferManager.h"
22
#include "ImageManager.h"
23
#include "Quotas.h"
24
#include "Request.h"
25

    
26
/* -------------------------------------------------------------------------- */
27
/* -------------------------------------------------------------------------- */
28

    
29
int DispatchManager::deploy (VirtualMachine * vm, const RequestAttributes& ra)
30
{
31
    ostringstream oss;
32
    int           vid;
33

    
34
    if ( vm == 0 )
35
    {
36
        return -1;
37
    }
38

    
39
    vid = vm->get_oid();
40

    
41
    oss << "Deploying VM " << vid;
42
    NebulaLog::log("DiM",Log::DEBUG,oss);
43

    
44
    if ( vm->get_state() == VirtualMachine::PENDING ||
45
         vm->get_state() == VirtualMachine::HOLD ||
46
         vm->get_state() == VirtualMachine::STOPPED ||
47
         vm->get_state() == VirtualMachine::UNDEPLOYED )
48
    {
49
        vm->set_state(VirtualMachine::ACTIVE);
50

    
51
        vmpool->update(vm);
52

    
53
        lcm->trigger(LCMAction::DEPLOY, vid, ra);
54
    }
55
    else
56
    {
57
        goto error;
58
    }
59

    
60
    return 0;
61

    
62
error:
63
    oss.str("");
64
    oss << "Could not deploy VM " << vid
65
        << ", wrong state " << vm->state_str() << ".";
66
    NebulaLog::log("DiM",Log::ERROR,oss);
67

    
68
    return -1;
69
}
70

    
71
/* -------------------------------------------------------------------------- */
72
/* -------------------------------------------------------------------------- */
73

    
74
int DispatchManager::import(VirtualMachine * vm, const RequestAttributes& ra)
75
{
76
    ostringstream oss;
77
    string import_state;
78

    
79
    if ( vm == 0 )
80
    {
81
        return -1;
82
    }
83

    
84
    if ( vm->get_state() != VirtualMachine::PENDING &&
85
         vm->get_state() != VirtualMachine::HOLD )
86
    {
87
        return -1;
88
    }
89

    
90
    time_t the_time = time(0);
91
    int    cpu, mem, disk;
92
    vector<VectorAttribute *> pci;
93

    
94
    vm->get_requirements(cpu, mem, disk, pci);
95

    
96
    hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
97

    
98
    import_state = vm->get_import_state();
99

    
100
    if(import_state == "POWEROFF")
101
    {
102
        vm->set_state(VirtualMachine::POWEROFF);
103
        vm->set_state(VirtualMachine::LCM_INIT);
104
    }
105
    else
106
    {
107
        vm->set_state(VirtualMachine::ACTIVE);
108
        vm->set_state(VirtualMachine::RUNNING);
109
    }
110

    
111
    vm->set_stime(the_time);
112

    
113
    vm->set_prolog_stime(the_time);
114
    vm->set_prolog_etime(the_time);
115

    
116
    vm->set_running_stime(the_time);
117

    
118
    vm->set_last_poll(0);
119

    
120
    vmpool->update_history(vm);
121

    
122
    vmpool->update(vm);
123

    
124
    return 0;
125
}
126

    
127
/* -------------------------------------------------------------------------- */
128
/* -------------------------------------------------------------------------- */
129

    
130
int DispatchManager::migrate(VirtualMachine * vm, const RequestAttributes& ra)
131
{
132
    ostringstream oss;
133
    int           vid;
134

    
135
    if ( vm == 0 )
136
    {
137
        return -1;
138
    }
139

    
140
    vid = vm->get_oid();
141

    
142
    oss << "Migrating VM " << vid;
143
    NebulaLog::log("DiM",Log::DEBUG,oss);
144

    
145
    if ((vm->get_state()     == VirtualMachine::ACTIVE &&
146
         (vm->get_lcm_state() == VirtualMachine::RUNNING ||
147
          vm->get_lcm_state() == VirtualMachine::UNKNOWN )) ||
148
         vm->get_state() == VirtualMachine::POWEROFF ||
149
         vm->get_state() == VirtualMachine::SUSPENDED)
150
    {
151
        lcm->trigger(LCMAction::MIGRATE, vid, ra);
152
    }
153
    else
154
    {
155
        goto error;
156
    }
157

    
158
    return 0;
159

    
160
error:
161
    oss.str("");
162
    oss << "Could not migrate VM " << vid
163
        << ", wrong state " << vm->state_str() << ".";
164
    NebulaLog::log("DiM",Log::ERROR,oss);
165

    
166
    return -1;
167
}
168

    
169
/* -------------------------------------------------------------------------- */
170
/* -------------------------------------------------------------------------- */
171

    
172
int DispatchManager::live_migrate(VirtualMachine * vm,
173
        const RequestAttributes& ra)
174
{
175
    ostringstream oss;
176
    int           vid;
177

    
178
    if ( vm == 0 )
179
    {
180
        return -1;
181
    }
182

    
183
    vid = vm->get_oid();
184

    
185
    oss << "Live-migrating VM " << vid;
186
    NebulaLog::log("DiM",Log::DEBUG,oss);
187

    
188
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
189
        vm->get_lcm_state() == VirtualMachine::RUNNING )
190
    {
191
        lcm->trigger(LCMAction::LIVE_MIGRATE, vid, ra);
192
    }
193
    else
194
    {
195
        goto error;
196
    }
197

    
198
    return 0;
199

    
200
error:
201
    oss.str("");
202
    oss << "Could not live-migrate VM " << vid
203
        << ", wrong state " << vm->state_str() << ".";
204
    NebulaLog::log("DiM",Log::ERROR,oss);
205

    
206
    return -1;
207
}
208

    
209
/* ************************************************************************** */
210
/* ************************************************************************** */
211

    
212
void DispatchManager::free_vm_resources(VirtualMachine * vm)
213
{
214
    Template* tmpl;
215
    vector<Template *> ds_quotas;
216

    
217
    int uid;
218
    int gid;
219
    int vrid = -1;
220
    int vmid;
221

    
222
    vm->release_network_leases();
223
    vm->release_vmgroup();
224
    vm->release_disk_images(ds_quotas);
225

    
226
    vm->set_exit_time(time(0));
227

    
228
    vm->set_state(VirtualMachine::LCM_INIT);
229
    vm->set_state(VirtualMachine::DONE);
230
    vmpool->update(vm);
231

    
232
    vmid = vm->get_oid();
233
    uid  = vm->get_uid();
234
    gid  = vm->get_gid();
235
    tmpl = vm->clone_template();
236

    
237
    if (vm->is_vrouter())
238
    {
239
        vrid = vm->get_vrouter_id();
240
    }
241

    
242
    vm->unlock();
243

    
244
    Quotas::vm_del(uid, gid, tmpl);
245

    
246
    delete tmpl;
247

    
248
    if ( !ds_quotas.empty() )
249
    {
250
        Quotas::ds_del(uid, gid, ds_quotas);
251
    }
252

    
253
    if (vrid != -1)
254
    {
255
        VirtualRouter* vr = vrouterpool->get(vrid, true);
256

    
257
        if (vr != 0)
258
        {
259
            vr->del_vmid(vmid);
260

    
261
            vrouterpool->update(vr);
262

    
263
            vr->unlock();
264
        }
265
    }
266
}
267

    
268
/* -------------------------------------------------------------------------- */
269
/* -------------------------------------------------------------------------- */
270

    
271
int DispatchManager::terminate(int vid, bool hard, const RequestAttributes& ra,
272
        string& error_str)
273
{
274
    int rc = 0;
275
    ostringstream oss;
276

    
277
    VirtualMachine * vm = vmpool->get(vid,true);
278

    
279
    if ( vm == 0 )
280
    {
281
        return -1;
282
    }
283

    
284
    oss << "Terminating VM " << vid;
285
    NebulaLog::log("DiM",Log::DEBUG,oss);
286

    
287
    switch (vm->get_state())
288
    {
289
        //Hard has no effect, VM is not RUNNING
290
        case VirtualMachine::SUSPENDED:
291
        case VirtualMachine::POWEROFF:
292
        case VirtualMachine::STOPPED:
293
        case VirtualMachine::UNDEPLOYED:
294
            lcm->trigger(LCMAction::SHUTDOWN, vid, ra);
295
            vm->unlock();
296
            break;
297

    
298
        case VirtualMachine::INIT:
299
        case VirtualMachine::PENDING:
300
        case VirtualMachine::HOLD:
301
        case VirtualMachine::CLONING:
302
        case VirtualMachine::CLONING_FAILURE:
303
            free_vm_resources(vm);
304
            break;
305

    
306
        case VirtualMachine::DONE:
307
            vm->unlock();
308
            break;
309

    
310
        case VirtualMachine::ACTIVE:
311
            switch (vm->get_lcm_state())
312
            {
313
                case VirtualMachine::RUNNING:
314
                case VirtualMachine::UNKNOWN:
315
                    if (hard)
316
                    {
317
                        lcm->trigger(LCMAction::CANCEL, vid, ra);
318
                    }
319
                    else
320
                    {
321
                        lcm->trigger(LCMAction::SHUTDOWN, vid, ra);
322
                    }
323
                    break;
324

    
325
                case VirtualMachine::BOOT_FAILURE:
326
                case VirtualMachine::BOOT_MIGRATE_FAILURE:
327
                case VirtualMachine::PROLOG_MIGRATE_FAILURE:
328
                case VirtualMachine::PROLOG_FAILURE:
329
                case VirtualMachine::EPILOG_FAILURE:
330
                case VirtualMachine::EPILOG_STOP_FAILURE:
331
                case VirtualMachine::EPILOG_UNDEPLOY_FAILURE:
332
                case VirtualMachine::PROLOG_MIGRATE_POWEROFF_FAILURE:
333
                case VirtualMachine::PROLOG_MIGRATE_SUSPEND_FAILURE:
334
                case VirtualMachine::BOOT_UNDEPLOY_FAILURE:
335
                case VirtualMachine::BOOT_STOPPED_FAILURE:
336
                case VirtualMachine::PROLOG_RESUME_FAILURE:
337
                case VirtualMachine::PROLOG_UNDEPLOY_FAILURE:
338
                case VirtualMachine::PROLOG_MIGRATE_UNKNOWN_FAILURE:
339
                    lcm->trigger(LCMAction::DELETE, vid, ra);
340
                    break;
341

    
342
                default:
343
                    oss.str("");
344
                    oss << "Could not terminate VM " << vid
345
                        << ", wrong state " << vm->state_str() << ".";
346

    
347
                    NebulaLog::log("DiM",Log::ERROR,oss);
348
                    error_str = oss.str();
349

    
350
                    rc = -2;
351
                    break;
352
            }
353
            vm->unlock();
354
            break;
355
    }
356

    
357
    return rc;
358
}
359

    
360
/* -------------------------------------------------------------------------- */
361
/* -------------------------------------------------------------------------- */
362

    
363
int DispatchManager::undeploy(int vid, bool hard, const RequestAttributes& ra,
364
        string& error_str)
365
{
366
    ostringstream oss;
367

    
368
    VirtualMachine * vm = vmpool->get(vid, true);
369

    
370
    if ( vm == 0 )
371
    {
372
        return -1;
373
    }
374

    
375
    oss << "Undeploying VM " << vid;
376
    NebulaLog::log("DiM",Log::DEBUG,oss);
377

    
378
    if ( vm->get_state()       == VirtualMachine::POWEROFF ||
379
         (vm->get_state()       == VirtualMachine::ACTIVE &&
380
           (vm->get_lcm_state() == VirtualMachine::RUNNING ||
381
            vm->get_lcm_state() == VirtualMachine::UNKNOWN)))
382
    {
383
        if (hard)
384
        {
385
            lcm->trigger(LCMAction::UNDEPLOY_HARD, vid, ra);
386
        }
387
        else
388
        {
389
            lcm->trigger(LCMAction::UNDEPLOY, vid, ra);
390
        }
391
    }
392
    else
393
    {
394
        goto error;
395
    }
396

    
397
    vm->unlock();
398

    
399
    return 0;
400

    
401
error:
402
    oss.str("");
403
    oss << "Could not undeploy VM " << vid
404
        << ", wrong state " << vm->state_str() << ".";
405
    NebulaLog::log("DiM",Log::ERROR,oss);
406

    
407
    oss.str("");
408
    oss << "This action is not available for state " << vm->state_str();
409
    error_str = oss.str();
410

    
411
    vm->unlock();
412
    return -2;
413
}
414

    
415
/* -------------------------------------------------------------------------- */
416
/* -------------------------------------------------------------------------- */
417

    
418
int DispatchManager::poweroff (int vid, bool hard, const RequestAttributes& ra,
419
        string& error_str)
420
{
421
    ostringstream oss;
422

    
423
    VirtualMachine * vm = vmpool->get(vid, true);
424

    
425
    if ( vm == 0 )
426
    {
427
        return -1;
428
    }
429

    
430
    oss << "Powering off VM " << vid;
431
    NebulaLog::log("DiM",Log::DEBUG,oss);
432

    
433
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
434
        (vm->get_lcm_state() == VirtualMachine::RUNNING ||
435
         vm->get_lcm_state() == VirtualMachine::UNKNOWN))
436
    {
437
        if (hard)
438
        {
439
            lcm->trigger(LCMAction::POWEROFF_HARD, vid, ra);
440
        }
441
        else
442
        {
443
            lcm->trigger(LCMAction::POWEROFF, vid, ra);
444
        }
445
    }
446
    else
447
    {
448
        goto error;
449
    }
450

    
451
    vm->unlock();
452

    
453
    return 0;
454

    
455
error:
456

    
457
    oss.str("");
458
    oss << "Could not power off VM " << vid
459
        << ", wrong state " << vm->state_str() << ".";
460
    NebulaLog::log("DiM",Log::ERROR,oss);
461

    
462
    oss.str("");
463
    oss << "This action is not available for state " << vm->state_str();
464
    error_str = oss.str();
465

    
466
    vm->unlock();
467
    return -2;
468
}
469

    
470
/* -------------------------------------------------------------------------- */
471
/* -------------------------------------------------------------------------- */
472

    
473
int DispatchManager::hold(int vid, const RequestAttributes& ra,
474
        string& error_str)
475
{
476
    ostringstream oss;
477

    
478
    VirtualMachine * vm = vmpool->get(vid, true);
479

    
480
    if ( vm == 0 )
481
    {
482
        return -1;
483
    }
484

    
485
    oss << "Holding VM " << vid;
486
    NebulaLog::log("DiM",Log::DEBUG,oss);
487

    
488
    if (vm->get_state() == VirtualMachine::PENDING)
489
    {
490
        vm->set_state(VirtualMachine::HOLD);
491

    
492
        vmpool->update(vm);
493
    }
494
    else
495
    {
496
        goto error;
497
    }
498

    
499
    vm->unlock();
500

    
501
    return 0;
502

    
503
error:
504

    
505
    oss.str("");
506
    oss << "Could not hold VM " << vid
507
        << ", wrong state " << vm->state_str() << ".";
508
    NebulaLog::log("DiM",Log::ERROR,oss);
509

    
510
    oss.str("");
511
    oss << "This action is not available for state " << vm->state_str();
512
    error_str = oss.str();
513

    
514
    vm->unlock();
515
    return -2;
516
}
517

    
518
/* -------------------------------------------------------------------------- */
519
/* -------------------------------------------------------------------------- */
520

    
521
int DispatchManager::release(int vid, const RequestAttributes& ra,
522
        string& error_str)
523
{
524
    ostringstream oss;
525

    
526
    VirtualMachine * vm = vmpool->get(vid, true);
527

    
528
    if ( vm == 0 )
529
    {
530
        return -1;
531
    }
532

    
533
    oss << "Releasing VM " << vid;
534
    NebulaLog::log("DiM",Log::DEBUG,oss);
535

    
536
    if (vm->get_state() == VirtualMachine::HOLD)
537
    {
538
        set<int> cluster_ids;
539
        int rc = vm->automatic_requirements(cluster_ids, error_str);
540

    
541
        if (rc != 0)
542
        {
543
            vmpool->update(vm);
544

    
545
            goto error_requirements;
546
        }
547

    
548
        vm->set_state(VirtualMachine::PENDING);
549

    
550
        vmpool->update(vm);
551
    }
552
    else
553
    {
554
        goto error_state;
555
    }
556

    
557
    vm->unlock();
558

    
559
    return 0;
560

    
561
error_requirements:
562
    oss.str("");
563
    oss << "Could not release VM " << vid
564
        << ", error updating requirements. " << error_str;
565
    NebulaLog::log("DiM",Log::ERROR,oss);
566

    
567
    error_str = oss.str();
568

    
569
    vm->unlock();
570
    return -2;
571

    
572
error_state:
573
    oss.str("");
574
    oss << "Could not release VM " << vid
575
        << ", wrong state " << vm->state_str() << ".";
576
    NebulaLog::log("DiM",Log::ERROR,oss);
577

    
578
    oss.str("");
579
    oss << "This action is not available for state " << vm->state_str();
580
    error_str = oss.str();
581

    
582
    vm->unlock();
583
    return -2;
584
}
585

    
586
/* -------------------------------------------------------------------------- */
587
/* -------------------------------------------------------------------------- */
588

    
589
int DispatchManager::stop(int vid, const RequestAttributes& ra,
590
        string& error_str)
591
{
592
    ostringstream oss;
593

    
594
    VirtualMachine * vm = vmpool->get(vid, true);
595

    
596
    if ( vm == 0 )
597
    {
598
        return -1;
599
    }
600

    
601
    oss << "Stopping VM " << vid;
602
    NebulaLog::log("DiM",Log::DEBUG,oss);
603

    
604
    if (vm->get_state()        == VirtualMachine::SUSPENDED ||
605
        (vm->get_state()       == VirtualMachine::ACTIVE &&
606
         vm->get_lcm_state() == VirtualMachine::RUNNING ))
607
    {
608
        lcm->trigger(LCMAction::STOP, vid, ra);
609
    }
610
    else
611
    {
612
        goto error;
613
    }
614

    
615
    vm->unlock();
616

    
617
    return 0;
618

    
619
error:
620
    oss.str("");
621
    oss << "Could not stop VM " << vid
622
        << ", wrong state " << vm->state_str() << ".";
623
    NebulaLog::log("DiM",Log::ERROR,oss);
624

    
625
    oss.str("");
626
    oss << "This action is not available for state " << vm->state_str();
627
    error_str = oss.str();
628

    
629
    vm->unlock();
630
    return -2;
631
}
632

    
633
/* -------------------------------------------------------------------------- */
634
/* -------------------------------------------------------------------------- */
635

    
636
int DispatchManager::suspend(int vid, const RequestAttributes& ra,
637
        string& error_str)
638
{
639
    ostringstream oss;
640

    
641
    VirtualMachine * vm = vmpool->get(vid, true);
642

    
643
    if ( vm == 0 )
644
    {
645
        return -1;
646
    }
647

    
648
    oss << "Suspending VM " << vid;
649
    NebulaLog::log("DiM",Log::DEBUG,oss);
650

    
651
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
652
        vm->get_lcm_state() == VirtualMachine::RUNNING )
653
    {
654
        lcm->trigger(LCMAction::SUSPEND, vid, ra);
655
    }
656
    else
657
    {
658
        goto error;
659
    }
660

    
661
    vm->unlock();
662

    
663
    return 0;
664

    
665
error:
666
    oss.str("");
667
    oss << "Could not suspend VM " << vid
668
        << ", wrong state " << vm->state_str() << ".";
669
    NebulaLog::log("DiM", Log::ERROR, oss);
670

    
671
    oss.str("");
672
    oss << "This action is not available for state " << vm->state_str();
673
    error_str = oss.str();
674

    
675
    vm->unlock();
676
    return -2;
677
}
678

    
679
/* -------------------------------------------------------------------------- */
680
/* -------------------------------------------------------------------------- */
681

    
682
int DispatchManager::resume(int vid, const RequestAttributes& ra,
683
        string& error_str)
684
{
685
    ostringstream oss;
686

    
687
    VirtualMachine * vm = vmpool->get(vid, true);
688

    
689
    if ( vm == 0 )
690
    {
691
        return -1;
692
    }
693

    
694
    oss << "Resuming VM " << vid;
695
    NebulaLog::log("DiM",Log::DEBUG,oss);
696

    
697
    if (vm->get_state() == VirtualMachine::STOPPED ||
698
        vm->get_state() == VirtualMachine::UNDEPLOYED )
699
    {
700
        set<int> cluster_ids;
701
        int rc = vm->automatic_requirements(cluster_ids, error_str);
702

    
703
        if (rc != 0)
704
        {
705
            vmpool->update(vm);
706

    
707
            goto error_requirements;
708
        }
709

    
710
        vm->set_state(VirtualMachine::PENDING);
711

    
712
        vmpool->update(vm);
713
    }
714
    else if (vm->get_state() == VirtualMachine::SUSPENDED)
715
    {
716
        lcm->trigger(LCMAction::RESTORE, vid, ra);
717
    }
718
    else if ( vm->get_state() == VirtualMachine::POWEROFF ||
719
             (vm->get_state() == VirtualMachine::ACTIVE &&
720
              vm->get_lcm_state() == VirtualMachine::UNKNOWN))
721
    {
722
        lcm->trigger(LCMAction::RESTART, vid, ra);
723
    }
724
    else
725
    {
726
        goto error_state;
727
    }
728

    
729
    vm->unlock();
730

    
731
    return 0;
732

    
733
error_requirements:
734
    oss.str("");
735
    oss << "Could not resume VM " << vid
736
        << ", error updating requirements. " << error_str;
737
    NebulaLog::log("DiM",Log::ERROR,oss);
738

    
739
    error_str = oss.str();
740

    
741
    vm->unlock();
742
    return -2;
743

    
744
error_state:
745
    oss.str("");
746
    oss << "Could not resume VM " << vid
747
        << ", wrong state " << vm->state_str() << ".";
748
    NebulaLog::log("DiM",Log::ERROR,oss);
749

    
750
    oss.str("");
751
    oss << "This action is not available for state " << vm->state_str();
752
    error_str = oss.str();
753

    
754
    vm->unlock();
755
    return -2;
756
}
757

    
758
/* -------------------------------------------------------------------------- */
759
/* -------------------------------------------------------------------------- */
760

    
761
int DispatchManager::reboot(int vid, bool hard, const RequestAttributes& ra,
762
        string& error_str)
763
{
764
    ostringstream oss;
765

    
766
    VirtualMachine * vm = vmpool->get(vid, true);
767

    
768
    if ( vm == 0 )
769
    {
770
        return -1;
771
    }
772

    
773
    oss << "Rebooting VM " << vid;
774
    NebulaLog::log("DiM",Log::DEBUG,oss);
775

    
776
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
777
        vm->get_lcm_state() == VirtualMachine::RUNNING )
778
    {
779
        if (hard)
780
        {
781
            vmm->trigger(VMMAction::RESET, vid);
782
        }
783
        else
784
        {
785
            vmm->trigger(VMMAction::REBOOT, vid);
786
        }
787

    
788
        vm->set_resched(false); //Rebooting cancels re-scheduling actions
789

    
790
        vmpool->update(vm);
791
    }
792
    else
793
    {
794
        goto error;
795
    }
796

    
797
    vm->unlock();
798

    
799
    return 0;
800

    
801
error:
802
    oss.str("");
803
    oss << "Could not reboot VM " << vid
804
        << ", wrong state " << vm->state_str() << ".";
805
    NebulaLog::log("DiM",Log::ERROR,oss);
806

    
807
    oss.str("");
808
    oss << "This action is not available for state " << vm->state_str();
809
    error_str = oss.str();
810

    
811
    vm->unlock();
812

    
813
    return -2;
814
}
815

    
816
/* -------------------------------------------------------------------------- */
817
/* -------------------------------------------------------------------------- */
818

    
819
int DispatchManager::resched(int vid, bool do_resched,
820
        const RequestAttributes& ra, string& error_str)
821
{
822
    ostringstream oss;
823

    
824
    VirtualMachine * vm = vmpool->get(vid, true);
825

    
826
    if ( vm == 0 )
827
    {
828
        return -1;
829
    }
830

    
831
    oss << "Setting rescheduling flag on VM " << vid;
832
    NebulaLog::log("DiM",Log::DEBUG,oss);
833

    
834
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
835
        (vm->get_lcm_state() == VirtualMachine::RUNNING ||
836
         vm->get_lcm_state() == VirtualMachine::UNKNOWN))
837
    {
838
        if (do_resched)
839
        {
840
            set<int> cluster_ids;
841
            int rc = vm->automatic_requirements(cluster_ids, error_str);
842

    
843
            if (rc != 0)
844
            {
845
                vmpool->update(vm);
846

    
847
                goto error_requirements;
848
            }
849
        }
850

    
851
        vm->set_resched(do_resched);
852
        vmpool->update(vm);
853
    }
854
    else
855
    {
856
        goto error_state;
857
    }
858

    
859
    vm->unlock();
860

    
861
    return 0;
862

    
863
error_requirements:
864
    oss.str("");
865
    oss << "Could not set rescheduling flag for VM " << vid
866
        << ", error updating requirements. " << error_str;
867
    NebulaLog::log("DiM",Log::ERROR,oss);
868

    
869
    error_str = oss.str();
870

    
871
    vm->unlock();
872
    return -2;
873

    
874
error_state:
875
    oss.str("");
876
    oss << "Could not set rescheduling flag for VM " << vid
877
        << ", wrong state " << vm->state_str() << ".";
878
    NebulaLog::log("DiM",Log::ERROR,oss);
879

    
880
    oss.str("");
881
    oss << "This action is not available for state " << vm->state_str();
882
    error_str = oss.str();
883

    
884
    vm->unlock();
885

    
886
    return -2;
887
}
888

    
889
/* -------------------------------------------------------------------------- */
890
/* -------------------------------------------------------------------------- */
891

    
892
int DispatchManager::recover(VirtualMachine * vm, bool success,
893
         const RequestAttributes& ra, string& error_str)
894
{
895
    int rc = 0;
896
    int vid = vm->get_oid();
897

    
898
    switch (vm->get_state())
899
    {
900
        case VirtualMachine::CLONING_FAILURE:
901
            if (success)
902
            {
903
                lcm->trigger(LCMAction::DISK_LOCK_SUCCESS, vid, ra);
904
            }
905
            else
906
            {
907
                lcm->trigger(LCMAction::DISK_LOCK_FAILURE, vid, ra);
908
            }
909
            break;
910

    
911
        case VirtualMachine::ACTIVE:
912
            lcm->recover(vm, success, ra);
913
            break;
914

    
915
        default:
916
            rc    = -1;
917

    
918
            ostringstream oss;
919
            oss << "Could not perform a recover operation on VM " << vm->get_oid()
920
                << ", wrong state " << vm->state_str() << ".";
921
            error_str = oss.str();
922

    
923
            break;
924
    }
925

    
926
    vm->unlock();
927

    
928
    return rc;
929
}
930

    
931
/* -------------------------------------------------------------------------- */
932
/* -------------------------------------------------------------------------- */
933

    
934
int DispatchManager::retry(VirtualMachine * vm,  const RequestAttributes& ra,
935
        string& error_str)
936
{
937
    int rc = 0;
938

    
939
    switch (vm->get_state())
940
    {
941
        case VirtualMachine::ACTIVE:
942
            lcm->retry(vm);
943
            break;
944

    
945
        default:
946
            rc    = -1;
947

    
948
            ostringstream oss;
949
            oss << "Could not perform a retry on VM " << vm->get_oid()
950
                << ", wrong state " << vm->state_str() << ".";
951
            error_str = oss.str();
952

    
953
            break;
954
    }
955

    
956
    vm->unlock();
957

    
958
    return rc;
959
}
960

    
961
/* -------------------------------------------------------------------------- */
962
/* -------------------------------------------------------------------------- */
963

    
964
int DispatchManager::delete_vm(VirtualMachine * vm, const RequestAttributes& ra,
965
        string& error)
966
{
967
    ostringstream oss;
968

    
969
    int cpu, mem, disk;
970
    vector<VectorAttribute *> pci;
971

    
972
    bool is_public_host = false;
973
    int  host_id = -1;
974

    
975
    if(vm->hasHistory())
976
    {
977
        host_id = vm->get_hid();
978
    }
979

    
980
    int vid = vm->get_oid();
981

    
982
    if(host_id != -1)
983
    {
984
        Host * host = hpool->get(host_id,true);
985

    
986
        if ( host == 0 )
987
        {
988
            oss << "Error getting host " << host_id;
989
            error = oss.str();
990

    
991
            vm->unlock();
992

    
993
            return -1;
994
        }
995

    
996
        is_public_host = host->is_public_cloud();
997

    
998
        host->unlock();
999
    }
1000

    
1001
    oss << "Deleting VM " << vm->get_oid();
1002
    NebulaLog::log("DiM",Log::DEBUG,oss);
1003

    
1004
    switch (vm->get_state())
1005
    {
1006
        case VirtualMachine::SUSPENDED:
1007
        case VirtualMachine::POWEROFF:
1008
            vm->get_requirements(cpu, mem, disk, pci);
1009

    
1010
            hpool->del_capacity(vm->get_hid(), vid, cpu, mem, disk, pci);
1011

    
1012
            if (is_public_host)
1013
            {
1014
                vmm->trigger(VMMAction::CLEANUP, vid);
1015
            }
1016
            else
1017
            {
1018
                tm->trigger(TMAction::EPILOG_DELETE, vid);
1019
            }
1020

    
1021
            free_vm_resources(vm);
1022
        break;
1023

    
1024
        case VirtualMachine::STOPPED:
1025
        case VirtualMachine::UNDEPLOYED:
1026
            if (is_public_host)
1027
            {
1028
                vmm->trigger(VMMAction::CLEANUP, vid);
1029
            }
1030
            else
1031
            {
1032
                tm->trigger(TMAction::EPILOG_DELETE, vid);
1033
            }
1034

    
1035
            free_vm_resources(vm);
1036
        break;
1037

    
1038
        case VirtualMachine::INIT:
1039
        case VirtualMachine::PENDING:
1040
        case VirtualMachine::HOLD:
1041
        case VirtualMachine::CLONING:
1042
        case VirtualMachine::CLONING_FAILURE:
1043
            free_vm_resources(vm);
1044
        break;
1045

    
1046
        case VirtualMachine::ACTIVE:
1047
            lcm->trigger(LCMAction::DELETE, vid, ra);
1048
            vm->unlock();
1049
        break;
1050

    
1051
        case VirtualMachine::DONE:
1052
            vm->unlock();
1053
        break;
1054
    }
1055

    
1056
    return 0;
1057
}
1058

    
1059
/* -------------------------------------------------------------------------- */
1060
/* -------------------------------------------------------------------------- */
1061

    
1062
int DispatchManager::delete_recreate(VirtualMachine * vm,
1063
        const RequestAttributes& ra, string& error)
1064
{
1065
    ostringstream oss;
1066

    
1067
    int rc = 0;
1068

    
1069
    Template * vm_quotas_snp = 0;
1070
    Template * vm_quotas_rsz = 0;
1071

    
1072
    vector<Template *> ds_quotas_snp;
1073
    vector<Template *> ds_quotas_rsz;
1074

    
1075
    int vm_uid, vm_gid;
1076

    
1077
    switch (vm->get_state())
1078
    {
1079
        case VirtualMachine::POWEROFF:
1080
            error = "Cannot delete-recreate a powered off VM. Resume it first";
1081
            NebulaLog::log("DiM", Log::ERROR, error);
1082
            rc = -1;
1083
        break;
1084

    
1085
        case VirtualMachine::SUSPENDED:
1086
            error = "Cannot delete-recreate a suspended VM. Resume it first";
1087
            NebulaLog::log("DiM", Log::ERROR, error);
1088
            rc = -1;
1089
        break;
1090

    
1091
        case VirtualMachine::INIT:
1092
        case VirtualMachine::PENDING:
1093
        case VirtualMachine::CLONING:
1094
        case VirtualMachine::CLONING_FAILURE:
1095
        break;
1096

    
1097
        case VirtualMachine::STOPPED:
1098
        case VirtualMachine::UNDEPLOYED:
1099
            vm_uid = vm->get_uid();
1100
            vm_gid = vm->get_gid();
1101

    
1102
            vm->delete_non_persistent_disk_snapshots(&vm_quotas_rsz,
1103
                    ds_quotas_rsz);
1104
            vm->delete_non_persistent_disk_resizes(&vm_quotas_rsz,
1105
                    ds_quotas_rsz);
1106

    
1107
        case VirtualMachine::HOLD:
1108
            if (vm->hasHistory())
1109
            {
1110
                vm->set_action(History::DELETE_RECREATE_ACTION, ra.uid, ra.gid,
1111
                        ra.req_id);
1112
                vmpool->update_history(vm);
1113
            }
1114

    
1115
            // Automatic requirements are not recalculated on purpose
1116

    
1117
            vm->set_state(VirtualMachine::LCM_INIT);
1118
            vm->set_state(VirtualMachine::PENDING);
1119

    
1120
            vmpool->update(vm);
1121
        break;
1122

    
1123
        case VirtualMachine::ACTIVE: //Cleanup VM resources before PENDING
1124
            lcm->trigger(LCMAction::DELETE_RECREATE, vm->get_oid(), ra);
1125
        break;
1126

    
1127
        case VirtualMachine::DONE:
1128
            error = "Cannot delete-recreate a VM already in DONE state";
1129
            NebulaLog::log("DiM", Log::ERROR, error);
1130
            rc = -1;
1131
        break;
1132
    }
1133

    
1134
    vm->unlock();
1135

    
1136
    if ( !ds_quotas_snp.empty() )
1137
    {
1138
        Quotas::ds_del_recreate(vm_uid, vm_gid, ds_quotas_snp);
1139
    }
1140

    
1141
    if ( !ds_quotas_rsz.empty() )
1142
    {
1143
        Quotas::ds_del_recreate(vm_uid, vm_gid, ds_quotas_rsz);
1144
    }
1145

    
1146
    if ( vm_quotas_snp != 0 )
1147
    {
1148
        Quotas::vm_del(vm_uid, vm_gid, vm_quotas_snp);
1149

    
1150
        delete vm_quotas_snp;
1151
    }
1152

    
1153
    if ( vm_quotas_rsz != 0 )
1154
    {
1155
        Quotas::vm_del(vm_uid, vm_gid, vm_quotas_rsz);
1156

    
1157
        delete vm_quotas_rsz;
1158
    }
1159

    
1160
    return rc;
1161
}
1162

    
1163
/* -------------------------------------------------------------------------- */
1164
/* -------------------------------------------------------------------------- */
1165

    
1166
int DispatchManager::attach(int vid, VirtualMachineTemplate * tmpl,
1167
        const RequestAttributes& ra, string & err)
1168
{
1169
    ostringstream oss;
1170

    
1171
    VirtualMachine * vm = vmpool->get(vid, true);
1172

    
1173
    if ( vm == 0 )
1174
    {
1175
        oss << "Could not attach a new disk to VM " << vid
1176
            << ", VM does not exist" ;
1177
        err = oss.str();
1178

    
1179
        NebulaLog::log("DiM", Log::ERROR, err);
1180

    
1181
        return -1;
1182
    }
1183

    
1184
    if ( vm->get_state()     == VirtualMachine::ACTIVE &&
1185
         vm->get_lcm_state() == VirtualMachine::RUNNING )
1186
    {
1187
        vm->set_state(VirtualMachine::HOTPLUG);
1188
    }
1189
    else if ( vm->get_state() == VirtualMachine::POWEROFF )
1190
    {
1191
        vm->set_state(VirtualMachine::ACTIVE);
1192
        vm->set_state(VirtualMachine::HOTPLUG_PROLOG_POWEROFF);
1193
    }
1194
    else
1195
    {
1196
        oss << "Could not attach a new disk to VM " << vid << ", wrong state "
1197
            << vm->state_str() << ".";
1198
        err = oss.str();
1199

    
1200
        NebulaLog::log("DiM", Log::ERROR, err);
1201

    
1202
        vm->unlock();
1203
        return -1;
1204
    }
1205

    
1206
    vm->set_resched(false);
1207

    
1208
    if ( vm->set_up_attach_disk(tmpl, err) != 0 )
1209
    {
1210
        if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1211
        {
1212
            vm->set_state(VirtualMachine::RUNNING);
1213
        }
1214
        else
1215
        {
1216
            vm->set_state(VirtualMachine::LCM_INIT);
1217
            vm->set_state(VirtualMachine::POWEROFF);
1218
        }
1219

    
1220
        vmpool->update(vm);
1221

    
1222
        vm->unlock();
1223

    
1224
        NebulaLog::log("DiM", Log::ERROR, err);
1225
        return -1;
1226
    }
1227

    
1228
    if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1229
    {
1230
        time_t the_time = time(0);
1231

    
1232
        // Close current history record
1233

    
1234
        vm->set_running_etime(the_time);
1235

    
1236
        vm->set_etime(the_time);
1237

    
1238
        vm->set_action(History::DISK_ATTACH_ACTION, ra.uid, ra.gid, ra.req_id);
1239

    
1240
        vmpool->update_history(vm);
1241

    
1242
        // Open a new history record
1243

    
1244
        vm->cp_history();
1245

    
1246
        vm->set_stime(the_time);
1247

    
1248
        vm->set_running_stime(the_time);
1249

    
1250
        vmpool->update_history(vm);
1251

    
1252
        //-----------------------------------------------
1253

    
1254
        vmm->trigger(VMMAction::ATTACH, vid);
1255
    }
1256
    else
1257
    {
1258
        tm->trigger(TMAction::PROLOG_ATTACH, vid);
1259
    }
1260

    
1261
    vmpool->update(vm);
1262

    
1263
    vm->unlock();
1264

    
1265
    return 0;
1266
}
1267

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

    
1271
int DispatchManager::detach(int vid, int disk_id, const RequestAttributes& ra,
1272
        string&  error_str)
1273
{
1274
    ostringstream oss;
1275

    
1276
    VirtualMachine * vm = vmpool->get(vid, true);
1277

    
1278
    if ( vm == 0 )
1279
    {
1280
        oss << "VirtualMachine " << vid << " no longer exists";
1281
        error_str = oss.str();
1282

    
1283
        NebulaLog::log("DiM", Log::ERROR, error_str);
1284
        return -1;
1285
    }
1286

    
1287
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1288
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1289
        vm->get_state()       != VirtualMachine::POWEROFF)
1290
    {
1291
        oss << "Could not detach disk from VM " << vid << ", wrong state "
1292
            << vm->state_str() << ".";
1293
        error_str = oss.str();
1294

    
1295
        NebulaLog::log("DiM", Log::ERROR, error_str);
1296

    
1297
        vm->unlock();
1298
        return -1;
1299
    }
1300

    
1301
    if ( vm->set_attach_disk(disk_id) == -1 )
1302
    {
1303
        oss << "Could not detach disk with DISK_ID " << disk_id
1304
            << ", it does not exist.";
1305
        error_str = oss.str();
1306

    
1307
        NebulaLog::log("DiM", Log::ERROR, error_str);
1308

    
1309
        vm->unlock();
1310
        return -1;
1311
    }
1312

    
1313
    vm->set_resched(false);
1314

    
1315
    if ( vm->get_state() == VirtualMachine::ACTIVE &&
1316
         vm->get_lcm_state() == VirtualMachine::RUNNING )
1317
    {
1318
        time_t the_time = time(0);
1319

    
1320
        // Close current history record
1321

    
1322
        vm->set_vm_info();
1323

    
1324
        vm->set_running_etime(the_time);
1325

    
1326
        vm->set_etime(the_time);
1327

    
1328
        vm->set_action(History::DISK_DETACH_ACTION, ra.uid, ra.gid, ra.req_id);
1329

    
1330
        vmpool->update_history(vm);
1331

    
1332
        // Open a new history record
1333

    
1334
        vm->cp_history();
1335

    
1336
        vm->set_stime(the_time);
1337

    
1338
        vm->set_running_stime(the_time);
1339

    
1340
        vmpool->update_history(vm);
1341

    
1342
        //---------------------------------------------------
1343

    
1344
        vm->set_state(VirtualMachine::HOTPLUG);
1345

    
1346
        vmm->trigger(VMMAction::DETACH, vid);
1347
    }
1348
    else
1349
    {
1350
        vm->set_state(VirtualMachine::ACTIVE);
1351
        vm->set_state(VirtualMachine::HOTPLUG_EPILOG_POWEROFF);
1352

    
1353
        tm->trigger(TMAction::EPILOG_DETACH, vid);
1354
    }
1355

    
1356
    vmpool->update(vm);
1357

    
1358
    vm->unlock();
1359

    
1360
    return 0;
1361
}
1362

    
1363
/* -------------------------------------------------------------------------- */
1364
/* -------------------------------------------------------------------------- */
1365

    
1366
int DispatchManager::snapshot_create(int vid, string& name, int& snap_id,
1367
        const RequestAttributes& ra, string& error_str)
1368
{
1369
    ostringstream oss;
1370

    
1371
    VirtualMachine * vm = vmpool->get(vid, true);
1372

    
1373
    if ( vm == 0 )
1374
    {
1375
        oss << "Could not create a new snapshot for VM " << vid
1376
            << ", VM does not exist" ;
1377
        error_str = oss.str();
1378

    
1379
        NebulaLog::log("DiM", Log::ERROR, error_str);
1380

    
1381
        return -1;
1382
    }
1383

    
1384
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1385
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1386
    {
1387
        oss << "Could not create a new snapshot for VM " << vid
1388
            << ", wrong state " << vm->state_str() << ".";
1389
        error_str = oss.str();
1390

    
1391
        NebulaLog::log("DiM", Log::ERROR, error_str);
1392

    
1393
        vm->unlock();
1394
        return -1;
1395
    }
1396

    
1397
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1398

    
1399
    vm->set_resched(false);
1400

    
1401
    vm->new_snapshot(name, snap_id);
1402

    
1403
    vmpool->update(vm);
1404

    
1405
    vm->unlock();
1406

    
1407
    vmm->trigger(VMMAction::SNAPSHOT_CREATE, vid);
1408

    
1409
    return 0;
1410
}
1411

    
1412
/* -------------------------------------------------------------------------- */
1413
/* -------------------------------------------------------------------------- */
1414

    
1415
int DispatchManager::snapshot_revert(int vid, int snap_id,
1416
        const RequestAttributes& ra, string& error_str)
1417
{
1418
    ostringstream oss;
1419

    
1420
    int rc;
1421

    
1422
    VirtualMachine * vm = vmpool->get(vid, true);
1423

    
1424
    if ( vm == 0 )
1425
    {
1426
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1427
            << ", VM does not exist" ;
1428
        error_str = oss.str();
1429

    
1430
        NebulaLog::log("DiM", Log::ERROR, error_str);
1431

    
1432
        return -1;
1433
    }
1434

    
1435
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1436
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1437
    {
1438
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1439
            << ", wrong state " << vm->state_str() << ".";
1440
        error_str = oss.str();
1441

    
1442
        NebulaLog::log("DiM", Log::ERROR, error_str);
1443

    
1444
        vm->unlock();
1445
        return -1;
1446
    }
1447

    
1448
    rc = vm->set_revert_snapshot(snap_id);
1449

    
1450
    if ( rc == -1 )
1451
    {
1452
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1453
            << ", it does not exist.";
1454
        error_str = oss.str();
1455

    
1456
        NebulaLog::log("DiM", Log::ERROR, error_str);
1457

    
1458
        vm->unlock();
1459
        return -1;
1460
    }
1461

    
1462
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1463

    
1464
    vm->set_resched(false);
1465

    
1466
    vmpool->update(vm);
1467

    
1468
    vm->unlock();
1469

    
1470
    vmm->trigger(VMMAction::SNAPSHOT_REVERT, vid);
1471

    
1472
    return 0;
1473
}
1474

    
1475
/* -------------------------------------------------------------------------- */
1476
/* -------------------------------------------------------------------------- */
1477

    
1478
int DispatchManager::snapshot_delete(int vid, int snap_id,
1479
        const RequestAttributes& ra,string& error_str)
1480
{
1481
    ostringstream oss;
1482

    
1483
    int rc;
1484

    
1485
    VirtualMachine * vm = vmpool->get(vid, true);
1486

    
1487
    if ( vm == 0 )
1488
    {
1489
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1490
            << ", VM does not exist" ;
1491
        error_str = oss.str();
1492

    
1493
        NebulaLog::log("DiM", Log::ERROR, error_str);
1494

    
1495
        return -1;
1496
    }
1497

    
1498
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1499
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1500
    {
1501
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1502
            << ", wrong state " << vm->state_str() << ".";
1503
        error_str = oss.str();
1504

    
1505
        NebulaLog::log("DiM", Log::ERROR, error_str);
1506

    
1507
        vm->unlock();
1508
        return -1;
1509
    }
1510

    
1511
    rc = vm->set_delete_snapshot(snap_id);
1512

    
1513
    if ( rc == -1 )
1514
    {
1515
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1516
            << ", it does not exist.";
1517
        error_str = oss.str();
1518

    
1519
        NebulaLog::log("DiM", Log::ERROR, error_str);
1520

    
1521
        vm->unlock();
1522
        return -1;
1523
    }
1524

    
1525
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1526

    
1527
    vm->set_resched(false);
1528

    
1529
    vmpool->update(vm);
1530

    
1531
    vm->unlock();
1532

    
1533
    vmm->trigger(VMMAction::SNAPSHOT_DELETE, vid);
1534

    
1535
    return 0;
1536
}
1537

    
1538
/* -------------------------------------------------------------------------- */
1539
/* -------------------------------------------------------------------------- */
1540

    
1541
int DispatchManager::attach_nic(int vid, VirtualMachineTemplate* tmpl,
1542
        const RequestAttributes& ra, string& error_str)
1543
{
1544
    ostringstream oss;
1545

    
1546
    VirtualMachine * vm = vmpool->get(vid, true);
1547

    
1548
    if ( vm == 0 )
1549
    {
1550
        oss << "Could not add a new NIC to VM " << vid
1551
            << ", VM does not exist" ;
1552
        error_str = oss.str();
1553

    
1554
        NebulaLog::log("DiM", Log::ERROR, error_str);
1555

    
1556
        return -1;
1557
    }
1558

    
1559
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1560
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1561
        vm->get_state()       != VirtualMachine::POWEROFF )
1562
    {
1563
        oss << "Could not add a new NIC to VM " << vid << ", wrong state "
1564
            << vm->state_str() << ".";
1565
        error_str = oss.str();
1566

    
1567
        NebulaLog::log("DiM", Log::ERROR, error_str);
1568

    
1569
        vm->unlock();
1570
        return -1;
1571
    }
1572

    
1573
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1574
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1575
    {
1576
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1577
    }
1578

    
1579
    vm->set_resched(false);
1580

    
1581
    if ( vm->set_up_attach_nic(tmpl, error_str) != 0 )
1582
    {
1583
        if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1584
        {
1585
            vm->set_state(VirtualMachine::RUNNING);
1586
        }
1587

    
1588
        vmpool->update(vm);
1589

    
1590
        vm->unlock();
1591

    
1592
        NebulaLog::log("DiM", Log::ERROR, error_str);
1593

    
1594
        return -1;
1595
    }
1596

    
1597
    if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1598
    {
1599
        time_t the_time = time(0);
1600

    
1601
        // Close current history record
1602

    
1603
        vm->set_running_etime(the_time);
1604

    
1605
        vm->set_etime(the_time);
1606

    
1607
        vm->set_action(History::NIC_ATTACH_ACTION, ra.uid, ra.gid, ra.req_id);
1608

    
1609
        vmpool->update_history(vm);
1610

    
1611
        // Open a new history record
1612

    
1613
        vm->cp_history();
1614

    
1615
        vm->set_stime(the_time);
1616

    
1617
        vm->set_running_stime(the_time);
1618

    
1619
        vmpool->update_history(vm);
1620

    
1621
        //-----------------------------------------------
1622

    
1623
        vmm->trigger(VMMAction::ATTACH_NIC, vid);
1624
    }
1625
    else
1626
    {
1627
        vm->log("DiM", Log::INFO, "VM NIC Successfully attached.");
1628

    
1629
        vm->clear_attach_nic();
1630
    }
1631

    
1632
    vmpool->update(vm);
1633

    
1634
    vm->unlock();
1635

    
1636
    return 0;
1637
}
1638

    
1639
/* -------------------------------------------------------------------------- */
1640
/* -------------------------------------------------------------------------- */
1641

    
1642
int DispatchManager::detach_nic(int vid, int nic_id,const RequestAttributes& ra,
1643
        string&  error_str)
1644
{
1645
    ostringstream oss;
1646
    string        tmp_error;
1647

    
1648
    VirtualMachine * vm = vmpool->get(vid, true);
1649

    
1650
    if ( vm == 0 )
1651
    {
1652
        oss << "VirtualMachine " << vid << " no longer exists";
1653
        error_str = oss.str();
1654

    
1655
        NebulaLog::log("DiM", Log::ERROR, error_str);
1656
        return -1;
1657
    }
1658

    
1659
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1660
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1661
        vm->get_state()       != VirtualMachine::POWEROFF )
1662
    {
1663
        oss << "Could not detach NIC from VM " << vid << ", wrong state "
1664
            << vm->state_str() << ".";
1665
        error_str = oss.str();
1666

    
1667
        NebulaLog::log("DiM", Log::ERROR, error_str);
1668

    
1669
        vm->unlock();
1670
        return -1;
1671
    }
1672

    
1673
    if ( vm->set_detach_nic(nic_id) == -1 )
1674
    {
1675
        oss << "Could not detach NIC with NIC_ID " << nic_id
1676
            << ", it does not exist.";
1677
        error_str = oss.str();
1678

    
1679
        NebulaLog::log("DiM", Log::ERROR, error_str);
1680

    
1681
        vm->unlock();
1682
        return -1;
1683
    }
1684

    
1685
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1686
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1687
    {
1688
        time_t the_time = time(0);
1689

    
1690
        // Close current history record
1691

    
1692
        vm->set_vm_info();
1693

    
1694
        vm->set_running_etime(the_time);
1695

    
1696
        vm->set_etime(the_time);
1697

    
1698
        vm->set_action(History::NIC_DETACH_ACTION, ra.uid, ra.gid, ra.req_id);
1699

    
1700
        vmpool->update_history(vm);
1701

    
1702
        // Open a new history record
1703

    
1704
        vm->cp_history();
1705

    
1706
        vm->set_stime(the_time);
1707

    
1708
        vm->set_running_stime(the_time);
1709

    
1710
        vmpool->update_history(vm);
1711

    
1712
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1713

    
1714
        vm->set_resched(false);
1715

    
1716
        vmpool->update(vm);
1717

    
1718
        vm->unlock();
1719

    
1720
        //---------------------------------------------------
1721

    
1722
        vmm->trigger(VMMAction::DETACH_NIC, vid);
1723
    }
1724
    else
1725
    {
1726
        vm->log("DiM", Log::INFO, "VM NIC Successfully detached.");
1727

    
1728
        vmpool->update(vm);
1729

    
1730
        vm->unlock();
1731

    
1732
        vmpool->detach_nic_success(vid);
1733
    }
1734

    
1735
    return 0;
1736
}
1737

    
1738
/* -------------------------------------------------------------------------- */
1739
/* -------------------------------------------------------------------------- */
1740

    
1741
int DispatchManager::disk_snapshot_create(int vid, int did, const string& name,
1742
        int& snap_id, const RequestAttributes& ra, string& error_str)
1743
{
1744
    ostringstream oss;
1745
    time_t        the_time;
1746

    
1747
    VirtualMachine * vm = vmpool->get(vid, true);
1748

    
1749
    if ( vm == 0 )
1750
    {
1751
        oss << "Could not create a new disk snapshot for VM " << vid
1752
            << ", VM does not exist" ;
1753
        error_str = oss.str();
1754

    
1755
        NebulaLog::log("DiM", Log::ERROR, error_str);
1756

    
1757
        return -1;
1758
    }
1759

    
1760
    VirtualMachine::VmState  state  = vm->get_state();
1761
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1762

    
1763
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1764
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1765
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1766
    {
1767
        oss << "Could not create a new snapshot for VM " << vid
1768
            << ", wrong state " << vm->state_str() << ".";
1769
        error_str = oss.str();
1770

    
1771
        NebulaLog::log("DiM", Log::ERROR, error_str);
1772

    
1773
        vm->unlock();
1774

    
1775
        return -1;
1776
    }
1777

    
1778
    // Set the VM info in the history before the snapshot is added to VM
1779
    vm->set_vm_info();
1780

    
1781
    snap_id = vm->new_disk_snapshot(did, name, error_str);
1782

    
1783
    if (snap_id == -1)
1784
    {
1785
        vm->unlock();
1786
        return -1;
1787
    }
1788

    
1789
    switch(state)
1790
    {
1791
        case VirtualMachine::POWEROFF:
1792
            vm->set_state(VirtualMachine::ACTIVE);
1793
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF);
1794
            break;
1795

    
1796
        case VirtualMachine::SUSPENDED:
1797
            vm->set_state(VirtualMachine::ACTIVE);
1798
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_SUSPENDED);
1799
            break;
1800

    
1801
        case VirtualMachine::ACTIVE:
1802
            vm->set_state(VirtualMachine::ACTIVE);
1803
            vm->set_state(VirtualMachine::DISK_SNAPSHOT);
1804
            break;
1805

    
1806
        default: break;
1807
    }
1808

    
1809
    switch(state)
1810
    {
1811
        case VirtualMachine::POWEROFF:
1812
        case VirtualMachine::SUSPENDED:
1813
            tm->trigger(TMAction::SNAPSHOT_CREATE, vid);
1814
            break;
1815

    
1816
        case VirtualMachine::ACTIVE:
1817
            the_time = time(0);
1818

    
1819
            // Close current history record
1820

    
1821
            vm->set_running_etime(the_time);
1822

    
1823
            vm->set_etime(the_time);
1824

    
1825
            vm->set_action(History::DISK_SNAPSHOT_CREATE_ACTION, ra.uid, ra.gid,
1826
                    ra.req_id);
1827

    
1828
            vmpool->update_history(vm);
1829

    
1830
            // Open a new history record
1831

    
1832
            vm->cp_history();
1833

    
1834
            vm->set_stime(the_time);
1835

    
1836
            vm->set_running_stime(the_time);
1837

    
1838
            vmpool->update_history(vm);
1839

    
1840
            vmm->trigger(VMMAction::DISK_SNAPSHOT_CREATE, vid);
1841
            break;
1842

    
1843
        default: break;
1844
    }
1845

    
1846
    vmpool->update(vm);
1847

    
1848
    vm->unlock();
1849

    
1850
    return 0;
1851
}
1852

    
1853
/* -------------------------------------------------------------------------- */
1854
/* -------------------------------------------------------------------------- */
1855

    
1856
int DispatchManager::disk_snapshot_revert(int vid, int did, int snap_id,
1857
        const RequestAttributes& ra, string& error_str)
1858
{
1859
    ostringstream oss;
1860

    
1861
    VirtualMachine * vm = vmpool->get(vid, true);
1862

    
1863
    if ( vm == 0 )
1864
    {
1865
        oss << "Could not revert to disk snapshot for VM " << vid
1866
            << ", VM does not exist" ;
1867
        error_str = oss.str();
1868

    
1869
        NebulaLog::log("DiM", Log::ERROR, error_str);
1870

    
1871
        return -1;
1872
    }
1873

    
1874
    VirtualMachine::VmState  state  = vm->get_state();
1875
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1876

    
1877
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1878
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT))
1879
    {
1880
        oss << "Could not revert to disk snapshot for VM " << vid
1881
            << ", wrong state " << vm->state_str() << ".";
1882
        error_str = oss.str();
1883

    
1884
        NebulaLog::log("DiM", Log::ERROR, error_str);
1885

    
1886
        vm->unlock();
1887
        return -1;
1888
    }
1889

    
1890
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1891

    
1892
    if (snaps == 0)
1893
    {
1894
        vm->unlock();
1895
        return -1;
1896
    }
1897

    
1898
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1899
    {
1900
        vm->unlock();
1901
        return -1;
1902
    }
1903

    
1904
    switch(state)
1905
    {
1906
        case VirtualMachine::POWEROFF:
1907
            vm->set_state(VirtualMachine::ACTIVE);
1908
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF);
1909
            break;
1910

    
1911
        case VirtualMachine::SUSPENDED:
1912
            vm->set_state(VirtualMachine::ACTIVE);
1913
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_SUSPENDED);
1914
            break;
1915

    
1916
        default: break;
1917
    }
1918

    
1919
    vmpool->update(vm);
1920

    
1921
    vm->unlock();
1922

    
1923
    tm->trigger(TMAction::SNAPSHOT_REVERT, vid);
1924

    
1925
    return 0;
1926
}
1927

    
1928
/* -------------------------------------------------------------------------- */
1929
/* -------------------------------------------------------------------------- */
1930

    
1931
int DispatchManager::disk_snapshot_delete(int vid, int did, int snap_id,
1932
        const RequestAttributes& ra, string& error_str)
1933
{
1934
    ostringstream oss;
1935
    time_t        the_time;
1936

    
1937
    VirtualMachine * vm = vmpool->get(vid, true);
1938

    
1939
    if ( vm == 0 )
1940
    {
1941
        oss << "Could not delete disk snapshot from VM " << vid
1942
            << ", VM does not exist" ;
1943
        error_str = oss.str();
1944

    
1945
        NebulaLog::log("DiM", Log::ERROR, error_str);
1946

    
1947
        return -1;
1948
    }
1949

    
1950
    VirtualMachine::VmState  state  = vm->get_state();
1951
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1952

    
1953
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1954
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1955
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1956
    {
1957
        oss << "Could not delete disk snapshot from VM " << vid
1958
            << ", wrong state " << vm->state_str() << ".";
1959
        error_str = oss.str();
1960

    
1961
        NebulaLog::log("DiM", Log::ERROR, error_str);
1962

    
1963
        vm->unlock();
1964
        return -1;
1965
    }
1966

    
1967
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1968

    
1969
    if (snaps == 0)
1970
    {
1971
        vm->unlock();
1972
        return -1;
1973
    }
1974

    
1975
    if (!snaps->test_delete(snap_id, error_str))
1976
    {
1977
        vm->unlock();
1978
        return -1;
1979
    }
1980

    
1981
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1982
    {
1983
        vm->unlock();
1984
        return -1;
1985
    }
1986

    
1987
    // Set the VM info in the history before the snapshot is removed from the VM
1988
    vm->set_vm_info();
1989

    
1990
    switch(state)
1991
    {
1992
        case VirtualMachine::POWEROFF:
1993
            vm->set_state(VirtualMachine::ACTIVE);
1994
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF);
1995
            break;
1996

    
1997
        case VirtualMachine::SUSPENDED:
1998
            vm->set_state(VirtualMachine::ACTIVE);
1999
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_SUSPENDED);
2000
            break;
2001

    
2002
        case VirtualMachine::ACTIVE:
2003
            vm->set_state(VirtualMachine::ACTIVE);
2004
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE);
2005
            break;
2006

    
2007
        default: break;
2008
    }
2009

    
2010
    switch(state)
2011
    {
2012
        case VirtualMachine::ACTIVE:
2013
            the_time = time(0);
2014

    
2015
            // Close current history record
2016

    
2017
            vm->set_running_etime(the_time);
2018

    
2019
            vm->set_etime(the_time);
2020

    
2021
            vm->set_action(History::DISK_SNAPSHOT_DELETE_ACTION, ra.uid, ra.gid,
2022
                    ra.req_id);
2023

    
2024
            vmpool->update_history(vm);
2025

    
2026
            // Open a new history record
2027

    
2028
            vm->cp_history();
2029

    
2030
            vm->set_stime(the_time);
2031

    
2032
            vm->set_running_stime(the_time);
2033

    
2034
            vmpool->update_history(vm);
2035

    
2036
        case VirtualMachine::POWEROFF:
2037
        case VirtualMachine::SUSPENDED:
2038
            tm->trigger(TMAction::SNAPSHOT_DELETE, vid);
2039
            break;
2040

    
2041
        default: break;
2042
    }
2043

    
2044
    vmpool->update(vm);
2045

    
2046
    vm->unlock();
2047

    
2048
    return 0;
2049
}
2050

    
2051
/* -------------------------------------------------------------------------- */
2052
/* -------------------------------------------------------------------------- */
2053

    
2054
int DispatchManager::disk_resize(int vid, int did, long long new_size,
2055
        const RequestAttributes& ra, string& error_str)
2056
{
2057
    ostringstream oss;
2058
    time_t        the_time;
2059

    
2060
    VirtualMachine * vm = vmpool->get(vid, true);
2061

    
2062
    if ( vm == 0 )
2063
    {
2064
        oss << "Could not resize disk for VM " << vid << ", VM does not exist" ;
2065
        error_str = oss.str();
2066

    
2067
        NebulaLog::log("DiM", Log::ERROR, error_str);
2068
        return -1;
2069
    }
2070

    
2071
    VirtualMachine::VmState  state  = vm->get_state();
2072
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
2073

    
2074
    if ((state!=VirtualMachine::POWEROFF  || lstate!=VirtualMachine::LCM_INIT)&&
2075
        (state!=VirtualMachine::UNDEPLOYED|| lstate!=VirtualMachine::LCM_INIT)&&
2076
        (state!=VirtualMachine::ACTIVE    || lstate!=VirtualMachine::RUNNING))
2077
    {
2078
        oss << "Could not resize disk for VM " << vid << ", wrong state "
2079
            << vm->state_str() << ".";
2080
        error_str = oss.str();
2081

    
2082
        NebulaLog::log("DiM", Log::ERROR, error_str);
2083

    
2084
        vm->unlock();
2085

    
2086
        return -1;
2087
    }
2088

    
2089
    // Set the VM info in the history before the disk is resized
2090
    vm->set_vm_info();
2091

    
2092
    int rc = vm->set_up_resize_disk(did, new_size, error_str);
2093

    
2094
    if (rc == -1)
2095
    {
2096
        vm->unlock();
2097
        return -1;
2098
    }
2099

    
2100
    switch(state)
2101
    {
2102
        case VirtualMachine::POWEROFF:
2103
            vm->set_state(VirtualMachine::ACTIVE);
2104
            vm->set_state(VirtualMachine::DISK_RESIZE_POWEROFF);
2105
            break;
2106

    
2107
        case VirtualMachine::UNDEPLOYED:
2108
            vm->set_state(VirtualMachine::ACTIVE);
2109
            vm->set_state(VirtualMachine::DISK_RESIZE_UNDEPLOYED);
2110
            break;
2111

    
2112
        case VirtualMachine::ACTIVE:
2113
            vm->set_state(VirtualMachine::ACTIVE);
2114
            vm->set_state(VirtualMachine::DISK_RESIZE);
2115
            break;
2116

    
2117
        default: break;
2118
    }
2119

    
2120
    switch(state)
2121
    {
2122
        case VirtualMachine::POWEROFF:
2123
        case VirtualMachine::UNDEPLOYED:
2124
            tm->trigger(TMAction::RESIZE, vid);
2125
            break;
2126

    
2127
        case VirtualMachine::ACTIVE:
2128
            the_time = time(0);
2129

    
2130
            // Close current history record
2131

    
2132
            vm->set_running_etime(the_time);
2133

    
2134
            vm->set_etime(the_time);
2135

    
2136
            vm->set_action(History::DISK_RESIZE_ACTION, ra.uid, ra.gid,
2137
                    ra.req_id);
2138

    
2139
            vmpool->update_history(vm);
2140

    
2141
            // Open a new history record
2142

    
2143
            vm->cp_history();
2144

    
2145
            vm->set_stime(the_time);
2146

    
2147
            vm->set_running_stime(the_time);
2148

    
2149
            vmpool->update_history(vm);
2150

    
2151
            vmm->trigger(VMMAction::DISK_RESIZE, vid);
2152
            break;
2153

    
2154
        default: break;
2155
    }
2156

    
2157
    vmpool->update(vm);
2158

    
2159
    vm->unlock();
2160

    
2161
    return 0;
2162
}
2163

    
2164
/* -------------------------------------------------------------------------- */
2165
/* -------------------------------------------------------------------------- */