Statistics
| Branch: | Tag: | Revision:

one / src / dm / DispatchManagerActions.cc @ f22ca784

History | View | Annotate | Download (46.4 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs        */
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

    
25
/* -------------------------------------------------------------------------- */
26
/* -------------------------------------------------------------------------- */
27

    
28
int DispatchManager::deploy (
29
    VirtualMachine *    vm)
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(LifeCycleManager::DEPLOY,vid);
54
    }
55
    else
56
    {
57
        goto error;
58
    }
59

    
60
    vm->unlock();
61

    
62
    return 0;
63

    
64
error:
65

    
66
    oss.str("");
67
    oss << "Could not deploy VM " << vid << ", wrong state.";
68
    NebulaLog::log("DiM",Log::ERROR,oss);
69

    
70
    vm->unlock();
71
    return -1;
72
}
73

    
74
/* -------------------------------------------------------------------------- */
75
/* -------------------------------------------------------------------------- */
76

    
77
int DispatchManager::import (
78
    VirtualMachine *    vm)
79
{
80
    ostringstream oss;
81

    
82
    if ( vm == 0 )
83
    {
84
        return -1;
85
    }
86

    
87
    if ( vm->get_state() != VirtualMachine::PENDING &&
88
         vm->get_state() != VirtualMachine::HOLD )
89
    {
90
        return -1;
91
    }
92

    
93
    time_t the_time = time(0);
94
    int    cpu, mem, disk;
95

    
96
    vm->get_requirements(cpu, mem, disk);
97

    
98
    hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
99

    
100
    vm->set_state(VirtualMachine::ACTIVE);
101

    
102
    vm->set_state(VirtualMachine::RUNNING);
103

    
104
    vmpool->update(vm);
105

    
106
    vm->set_stime(the_time);
107

    
108
    vm->set_prolog_stime(the_time);
109
    vm->set_prolog_etime(the_time);
110

    
111
    vm->set_running_stime(the_time);
112

    
113
    vm->set_last_poll(0);
114

    
115
    vmpool->update_history(vm);
116

    
117
    vm->unlock();
118

    
119
    return 0;
120
}
121

    
122
/* -------------------------------------------------------------------------- */
123
/* -------------------------------------------------------------------------- */
124

    
125
int DispatchManager::migrate(
126
    VirtualMachine *    vm)
127
{
128
    ostringstream oss;
129
    int           vid;
130

    
131
    if ( vm == 0 )
132
    {
133
        return -1;
134
    }
135

    
136
    vid = vm->get_oid();
137

    
138
    oss << "Migrating VM " << vid;
139
    NebulaLog::log("DiM",Log::DEBUG,oss);
140

    
141
    if ((vm->get_state()     == VirtualMachine::ACTIVE &&
142
         (vm->get_lcm_state() == VirtualMachine::RUNNING ||
143
          vm->get_lcm_state() == VirtualMachine::UNKNOWN )) ||
144
         vm->get_state() == VirtualMachine::POWEROFF ||
145
         vm->get_state() == VirtualMachine::SUSPENDED)
146
    {
147
        lcm->trigger(LifeCycleManager::MIGRATE,vid);
148
    }
149
    else
150
    {
151
        goto error;
152
    }
153

    
154
    vm->unlock();
155

    
156
    return 0;
157

    
158
error:
159
    oss.str("");
160
    oss << "Could not migrate VM " << vid << ", wrong state.";
161
    NebulaLog::log("DiM",Log::ERROR,oss);
162

    
163
    vm->unlock();
164
    return -1;
165
}
166

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

    
170
int DispatchManager::live_migrate(
171
    VirtualMachine *    vm)
172
{
173
    ostringstream oss;
174
    int           vid;
175

    
176
    if ( vm == 0 )
177
    {
178
        return -1;
179
    }
180

    
181
    vid = vm->get_oid();
182

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

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

    
196
    vm->unlock();
197

    
198
    return 0;
199

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

    
205
    vm->unlock();
206
    return -1;
207
}
208

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

    
212
int DispatchManager::shutdown (
213
        int     vid,
214
        bool    hard,
215
        string& error_str)
216
{
217
    ostringstream oss;
218

    
219
    VirtualMachine * vm = vmpool->get(vid,true);
220

    
221
    if ( vm == 0 )
222
    {
223
        return -1;
224
    }
225

    
226
    oss << "Shutting down VM " << vid;
227
    NebulaLog::log("DiM",Log::DEBUG,oss);
228

    
229
    if (vm->get_state()     == VirtualMachine::POWEROFF ||
230
        vm->get_state()     == VirtualMachine::SUSPENDED ||
231
       (vm->get_state()     == VirtualMachine::ACTIVE &&
232
        (vm->get_lcm_state() == VirtualMachine::RUNNING ||
233
         vm->get_lcm_state() == VirtualMachine::UNKNOWN)))
234
    {
235
        if (hard)
236
        {
237
            lcm->trigger(LifeCycleManager::CANCEL,vid);
238
        }
239
        else
240
        {
241
            lcm->trigger(LifeCycleManager::SHUTDOWN,vid);
242
        }
243
    }
244
    else
245
    {
246
        goto error;
247
    }
248

    
249
    vm->unlock();
250

    
251
    return 0;
252

    
253
error:
254
    oss.str("");
255
    oss << "Could not shutdown VM " << vid << ", wrong state.";
256
    NebulaLog::log("DiM",Log::ERROR,oss);
257

    
258
    oss.str("");
259
    oss << "This action is not available for state " << vm->state_str();
260
    error_str = oss.str();
261

    
262
    vm->unlock();
263
    return -2;
264
}
265

    
266
/* -------------------------------------------------------------------------- */
267
/* -------------------------------------------------------------------------- */
268

    
269
int DispatchManager::undeploy(
270
    int     vid,
271
    bool    hard,
272
    string& error_str)
273
{
274
    ostringstream oss;
275

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

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

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

    
286
    if ( vm->get_state()       == VirtualMachine::POWEROFF ||
287
         (vm->get_state()       == VirtualMachine::ACTIVE &&
288
           (vm->get_lcm_state() == VirtualMachine::RUNNING ||
289
            vm->get_lcm_state() == VirtualMachine::UNKNOWN)))
290
    {
291
        if (hard)
292
        {
293
            lcm->trigger(LifeCycleManager::UNDEPLOY_HARD,vid);
294
        }
295
        else
296
        {
297
            lcm->trigger(LifeCycleManager::UNDEPLOY,vid);
298
        }
299
    }
300
    else
301
    {
302
        goto error;
303
    }
304

    
305
    vm->unlock();
306

    
307
    return 0;
308

    
309
error:
310
    oss.str("");
311
    oss << "Could not undeploy VM " << vid << ", wrong state.";
312
    NebulaLog::log("DiM",Log::ERROR,oss);
313

    
314
    oss.str("");
315
    oss << "This action is not available for state " << vm->state_str();
316
    error_str = oss.str();
317

    
318
    vm->unlock();
319
    return -2;
320
}
321

    
322
/* -------------------------------------------------------------------------- */
323
/* -------------------------------------------------------------------------- */
324

    
325
int DispatchManager::poweroff (
326
    int     vid,
327
    bool    hard,
328
    string& error_str)
329
{
330
    ostringstream oss;
331

    
332
    VirtualMachine * vm = vmpool->get(vid,true);
333

    
334
    if ( vm == 0 )
335
    {
336
        return -1;
337
    }
338

    
339
    oss << "Powering off VM " << vid;
340
    NebulaLog::log("DiM",Log::DEBUG,oss);
341

    
342
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
343
        (vm->get_lcm_state() == VirtualMachine::RUNNING ||
344
         vm->get_lcm_state() == VirtualMachine::UNKNOWN))
345
    {
346
        if (hard)
347
        {
348
            lcm->trigger(LifeCycleManager::POWEROFF_HARD,vid);
349
        }
350
        else
351
        {
352
            lcm->trigger(LifeCycleManager::POWEROFF,vid);
353
        }
354
    }
355
    else
356
    {
357
        goto error;
358
    }
359

    
360
    vm->unlock();
361

    
362
    return 0;
363

    
364
error:
365

    
366
    oss.str("");
367
    oss << "Could not power off VM " << vid << ", wrong state.";
368
    NebulaLog::log("DiM",Log::ERROR,oss);
369

    
370
    oss.str("");
371
    oss << "This action is not available for state " << vm->state_str();
372
    error_str = oss.str();
373

    
374
    vm->unlock();
375
    return -2;
376
}
377

    
378
/* -------------------------------------------------------------------------- */
379
/* -------------------------------------------------------------------------- */
380

    
381
int DispatchManager::hold(
382
    int     vid,
383
    string& error_str)
384
{
385
    ostringstream oss;
386

    
387
    VirtualMachine * vm = vmpool->get(vid,true);
388

    
389
    if ( vm == 0 )
390
    {
391
        return -1;
392
    }
393

    
394
    oss << "Holding VM " << vid;
395
    NebulaLog::log("DiM",Log::DEBUG,oss);
396

    
397
    if (vm->get_state() == VirtualMachine::PENDING)
398
    {
399
        vm->set_state(VirtualMachine::HOLD);
400

    
401
        vmpool->update(vm);
402
    }
403
    else
404
    {
405
        goto error;
406
    }
407

    
408
    vm->unlock();
409

    
410
    return 0;
411

    
412
error:
413

    
414
    oss.str("");
415
    oss << "Could not hold VM " << vid << ", wrong state.";
416
    NebulaLog::log("DiM",Log::ERROR,oss);
417

    
418
    oss.str("");
419
    oss << "This action is not available for state " << vm->state_str();
420
    error_str = oss.str();
421

    
422
    vm->unlock();
423
    return -2;
424
}
425

    
426
/* -------------------------------------------------------------------------- */
427
/* -------------------------------------------------------------------------- */
428

    
429
int DispatchManager::release(
430
    int     vid,
431
    string& error_str)
432
{
433
    ostringstream oss;
434

    
435
    VirtualMachine * vm = vmpool->get(vid,true);
436

    
437
    if ( vm == 0 )
438
    {
439
        return -1;
440
    }
441

    
442
    oss << "Releasing VM " << vid;
443
    NebulaLog::log("DiM",Log::DEBUG,oss);
444

    
445
    if (vm->get_state() == VirtualMachine::HOLD)
446
    {
447
        vm->set_state(VirtualMachine::PENDING);
448

    
449
        vmpool->update(vm);
450
    }
451
    else
452
    {
453
        goto error;
454
    }
455

    
456
    vm->unlock();
457

    
458
    return 0;
459

    
460
error:
461
    oss.str("");
462
    oss << "Could not release VM " << vid << ", wrong state.";
463
    NebulaLog::log("DiM",Log::ERROR,oss);
464

    
465
    oss.str("");
466
    oss << "This action is not available for state " << vm->state_str();
467
    error_str = oss.str();
468

    
469
    vm->unlock();
470
    return -2;
471
}
472

    
473
/* -------------------------------------------------------------------------- */
474
/* -------------------------------------------------------------------------- */
475

    
476
int DispatchManager::stop(
477
    int     vid,
478
    string& error_str)
479
{
480
    ostringstream oss;
481

    
482
    VirtualMachine * vm = vmpool->get(vid,true);
483

    
484
    if ( vm == 0 )
485
    {
486
        return -1;
487
    }
488

    
489
    oss << "Stopping VM " << vid;
490
    NebulaLog::log("DiM",Log::DEBUG,oss);
491

    
492
    if (vm->get_state()        == VirtualMachine::SUSPENDED ||
493
        (vm->get_state()       == VirtualMachine::ACTIVE &&
494
         vm->get_lcm_state() == VirtualMachine::RUNNING ))
495
    {
496
        lcm->trigger(LifeCycleManager::STOP,vid);
497
    }
498
    else
499
    {
500
        goto error;
501
    }
502

    
503
    vm->unlock();
504

    
505
    return 0;
506

    
507
error:
508
    oss.str("");
509
    oss << "Could not stop VM " << vid << ", wrong state.";
510
    NebulaLog::log("DiM",Log::ERROR,oss);
511

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

    
516
    vm->unlock();
517
    return -2;
518
}
519

    
520
/* -------------------------------------------------------------------------- */
521
/* -------------------------------------------------------------------------- */
522

    
523
int DispatchManager::suspend(
524
    int     vid,
525
    string& error_str)
526
{
527
    ostringstream oss;
528

    
529
    VirtualMachine * vm = vmpool->get(vid,true);
530

    
531
    if ( vm == 0 )
532
    {
533
        return -1;
534
    }
535

    
536
    oss << "Suspending VM " << vid;
537
    NebulaLog::log("DiM",Log::DEBUG,oss);
538

    
539
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
540
        vm->get_lcm_state() == VirtualMachine::RUNNING )
541
    {
542
        lcm->trigger(LifeCycleManager::SUSPEND,vid);
543
    }
544
    else
545
    {
546
        goto error;
547
    }
548

    
549
    vm->unlock();
550

    
551
    return 0;
552

    
553
error:
554
    oss.str("");
555
    oss << "Could not suspend VM " << vid << ", wrong state.";
556
    NebulaLog::log("DiM",Log::ERROR,oss);
557

    
558
    oss.str("");
559
    oss << "This action is not available for state " << vm->state_str();
560
    error_str = oss.str();
561

    
562
    vm->unlock();
563
    return -2;
564
}
565

    
566
/* -------------------------------------------------------------------------- */
567
/* -------------------------------------------------------------------------- */
568

    
569
int DispatchManager::resume(
570
    int     vid,
571
    string& error_str)
572
{
573
    ostringstream oss;
574

    
575
    VirtualMachine * vm = vmpool->get(vid,true);
576

    
577
    if ( vm == 0 )
578
    {
579
        return -1;
580
    }
581

    
582
    oss << "Resuming VM " << vid;
583
    NebulaLog::log("DiM",Log::DEBUG,oss);
584

    
585
    if (vm->get_state() == VirtualMachine::STOPPED ||
586
        vm->get_state() == VirtualMachine::UNDEPLOYED )
587
    {
588
        vm->set_state(VirtualMachine::PENDING);
589

    
590
        vmpool->update(vm);
591
    }
592
    else if (vm->get_state() == VirtualMachine::SUSPENDED)
593
    {
594
        lcm->trigger(LifeCycleManager::RESTORE,vid);
595
    }
596
    else if ( vm->get_state() == VirtualMachine::POWEROFF ||
597
             (vm->get_state() == VirtualMachine::ACTIVE &&
598
              vm->get_lcm_state() == VirtualMachine::UNKNOWN))
599
    {
600
        lcm->trigger(LifeCycleManager::RESTART,vid);
601
    }
602
    else
603
    {
604
        goto error;
605
    }
606

    
607
    vm->unlock();
608

    
609
    return 0;
610

    
611
error:
612
    oss.str("");
613
    oss << "Could not resume VM " << vid << ", wrong state.";
614
    NebulaLog::log("DiM",Log::ERROR,oss);
615

    
616
    oss.str("");
617
    oss << "This action is not available for state " << vm->state_str();
618
    error_str = oss.str();
619

    
620
    vm->unlock();
621
    return -2;
622
}
623

    
624
/* -------------------------------------------------------------------------- */
625
/* -------------------------------------------------------------------------- */
626

    
627
int DispatchManager::reboot(
628
    int     vid,
629
    bool    hard,
630
    string& error_str)
631
{
632
    ostringstream oss;
633

    
634
    VirtualMachine * vm = vmpool->get(vid,true);
635

    
636
    if ( vm == 0 )
637
    {
638
        return -1;
639
    }
640

    
641
    oss << "Rebooting VM " << vid;
642
    NebulaLog::log("DiM",Log::DEBUG,oss);
643

    
644
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
645
        vm->get_lcm_state() == VirtualMachine::RUNNING )
646
    {
647
        if (hard)
648
        {
649
            vmm->trigger(VirtualMachineManager::RESET,vid);
650
        }
651
        else
652
        {
653
            vmm->trigger(VirtualMachineManager::REBOOT,vid);
654
        }
655

    
656
        vm->set_resched(false); //Rebooting cancels re-scheduling actions
657

    
658
        vmpool->update(vm);
659
    }
660
    else
661
    {
662
        goto error;
663
    }
664

    
665
    vm->unlock();
666

    
667
    return 0;
668

    
669
error:
670
    oss.str("");
671
    oss << "Could not reboot VM " << vid << ", wrong state.";
672
    NebulaLog::log("DiM",Log::ERROR,oss);
673

    
674
    oss.str("");
675
    oss << "This action is not available for state " << vm->state_str();
676
    error_str = oss.str();
677

    
678
    vm->unlock();
679

    
680
    return -2;
681
}
682

    
683
/* -------------------------------------------------------------------------- */
684
/* -------------------------------------------------------------------------- */
685

    
686
int DispatchManager::resched(
687
    int     vid,
688
    bool    do_resched,
689
    string& error_str)
690
{
691
    ostringstream oss;
692

    
693
    VirtualMachine * vm = vmpool->get(vid,true);
694

    
695
    if ( vm == 0 )
696
    {
697
        return -1;
698
    }
699

    
700
    oss << "Setting rescheduling flag on VM " << vid;
701
    NebulaLog::log("DiM",Log::DEBUG,oss);
702

    
703
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
704
        (vm->get_lcm_state() == VirtualMachine::RUNNING ||
705
         vm->get_lcm_state() == VirtualMachine::UNKNOWN))
706
    {
707
        vm->set_resched(do_resched);
708
        vmpool->update(vm);
709
    }
710
    else
711
    {
712
        goto error;
713
    }
714

    
715
    vm->unlock();
716

    
717
    return 0;
718

    
719
error:
720
    oss.str("");
721
    oss << "Could not set rescheduling flag for VM " << vid << ", wrong state.";
722
    NebulaLog::log("DiM",Log::ERROR,oss);
723

    
724
    oss.str("");
725
    oss << "This action is not available for state " << vm->state_str();
726
    error_str = oss.str();
727

    
728
    vm->unlock();
729

    
730
    return -2;
731
}
732

    
733
/* -------------------------------------------------------------------------- */
734
/* -------------------------------------------------------------------------- */
735

    
736
void DispatchManager::finalize_cleanup(VirtualMachine * vm)
737
{
738
    Template *    tmpl;
739

    
740
    int uid;
741
    int gid;
742

    
743
    vm->release_network_leases();
744
    vm->release_disk_images();
745

    
746
    vm->set_exit_time(time(0));
747

    
748
    vm->set_state(VirtualMachine::LCM_INIT);
749
    vm->set_state(VirtualMachine::DONE);
750
    vmpool->update(vm);
751

    
752
    uid  = vm->get_uid();
753
    gid  = vm->get_gid();
754
    tmpl = vm->clone_template();
755

    
756
    vm->unlock();
757

    
758
    Quotas::vm_del(uid, gid, tmpl);
759

    
760
    delete tmpl;
761
}
762

    
763
/* -------------------------------------------------------------------------- */
764
/* -------------------------------------------------------------------------- */
765

    
766
int DispatchManager::finalize(
767
    int     vid,
768
    string& error_str)
769
{
770
    VirtualMachine * vm;
771
    Host * host;
772
    ostringstream oss;
773

    
774
    VirtualMachine::VmState state;
775
    bool is_public_host;
776

    
777
    vm   = vmpool->get(vid,true);
778

    
779
    host           = hpool->get(vm->get_hid(),true);
780
    is_public_host = host->is_public_cloud();
781
    host->unlock();
782
    
783

    
784
    if ( vm == 0 )
785
    {
786
        return -1;
787
    }
788

    
789
    state = vm->get_state();
790

    
791
    oss << "Finalizing VM " << vid;
792
    NebulaLog::log("DiM",Log::DEBUG,oss);
793

    
794
    switch (state)
795
    {
796
        case VirtualMachine::SUSPENDED:
797
        case VirtualMachine::POWEROFF:
798
            int cpu, mem, disk;
799

    
800
            vm->get_requirements(cpu,mem,disk);
801
            hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
802

    
803
            if (is_public_host)
804
            {
805
                vmm->trigger(VirtualMachineManager::CLEANUP,vid);
806
            }
807
            else
808
            {
809
                tm->trigger(TransferManager::EPILOG_DELETE,vid);
810
            }
811

    
812
            finalize_cleanup(vm);
813
        break;
814

    
815
        case VirtualMachine::STOPPED:
816
        case VirtualMachine::UNDEPLOYED:
817
            if (is_public_host)
818
            {
819
                vmm->trigger(VirtualMachineManager::CLEANUP,vid);
820
            }
821
            else
822
            {
823
                tm->trigger(TransferManager::EPILOG_DELETE,vid);
824
            }
825

    
826
            finalize_cleanup(vm);
827
        break;
828

    
829
        case VirtualMachine::INIT:
830
        case VirtualMachine::PENDING:
831
        case VirtualMachine::HOLD:
832
            finalize_cleanup(vm);
833
        break;
834

    
835
        case VirtualMachine::ACTIVE:
836
            lcm->trigger(LifeCycleManager::DELETE,vid);
837
            vm->unlock();
838
        break;
839

    
840
        case VirtualMachine::DONE:
841
            vm->unlock();
842
        break;
843
    }
844

    
845
    return 0;
846
}
847

    
848
/* -------------------------------------------------------------------------- */
849
/* -------------------------------------------------------------------------- */
850

    
851
int DispatchManager::resubmit(
852
    int     vid,
853
    string& error_str)
854
{
855
    VirtualMachine * vm;
856
    ostringstream    oss;
857
    int              rc = 0;
858

    
859
    vm = vmpool->get(vid,true);
860

    
861
    if ( vm == 0 )
862
    {
863
        return -1;
864
    }
865

    
866
    switch (vm->get_state())
867
    {
868
        case VirtualMachine::POWEROFF:
869
            error_str = "Cannot delete-recreate a powered off VM. Resume it first";
870
            NebulaLog::log("DiM",Log::ERROR,error_str);
871
            rc = -2;
872
        break;
873

    
874
        case VirtualMachine::SUSPENDED:
875
            error_str = "Cannot delete-recreate a suspended VM. Resume it first";
876
            NebulaLog::log("DiM",Log::ERROR,error_str);
877
            rc = -2;
878
        break;
879

    
880
        case VirtualMachine::INIT: // No need to do nothing here
881
        case VirtualMachine::PENDING:
882
        break;
883

    
884
        case VirtualMachine::HOLD: // Move the VM to PENDING in any of these
885
        case VirtualMachine::STOPPED:
886
        case VirtualMachine::UNDEPLOYED:
887
            if (vm->hasHistory())
888
            {
889
                vm->set_action(History::DELETE_RECREATE_ACTION);
890
                vmpool->update_history(vm);
891
            }
892

    
893
            vm->set_state(VirtualMachine::LCM_INIT);
894
            vm->set_state(VirtualMachine::PENDING);
895

    
896
            vmpool->update(vm);
897
        break;
898

    
899
        case VirtualMachine::ACTIVE: //Cleanup VM resources before PENDING
900
            lcm->trigger(LifeCycleManager::CLEAN, vid);
901
        break;
902

    
903
        case VirtualMachine::DONE:
904
            error_str = "Cannot delete-recreate a VM already in DONE state";
905
            NebulaLog::log("DiM",Log::ERROR,error_str);
906
            rc = -2;
907
        break;
908
    }
909

    
910
    vm->unlock();
911

    
912
    return rc;
913
}
914

    
915
/* -------------------------------------------------------------------------- */
916
/* -------------------------------------------------------------------------- */
917

    
918
int DispatchManager::attach(int vid,
919
                            VirtualMachineTemplate * tmpl,
920
                            string &                 error_str)
921
{
922
    ostringstream oss;
923

    
924
    int max_disk_id;
925
    int uid;
926
    int oid;
927
    int image_id;
928
    int image_cluster_id;
929

    
930
    set<string>       used_targets;
931
    VectorAttribute * disk;
932
    Snapshots *       snap;
933

    
934
    VirtualMachine * vm = vmpool->get(vid, true);
935

    
936
    if ( vm == 0 )
937
    {
938
        oss << "Could not attach a new disk to VM " << vid
939
            << ", VM does not exist" ;
940
        error_str = oss.str();
941

    
942
        NebulaLog::log("DiM", Log::ERROR, error_str);
943

    
944
        return -1;
945
    }
946

    
947
    if ( vm->get_state()     == VirtualMachine::ACTIVE &&
948
         vm->get_lcm_state() == VirtualMachine::RUNNING )
949
    {
950
        vm->set_state(VirtualMachine::HOTPLUG);
951
    }
952
    else if ( vm->get_state() == VirtualMachine::POWEROFF )
953
    {
954
        vm->set_state(VirtualMachine::ACTIVE);
955
        vm->set_state(VirtualMachine::HOTPLUG_PROLOG_POWEROFF);
956
    }
957
    else
958
    {
959
        oss << "Could not attach a new disk to VM " << vid << ", wrong state "
960
            << vm->state_str() << ".";
961
        error_str = oss.str();
962

    
963
        NebulaLog::log("DiM", Log::ERROR, error_str);
964

    
965
        vm->unlock();
966
        return -1;
967
    }
968

    
969
    vm->get_disk_info(max_disk_id, used_targets);
970

    
971
    vm->set_resched(false);
972

    
973
    uid = vm->get_uid();
974
    oid = vm->get_oid();
975

    
976
    vmpool->update(vm);
977

    
978
    vm->unlock();
979

    
980
    disk = VirtualMachine::set_up_attach_disk(oid,
981
                                              tmpl,
982
                                              used_targets,
983
                                              max_disk_id,
984
                                              uid,
985
                                              image_id,
986
                                              &snap,
987
                                              error_str);
988
    vm = vmpool->get(vid, true);
989

    
990
    if ( vm == 0 )
991
    {
992
                if ( disk != 0 )
993
                {
994
                        imagem->release_image(oid, image_id, false);
995

    
996
                        delete snap;
997
                        delete disk;
998
                }
999

    
1000
        error_str = "VM does not exist after setting its state to HOTPLUG.";
1001

    
1002
        NebulaLog::log("DiM", Log::ERROR, error_str);
1003
        return -1;
1004
    }
1005

    
1006
    if ( disk == 0 )
1007
    {
1008
        if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1009
        {
1010
            vm->set_state(VirtualMachine::RUNNING);
1011
        }
1012
        else
1013
        {
1014
            vm->set_state(VirtualMachine::LCM_INIT);
1015
            vm->set_state(VirtualMachine::POWEROFF);
1016
        }
1017

    
1018
        vmpool->update(vm);
1019

    
1020
        vm->unlock();
1021

    
1022
        NebulaLog::log("DiM", Log::ERROR, error_str);
1023
        return -1;
1024
    }
1025

    
1026
    // Check that we don't have a cluster incompatibility.
1027
    if (disk->vector_value("CLUSTER_ID", image_cluster_id) == 0)
1028
    {
1029
      if (vm->get_cid() != image_cluster_id)
1030
      {
1031
          imagem->release_image(oid, image_id, false);
1032

    
1033
          delete snap;
1034
          delete disk;
1035

    
1036
          if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1037
          {
1038
              vm->set_state(VirtualMachine::RUNNING);
1039
          }
1040
          else
1041
          {
1042
              vm->set_state(VirtualMachine::LCM_INIT);
1043
              vm->set_state(VirtualMachine::POWEROFF);
1044
          }
1045

    
1046
          vmpool->update(vm);
1047

    
1048
          vm->unlock();
1049

    
1050
          error_str = "Could not attach disk because of cluster incompatibility.";
1051

    
1052
          NebulaLog::log("DiM", Log::ERROR, error_str);
1053
          return -1;
1054
      }
1055
    }
1056

    
1057
    // Set the VM info in the history before the disk is attached to the
1058
    // VM template
1059
    vm->set_vm_info();
1060

    
1061
    vm->set_attach_disk(disk, snap);
1062

    
1063
    if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1064
    {
1065
        time_t the_time = time(0);
1066

    
1067
        // Close current history record
1068

    
1069
        vm->set_running_etime(the_time);
1070

    
1071
        vm->set_etime(the_time);
1072

    
1073
        vm->set_action(History::DISK_ATTACH_ACTION);
1074
        vm->set_reason(History::USER);
1075

    
1076
        vmpool->update_history(vm);
1077

    
1078
        // Open a new history record
1079

    
1080
        vm->cp_history();
1081

    
1082
        vm->set_stime(the_time);
1083

    
1084
        vm->set_running_stime(the_time);
1085

    
1086
        vmpool->update_history(vm);
1087

    
1088
        //-----------------------------------------------
1089

    
1090
        vmm->trigger(VirtualMachineManager::ATTACH,vid);
1091
    }
1092
    else
1093
    {
1094
        tm->trigger(TransferManager::PROLOG_ATTACH, vid);
1095
    }
1096

    
1097
    vmpool->update(vm);
1098

    
1099
    vm->unlock();
1100

    
1101
    return 0;
1102
}
1103

    
1104
/* -------------------------------------------------------------------------- */
1105
/* -------------------------------------------------------------------------- */
1106

    
1107
int DispatchManager::detach(
1108
    int      vid,
1109
    int      disk_id,
1110
    string&  error_str)
1111
{
1112
    ostringstream oss;
1113

    
1114
    VirtualMachine * vm = vmpool->get(vid, true);
1115

    
1116
    if ( vm == 0 )
1117
    {
1118
        oss << "VirtualMachine " << vid << " no longer exists";
1119
        error_str = oss.str();
1120

    
1121
        NebulaLog::log("DiM", Log::ERROR, error_str);
1122
        return -1;
1123
    }
1124

    
1125
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1126
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1127
        vm->get_state()       != VirtualMachine::POWEROFF)
1128
    {
1129
        oss << "Could not detach disk from VM " << vid << ", wrong state "
1130
            << vm->state_str() << ".";
1131
        error_str = oss.str();
1132

    
1133
        NebulaLog::log("DiM", Log::ERROR, error_str);
1134

    
1135
        vm->unlock();
1136
        return -1;
1137
    }
1138

    
1139
    if ( vm->set_attach_disk(disk_id) == -1 )
1140
    {
1141
        oss << "Could not detach disk with DISK_ID " << disk_id
1142
            << ", it does not exist.";
1143
        error_str = oss.str();
1144

    
1145
        NebulaLog::log("DiM", Log::ERROR, error_str);
1146

    
1147
        vm->unlock();
1148
        return -1;
1149
    }
1150

    
1151
    vm->set_resched(false);
1152

    
1153
    if ( vm->get_state() == VirtualMachine::ACTIVE &&
1154
         vm->get_lcm_state() == VirtualMachine::RUNNING )
1155
    {
1156
        time_t the_time = time(0);
1157

    
1158
        // Close current history record
1159

    
1160
        vm->set_vm_info();
1161

    
1162
        vm->set_running_etime(the_time);
1163

    
1164
        vm->set_etime(the_time);
1165

    
1166
        vm->set_action(History::DISK_DETACH_ACTION);
1167
        vm->set_reason(History::USER);
1168

    
1169
        vmpool->update_history(vm);
1170

    
1171
        // Open a new history record
1172

    
1173
        vm->cp_history();
1174

    
1175
        vm->set_stime(the_time);
1176

    
1177
        vm->set_running_stime(the_time);
1178

    
1179
        vmpool->update_history(vm);
1180

    
1181
        //---------------------------------------------------
1182

    
1183
        vm->set_state(VirtualMachine::HOTPLUG);
1184

    
1185
        vmm->trigger(VirtualMachineManager::DETACH,vid);
1186
    }
1187
    else
1188
    {
1189
        vm->set_state(VirtualMachine::ACTIVE);
1190
        vm->set_state(VirtualMachine::HOTPLUG_EPILOG_POWEROFF);
1191

    
1192
        tm->trigger(TransferManager::EPILOG_DETACH, vid);
1193
    }
1194

    
1195
    vmpool->update(vm);
1196

    
1197
    vm->unlock();
1198

    
1199
    return 0;
1200
}
1201

    
1202
/* -------------------------------------------------------------------------- */
1203
/* -------------------------------------------------------------------------- */
1204

    
1205
int DispatchManager::snapshot_create(
1206
    int     vid,
1207
    string& name,
1208
    int&    snap_id,
1209
    string& error_str)
1210
{
1211
    ostringstream oss;
1212

    
1213
    VirtualMachine * vm = vmpool->get(vid, true);
1214

    
1215
    if ( vm == 0 )
1216
    {
1217
        oss << "Could not create a new snapshot for VM " << vid
1218
            << ", VM does not exist" ;
1219
        error_str = oss.str();
1220

    
1221
        NebulaLog::log("DiM", Log::ERROR, error_str);
1222

    
1223
        return -1;
1224
    }
1225

    
1226
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1227
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1228
    {
1229
        oss << "Could not create a new snapshot for VM " << vid
1230
            << ", wrong state " << vm->state_str() << ".";
1231
        error_str = oss.str();
1232

    
1233
        NebulaLog::log("DiM", Log::ERROR, error_str);
1234

    
1235
        vm->unlock();
1236
        return -1;
1237
    }
1238

    
1239
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1240

    
1241
    vm->set_resched(false);
1242

    
1243
    vm->new_snapshot(name, snap_id);
1244

    
1245
    vmpool->update(vm);
1246

    
1247
    vm->unlock();
1248

    
1249
    vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
1250

    
1251
    return 0;
1252
}
1253

    
1254
/* -------------------------------------------------------------------------- */
1255
/* -------------------------------------------------------------------------- */
1256

    
1257
int DispatchManager::snapshot_revert(
1258
    int         vid,
1259
    int         snap_id,
1260
    string&     error_str)
1261
{
1262
    ostringstream oss;
1263

    
1264
    int rc;
1265

    
1266
    VirtualMachine * vm = vmpool->get(vid, true);
1267

    
1268
    if ( vm == 0 )
1269
    {
1270
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1271
            << ", VM does not exist" ;
1272
        error_str = oss.str();
1273

    
1274
        NebulaLog::log("DiM", Log::ERROR, error_str);
1275

    
1276
        return -1;
1277
    }
1278

    
1279
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1280
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1281
    {
1282
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1283
            << ", wrong state " << vm->state_str() << ".";
1284
        error_str = oss.str();
1285

    
1286
        NebulaLog::log("DiM", Log::ERROR, error_str);
1287

    
1288
        vm->unlock();
1289
        return -1;
1290
    }
1291

    
1292

    
1293
    rc = vm->set_active_snapshot(snap_id);
1294

    
1295
    if ( rc == -1 )
1296
    {
1297
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1298
            << ", it does not exist.";
1299
        error_str = oss.str();
1300

    
1301
        NebulaLog::log("DiM", Log::ERROR, error_str);
1302

    
1303
        vm->unlock();
1304
        return -1;
1305
    }
1306

    
1307
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1308

    
1309
    vm->set_resched(false);
1310

    
1311
    vmpool->update(vm);
1312

    
1313
    vm->unlock();
1314

    
1315
    vmm->trigger(VirtualMachineManager::SNAPSHOT_REVERT,vid);
1316

    
1317
    return 0;
1318
}
1319

    
1320
/* -------------------------------------------------------------------------- */
1321
/* -------------------------------------------------------------------------- */
1322

    
1323
int DispatchManager::snapshot_delete(
1324
    int         vid,
1325
    int         snap_id,
1326
    string&     error_str)
1327
{
1328
    ostringstream oss;
1329

    
1330
    int rc;
1331

    
1332
    VirtualMachine * vm = vmpool->get(vid, true);
1333

    
1334
    if ( vm == 0 )
1335
    {
1336
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1337
            << ", VM does not exist" ;
1338
        error_str = oss.str();
1339

    
1340
        NebulaLog::log("DiM", Log::ERROR, error_str);
1341

    
1342
        return -1;
1343
    }
1344

    
1345
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1346
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1347
    {
1348
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1349
            << ", wrong state " << vm->state_str() << ".";
1350
        error_str = oss.str();
1351

    
1352
        NebulaLog::log("DiM", Log::ERROR, error_str);
1353

    
1354
        vm->unlock();
1355
        return -1;
1356
    }
1357

    
1358
    rc = vm->set_active_snapshot(snap_id);
1359

    
1360
    if ( rc == -1 )
1361
    {
1362
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1363
            << ", it does not exist.";
1364
        error_str = oss.str();
1365

    
1366
        NebulaLog::log("DiM", Log::ERROR, error_str);
1367

    
1368
        vm->unlock();
1369
        return -1;
1370
    }
1371

    
1372
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1373

    
1374
    vm->set_resched(false);
1375

    
1376
    vmpool->update(vm);
1377

    
1378
    vm->unlock();
1379

    
1380
    vmm->trigger(VirtualMachineManager::SNAPSHOT_DELETE,vid);
1381

    
1382
    return 0;
1383
}
1384

    
1385
/* -------------------------------------------------------------------------- */
1386
/* -------------------------------------------------------------------------- */
1387

    
1388
int DispatchManager::attach_nic(
1389
        int                     vid,
1390
        VirtualMachineTemplate* tmpl,
1391
        string &                error_str)
1392
{
1393
    ostringstream oss;
1394

    
1395
    int max_nic_id;
1396
    int uid;
1397
    int oid;
1398
    int rc;
1399

    
1400
    set<int> vm_sgs;
1401

    
1402
    VectorAttribute *        nic;
1403
    vector<VectorAttribute*> sg_rules;
1404

    
1405
    VirtualMachine * vm = vmpool->get(vid, true);
1406

    
1407
    if ( vm == 0 )
1408
    {
1409
        oss << "Could not add a new NIC to VM " << vid
1410
            << ", VM does not exist" ;
1411
        error_str = oss.str();
1412

    
1413
        NebulaLog::log("DiM", Log::ERROR, error_str);
1414

    
1415
        return -1;
1416
    }
1417

    
1418
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1419
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1420
        vm->get_state()       != VirtualMachine::POWEROFF )
1421
    {
1422
        oss << "Could not add a new NIC to VM " << vid << ", wrong state "
1423
            << vm->state_str() << ".";
1424
        error_str = oss.str();
1425

    
1426
        NebulaLog::log("DiM", Log::ERROR, error_str);
1427

    
1428
        vm->unlock();
1429
        return -1;
1430
    }
1431

    
1432
    nic = vm->get_attach_nic_info(tmpl, max_nic_id, error_str);
1433

    
1434
    if ( nic == 0 )
1435
    {
1436
        vm->unlock();
1437

    
1438
        NebulaLog::log("DiM", Log::ERROR, error_str);
1439
        return -1;
1440
    }
1441

    
1442
    vm->get_security_groups(vm_sgs);
1443

    
1444
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1445
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1446
    {
1447
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1448
    }
1449

    
1450
    vm->set_resched(false);
1451

    
1452
    uid = vm->get_uid();
1453
    oid = vm->get_oid();
1454

    
1455
    vmpool->update(vm);
1456

    
1457
    vm->unlock();
1458

    
1459
    rc = VirtualMachine::set_up_attach_nic(oid,
1460
                                    vm_sgs,
1461
                                    nic,
1462
                                    sg_rules,
1463
                                    max_nic_id,
1464
                                    uid,
1465
                                    error_str);
1466
    vm = vmpool->get(vid, true);
1467

    
1468
    if ( vm == 0 )
1469
    {
1470
        delete nic;
1471

    
1472
        if ( rc == 0 )
1473
        {
1474
            VirtualMachine::release_network_leases(nic, vid);
1475

    
1476
            vector<VectorAttribute*>::iterator it;
1477
            for(it = sg_rules.begin(); it != sg_rules.end(); it++)
1478
            {
1479
                delete *it;
1480
            }
1481
        }
1482

    
1483
        oss << "Could not attach a new NIC to VM " << vid
1484
            << ", VM does not exist after setting its state to HOTPLUG." ;
1485
        error_str = oss.str();
1486

    
1487
        NebulaLog::log("DiM", Log::ERROR, error_str);
1488

    
1489
        return -1;
1490
    }
1491

    
1492
    if ( rc != 0 )
1493
    {
1494
        delete nic;
1495

    
1496
        vector<VectorAttribute*>::iterator it;
1497
        for(it = sg_rules.begin(); it != sg_rules.end(); it++)
1498
        {
1499
            delete *it;
1500
        }
1501

    
1502
        if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1503
        {
1504
            vm->set_state(VirtualMachine::RUNNING);
1505
        }
1506

    
1507
        vmpool->update(vm);
1508

    
1509
        vm->unlock();
1510

    
1511
        NebulaLog::log("DiM", Log::ERROR, error_str);
1512

    
1513
        return -1;
1514
    }
1515

    
1516
    // Set the VM info in the history before the nic is attached to the
1517
    // VM template
1518
    vm->set_vm_info();
1519

    
1520
    vm->set_attach_nic(nic, sg_rules);
1521

    
1522
    if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1523
    {
1524
        time_t the_time = time(0);
1525

    
1526
        // Close current history record
1527

    
1528
        vm->set_running_etime(the_time);
1529

    
1530
        vm->set_etime(the_time);
1531

    
1532
        vm->set_action(History::NIC_ATTACH_ACTION);
1533
        vm->set_reason(History::USER);
1534

    
1535
        vmpool->update_history(vm);
1536

    
1537
        // Open a new history record
1538

    
1539
        vm->cp_history();
1540

    
1541
        vm->set_stime(the_time);
1542

    
1543
        vm->set_running_stime(the_time);
1544

    
1545
        vmpool->update_history(vm);
1546

    
1547
        //-----------------------------------------------
1548

    
1549
        vmm->trigger(VirtualMachineManager::ATTACH_NIC,vid);
1550
    }
1551
    else
1552
    {
1553
        vm->log("DiM", Log::INFO, "VM NIC Successfully attached.");
1554

    
1555
        vm->clear_attach_nic();
1556
    }
1557

    
1558
    vmpool->update(vm);
1559

    
1560
    vm->unlock();
1561

    
1562
    return 0;
1563
}
1564

    
1565
/* -------------------------------------------------------------------------- */
1566
/* -------------------------------------------------------------------------- */
1567

    
1568
int DispatchManager::detach_nic(
1569
    int      vid,
1570
    int      nic_id,
1571
    string&  error_str)
1572
{
1573
    ostringstream oss;
1574

    
1575
    VirtualMachine * vm = vmpool->get(vid, true);
1576

    
1577
    if ( vm == 0 )
1578
    {
1579
        oss << "VirtualMachine " << vid << " no longer exists";
1580
        error_str = oss.str();
1581

    
1582
        NebulaLog::log("DiM", Log::ERROR, error_str);
1583
        return -1;
1584
    }
1585

    
1586
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1587
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1588
        vm->get_state()       != VirtualMachine::POWEROFF )
1589
    {
1590
        oss << "Could not detach NIC from VM " << vid << ", wrong state "
1591
            << vm->state_str() << ".";
1592
        error_str = oss.str();
1593

    
1594
        NebulaLog::log("DiM", Log::ERROR, error_str);
1595

    
1596
        vm->unlock();
1597
        return -1;
1598
    }
1599

    
1600
    if ( vm->set_attach_nic(nic_id) == -1 )
1601
    {
1602
        oss << "Could not detach NIC with NIC_ID " << nic_id
1603
            << ", it does not exist.";
1604
        error_str = oss.str();
1605

    
1606
        NebulaLog::log("DiM", Log::ERROR, error_str);
1607

    
1608
        vm->unlock();
1609
        return -1;
1610
    }
1611

    
1612
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1613
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1614
    {
1615
        time_t the_time = time(0);
1616

    
1617
        // Close current history record
1618

    
1619
        vm->set_vm_info();
1620

    
1621
        vm->set_running_etime(the_time);
1622

    
1623
        vm->set_etime(the_time);
1624

    
1625
        vm->set_action(History::NIC_DETACH_ACTION);
1626
        vm->set_reason(History::USER);
1627

    
1628
        vmpool->update_history(vm);
1629

    
1630
        // Open a new history record
1631

    
1632
        vm->cp_history();
1633

    
1634
        vm->set_stime(the_time);
1635

    
1636
        vm->set_running_stime(the_time);
1637

    
1638
        vmpool->update_history(vm);
1639

    
1640
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1641

    
1642
        vm->set_resched(false);
1643

    
1644
        vmpool->update(vm);
1645

    
1646
        vm->unlock();
1647

    
1648
        //---------------------------------------------------
1649

    
1650
        vmm->trigger(VirtualMachineManager::DETACH_NIC,vid);
1651
    }
1652
    else
1653
    {
1654
        vm->unlock();
1655

    
1656
        vmpool->delete_attach_nic(vid);
1657

    
1658
        vm->log("DiM", Log::INFO, "VM NIC Successfully detached.");
1659
    }
1660

    
1661
    return 0;
1662
}
1663

    
1664
/* -------------------------------------------------------------------------- */
1665
/* -------------------------------------------------------------------------- */
1666

    
1667
int DispatchManager::disk_snapshot_create(
1668
        int           vid,
1669
        int           did,
1670
        const string& name,
1671
        int&          snap_id,
1672
        string&       error_str)
1673
{
1674
    ostringstream oss;
1675
    time_t        the_time;
1676

    
1677
    VirtualMachine * vm = vmpool->get(vid, true);
1678

    
1679
    if ( vm == 0 )
1680
    {
1681
        oss << "Could not create a new disk snapshot for VM " << vid
1682
            << ", VM does not exist" ;
1683
        error_str = oss.str();
1684

    
1685
        NebulaLog::log("DiM", Log::ERROR, error_str);
1686

    
1687
        return -1;
1688
    }
1689

    
1690
    VirtualMachine::VmState  state  = vm->get_state();
1691
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1692

    
1693
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1694
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1695
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1696
    {
1697
        oss << "Could not create a new snapshot for VM " << vid
1698
            << ", wrong state " << vm->state_str() << ".";
1699
        error_str = oss.str();
1700

    
1701
        NebulaLog::log("DiM", Log::ERROR, error_str);
1702

    
1703
        vm->unlock();
1704

    
1705
        return -1;
1706
    }
1707

    
1708
    // Set the VM info in the history before the snapshot is added to VM
1709
    vm->set_vm_info();
1710

    
1711
    snap_id = vm->new_disk_snapshot(did, name, error_str);
1712

    
1713
    if (snap_id == -1)
1714
    {
1715
        vm->unlock();
1716
        return -1;
1717
    }
1718

    
1719
    switch(state)
1720
    {
1721
        case VirtualMachine::POWEROFF:
1722
            vm->set_state(VirtualMachine::ACTIVE);
1723
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF);
1724
            break;
1725

    
1726
        case VirtualMachine::SUSPENDED:
1727
            vm->set_state(VirtualMachine::ACTIVE);
1728
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_SUSPENDED);
1729
            break;
1730

    
1731
        case VirtualMachine::ACTIVE:
1732
            vm->set_state(VirtualMachine::ACTIVE);
1733
            vm->set_state(VirtualMachine::DISK_SNAPSHOT);
1734
            break;
1735

    
1736
        default: break;
1737
    }
1738

    
1739
    vmpool->update(vm);
1740

    
1741
    vm->unlock();
1742

    
1743
    switch(state)
1744
    {
1745
        case VirtualMachine::POWEROFF:
1746
        case VirtualMachine::SUSPENDED:
1747
            tm->trigger(TransferManager::SNAPSHOT_CREATE,vid);
1748
            break;
1749

    
1750
        case VirtualMachine::ACTIVE:
1751
            the_time = time(0);
1752

    
1753
            // Close current history record
1754

    
1755
            vm->set_running_etime(the_time);
1756

    
1757
            vm->set_etime(the_time);
1758

    
1759
            vm->set_action(History::DISK_SNAPSHOT_CREATE_ACTION);
1760
            vm->set_reason(History::USER);
1761

    
1762
            vmpool->update_history(vm);
1763

    
1764
            // Open a new history record
1765

    
1766
            vm->cp_history();
1767

    
1768
            vm->set_stime(the_time);
1769

    
1770
            vm->set_running_stime(the_time);
1771

    
1772
            vmpool->update_history(vm);
1773

    
1774
            vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_CREATE, vid);
1775
            break;
1776

    
1777
        default: break;
1778
    }
1779

    
1780
    return 0;
1781
}
1782

    
1783
/* -------------------------------------------------------------------------- */
1784
/* -------------------------------------------------------------------------- */
1785

    
1786
int DispatchManager::disk_snapshot_revert(
1787
        int           vid,
1788
        int           did,
1789
        int           snap_id,
1790
        string&       error_str)
1791
{
1792
    ostringstream oss;
1793

    
1794
    VirtualMachine * vm = vmpool->get(vid, true);
1795

    
1796
    if ( vm == 0 )
1797
    {
1798
        oss << "Could not revert to disk snapshot for VM " << vid
1799
            << ", VM does not exist" ;
1800
        error_str = oss.str();
1801

    
1802
        NebulaLog::log("DiM", Log::ERROR, error_str);
1803

    
1804
        return -1;
1805
    }
1806

    
1807
    VirtualMachine::VmState  state  = vm->get_state();
1808
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1809

    
1810
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1811
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1812
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1813
    {
1814
        oss << "Could not revert to disk snapshot for VM " << vid
1815
            << ", wrong state " << vm->state_str() << ".";
1816
        error_str = oss.str();
1817

    
1818
        NebulaLog::log("DiM", Log::ERROR, error_str);
1819

    
1820
        vm->unlock();
1821
        return -1;
1822
    }
1823

    
1824
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1825

    
1826
    if (snaps == 0)
1827
    {
1828
        vm->unlock();
1829
        return -1;
1830
    }
1831

    
1832
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1833
    {
1834
        vm->unlock();
1835
        return -1;
1836
    }
1837

    
1838
    switch(state)
1839
    {
1840
        case VirtualMachine::POWEROFF:
1841
            vm->set_state(VirtualMachine::ACTIVE);
1842
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF);
1843
            break;
1844

    
1845
        case VirtualMachine::SUSPENDED:
1846
            vm->set_state(VirtualMachine::ACTIVE);
1847
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_SUSPENDED);
1848
            break;
1849

    
1850
        case VirtualMachine::ACTIVE:
1851
            vm->set_state(VirtualMachine::ACTIVE);
1852
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT);
1853
            break;
1854

    
1855
        default: break;
1856
    }
1857

    
1858
    vmpool->update(vm);
1859

    
1860
    vm->unlock();
1861

    
1862
    switch(state)
1863
    {
1864
        case VirtualMachine::POWEROFF:
1865
        case VirtualMachine::SUSPENDED:
1866
            tm->trigger(TransferManager::SNAPSHOT_REVERT, vid);
1867
            break;
1868

    
1869
        case VirtualMachine::ACTIVE:
1870
            vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_REVERT, vid);
1871
            break;
1872

    
1873
        default: break;
1874
    }
1875

    
1876
    return 0;
1877
}
1878

    
1879
/* -------------------------------------------------------------------------- */
1880
/* -------------------------------------------------------------------------- */
1881

    
1882
int DispatchManager::disk_snapshot_delete(
1883
        int           vid,
1884
        int           did,
1885
        int           snap_id,
1886
        string&       error_str)
1887
{
1888
    ostringstream oss;
1889
    time_t        the_time;
1890

    
1891
    VirtualMachine * vm = vmpool->get(vid, true);
1892

    
1893
    if ( vm == 0 )
1894
    {
1895
        oss << "Could not delete disk snapshot from VM " << vid
1896
            << ", VM does not exist" ;
1897
        error_str = oss.str();
1898

    
1899
        NebulaLog::log("DiM", Log::ERROR, error_str);
1900

    
1901
        return -1;
1902
    }
1903

    
1904
    VirtualMachine::VmState  state  = vm->get_state();
1905
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1906

    
1907
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1908
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1909
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1910
    {
1911
        oss << "Could not delete disk snapshot from VM " << vid
1912
            << ", wrong state " << vm->state_str() << ".";
1913
        error_str = oss.str();
1914

    
1915
        NebulaLog::log("DiM", Log::ERROR, error_str);
1916

    
1917
        vm->unlock();
1918
        return -1;
1919
    }
1920

    
1921
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1922

    
1923
    if (snaps == 0)
1924
    {
1925
        vm->unlock();
1926
        return -1;
1927
    }
1928

    
1929
    if (!snaps->test_delete(snap_id, error_str))
1930
    {
1931
        vm->unlock();
1932
        return -1;
1933
    }
1934

    
1935
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1936
    {
1937
        vm->unlock();
1938
        return -1;
1939
    }
1940

    
1941
    // Set the VM info in the history before the snapshot is removed from the VM
1942
    vm->set_vm_info();
1943

    
1944
    switch(state)
1945
    {
1946
        case VirtualMachine::POWEROFF:
1947
            vm->set_state(VirtualMachine::ACTIVE);
1948
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF);
1949
            break;
1950

    
1951
        case VirtualMachine::SUSPENDED:
1952
            vm->set_state(VirtualMachine::ACTIVE);
1953
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_SUSPENDED);
1954
            break;
1955

    
1956
        case VirtualMachine::ACTIVE:
1957
            vm->set_state(VirtualMachine::ACTIVE);
1958
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE);
1959
            break;
1960

    
1961
        default: break;
1962
    }
1963

    
1964
    vmpool->update(vm);
1965

    
1966
    vm->unlock();
1967

    
1968
    switch(state)
1969
    {
1970
        case VirtualMachine::ACTIVE:
1971
            the_time = time(0);
1972

    
1973
            // Close current history record
1974

    
1975
            vm->set_running_etime(the_time);
1976

    
1977
            vm->set_etime(the_time);
1978

    
1979
            vm->set_action(History::DISK_SNAPSHOT_DELETE_ACTION);
1980
            vm->set_reason(History::USER);
1981

    
1982
            vmpool->update_history(vm);
1983

    
1984
            // Open a new history record
1985

    
1986
            vm->cp_history();
1987

    
1988
            vm->set_stime(the_time);
1989

    
1990
            vm->set_running_stime(the_time);
1991

    
1992
            vmpool->update_history(vm);
1993

    
1994
        case VirtualMachine::POWEROFF:
1995
        case VirtualMachine::SUSPENDED:
1996
            tm->trigger(TransferManager::SNAPSHOT_DELETE, vid);
1997
            break;
1998

    
1999
        default: break;
2000
    }
2001

    
2002
    return 0;
2003
}
2004