Statistics
| Branch: | Tag: | Revision:

one / src / dm / DispatchManagerActions.cc @ 78317974

History | View | Annotate | Download (46.5 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 = false;
776

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

    
779
    if(vm->hasHistory())
780
    {
781
        host           = hpool->get(vm->get_hid(),true);
782
        is_public_host = host->is_public_cloud();
783
        host->unlock();
784
    }
785

    
786
    if ( vm == 0 )
787
    {
788
        return -1;
789
    }
790

    
791
    state = vm->get_state();
792

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

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

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

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

    
814
            finalize_cleanup(vm);
815
        break;
816

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

    
828
            finalize_cleanup(vm);
829
        break;
830

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

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

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

    
847
    return 0;
848
}
849

    
850
/* -------------------------------------------------------------------------- */
851
/* -------------------------------------------------------------------------- */
852

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

    
861
    vm = vmpool->get(vid,true);
862

    
863
    if ( vm == 0 )
864
    {
865
        return -1;
866
    }
867

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

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

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

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

    
895
            vm->set_state(VirtualMachine::LCM_INIT);
896
            vm->set_state(VirtualMachine::PENDING);
897

    
898
            vmpool->update(vm);
899
        break;
900

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

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

    
912
    vm->unlock();
913

    
914
    return rc;
915
}
916

    
917
/* -------------------------------------------------------------------------- */
918
/* -------------------------------------------------------------------------- */
919

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

    
926
    int max_disk_id;
927
    int uid;
928
    int oid;
929
    int image_id;
930
    int image_cluster_id;
931

    
932
    set<string>       used_targets;
933
    VectorAttribute * disk;
934
    Snapshots *       snap;
935

    
936
    VirtualMachine * vm = vmpool->get(vid, true);
937

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

    
944
        NebulaLog::log("DiM", Log::ERROR, error_str);
945

    
946
        return -1;
947
    }
948

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

    
965
        NebulaLog::log("DiM", Log::ERROR, error_str);
966

    
967
        vm->unlock();
968
        return -1;
969
    }
970

    
971
    vm->get_disk_info(max_disk_id, used_targets);
972

    
973
    vm->set_resched(false);
974

    
975
    uid = vm->get_uid();
976
    oid = vm->get_oid();
977

    
978
    vmpool->update(vm);
979

    
980
    vm->unlock();
981

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

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

    
998
                        delete snap;
999
                        delete disk;
1000
                }
1001

    
1002
        error_str = "VM does not exist after setting its state to HOTPLUG.";
1003

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

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

    
1020
        vmpool->update(vm);
1021

    
1022
        vm->unlock();
1023

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

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

    
1035
          delete snap;
1036
          delete disk;
1037

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

    
1048
          vmpool->update(vm);
1049

    
1050
          vm->unlock();
1051

    
1052
          error_str = "Could not attach disk because of cluster incompatibility.";
1053

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

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

    
1063
    vm->set_attach_disk(disk, snap);
1064

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

    
1069
        // Close current history record
1070

    
1071
        vm->set_running_etime(the_time);
1072

    
1073
        vm->set_etime(the_time);
1074

    
1075
        vm->set_action(History::DISK_ATTACH_ACTION);
1076
        vm->set_reason(History::USER);
1077

    
1078
        vmpool->update_history(vm);
1079

    
1080
        // Open a new history record
1081

    
1082
        vm->cp_history();
1083

    
1084
        vm->set_stime(the_time);
1085

    
1086
        vm->set_running_stime(the_time);
1087

    
1088
        vmpool->update_history(vm);
1089

    
1090
        //-----------------------------------------------
1091

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

    
1099
    vmpool->update(vm);
1100

    
1101
    vm->unlock();
1102

    
1103
    return 0;
1104
}
1105

    
1106
/* -------------------------------------------------------------------------- */
1107
/* -------------------------------------------------------------------------- */
1108

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

    
1116
    VirtualMachine * vm = vmpool->get(vid, true);
1117

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

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

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

    
1135
        NebulaLog::log("DiM", Log::ERROR, error_str);
1136

    
1137
        vm->unlock();
1138
        return -1;
1139
    }
1140

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

    
1147
        NebulaLog::log("DiM", Log::ERROR, error_str);
1148

    
1149
        vm->unlock();
1150
        return -1;
1151
    }
1152

    
1153
    vm->set_resched(false);
1154

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

    
1160
        // Close current history record
1161

    
1162
        vm->set_vm_info();
1163

    
1164
        vm->set_running_etime(the_time);
1165

    
1166
        vm->set_etime(the_time);
1167

    
1168
        vm->set_action(History::DISK_DETACH_ACTION);
1169
        vm->set_reason(History::USER);
1170

    
1171
        vmpool->update_history(vm);
1172

    
1173
        // Open a new history record
1174

    
1175
        vm->cp_history();
1176

    
1177
        vm->set_stime(the_time);
1178

    
1179
        vm->set_running_stime(the_time);
1180

    
1181
        vmpool->update_history(vm);
1182

    
1183
        //---------------------------------------------------
1184

    
1185
        vm->set_state(VirtualMachine::HOTPLUG);
1186

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

    
1194
        tm->trigger(TransferManager::EPILOG_DETACH, vid);
1195
    }
1196

    
1197
    vmpool->update(vm);
1198

    
1199
    vm->unlock();
1200

    
1201
    return 0;
1202
}
1203

    
1204
/* -------------------------------------------------------------------------- */
1205
/* -------------------------------------------------------------------------- */
1206

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

    
1215
    VirtualMachine * vm = vmpool->get(vid, true);
1216

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

    
1223
        NebulaLog::log("DiM", Log::ERROR, error_str);
1224

    
1225
        return -1;
1226
    }
1227

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

    
1235
        NebulaLog::log("DiM", Log::ERROR, error_str);
1236

    
1237
        vm->unlock();
1238
        return -1;
1239
    }
1240

    
1241
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1242

    
1243
    vm->set_resched(false);
1244

    
1245
    vm->new_snapshot(name, snap_id);
1246

    
1247
    vmpool->update(vm);
1248

    
1249
    vm->unlock();
1250

    
1251
    vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
1252

    
1253
    return 0;
1254
}
1255

    
1256
/* -------------------------------------------------------------------------- */
1257
/* -------------------------------------------------------------------------- */
1258

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

    
1266
    int rc;
1267

    
1268
    VirtualMachine * vm = vmpool->get(vid, true);
1269

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

    
1276
        NebulaLog::log("DiM", Log::ERROR, error_str);
1277

    
1278
        return -1;
1279
    }
1280

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

    
1288
        NebulaLog::log("DiM", Log::ERROR, error_str);
1289

    
1290
        vm->unlock();
1291
        return -1;
1292
    }
1293

    
1294

    
1295
    rc = vm->set_active_snapshot(snap_id);
1296

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

    
1303
        NebulaLog::log("DiM", Log::ERROR, error_str);
1304

    
1305
        vm->unlock();
1306
        return -1;
1307
    }
1308

    
1309
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1310

    
1311
    vm->set_resched(false);
1312

    
1313
    vmpool->update(vm);
1314

    
1315
    vm->unlock();
1316

    
1317
    vmm->trigger(VirtualMachineManager::SNAPSHOT_REVERT,vid);
1318

    
1319
    return 0;
1320
}
1321

    
1322
/* -------------------------------------------------------------------------- */
1323
/* -------------------------------------------------------------------------- */
1324

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

    
1332
    int rc;
1333

    
1334
    VirtualMachine * vm = vmpool->get(vid, true);
1335

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

    
1342
        NebulaLog::log("DiM", Log::ERROR, error_str);
1343

    
1344
        return -1;
1345
    }
1346

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

    
1354
        NebulaLog::log("DiM", Log::ERROR, error_str);
1355

    
1356
        vm->unlock();
1357
        return -1;
1358
    }
1359

    
1360
    rc = vm->set_active_snapshot(snap_id);
1361

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

    
1368
        NebulaLog::log("DiM", Log::ERROR, error_str);
1369

    
1370
        vm->unlock();
1371
        return -1;
1372
    }
1373

    
1374
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1375

    
1376
    vm->set_resched(false);
1377

    
1378
    vmpool->update(vm);
1379

    
1380
    vm->unlock();
1381

    
1382
    vmm->trigger(VirtualMachineManager::SNAPSHOT_DELETE,vid);
1383

    
1384
    return 0;
1385
}
1386

    
1387
/* -------------------------------------------------------------------------- */
1388
/* -------------------------------------------------------------------------- */
1389

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

    
1397
    int max_nic_id;
1398
    int uid;
1399
    int oid;
1400
    int rc;
1401

    
1402
    set<int> vm_sgs;
1403

    
1404
    VectorAttribute *        nic;
1405
    vector<VectorAttribute*> sg_rules;
1406

    
1407
    VirtualMachine * vm = vmpool->get(vid, true);
1408

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

    
1415
        NebulaLog::log("DiM", Log::ERROR, error_str);
1416

    
1417
        return -1;
1418
    }
1419

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

    
1428
        NebulaLog::log("DiM", Log::ERROR, error_str);
1429

    
1430
        vm->unlock();
1431
        return -1;
1432
    }
1433

    
1434
    nic = vm->get_attach_nic_info(tmpl, max_nic_id, error_str);
1435

    
1436
    if ( nic == 0 )
1437
    {
1438
        vm->unlock();
1439

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

    
1444
    vm->get_security_groups(vm_sgs);
1445

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

    
1452
    vm->set_resched(false);
1453

    
1454
    uid = vm->get_uid();
1455
    oid = vm->get_oid();
1456

    
1457
    vmpool->update(vm);
1458

    
1459
    vm->unlock();
1460

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

    
1470
    if ( vm == 0 )
1471
    {
1472
        delete nic;
1473

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

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

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

    
1489
        NebulaLog::log("DiM", Log::ERROR, error_str);
1490

    
1491
        return -1;
1492
    }
1493

    
1494
    if ( rc != 0 )
1495
    {
1496
        delete nic;
1497

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

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

    
1509
        vmpool->update(vm);
1510

    
1511
        vm->unlock();
1512

    
1513
        NebulaLog::log("DiM", Log::ERROR, error_str);
1514

    
1515
        return -1;
1516
    }
1517

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

    
1522
    vm->set_attach_nic(nic, sg_rules);
1523

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

    
1528
        // Close current history record
1529

    
1530
        vm->set_running_etime(the_time);
1531

    
1532
        vm->set_etime(the_time);
1533

    
1534
        vm->set_action(History::NIC_ATTACH_ACTION);
1535
        vm->set_reason(History::USER);
1536

    
1537
        vmpool->update_history(vm);
1538

    
1539
        // Open a new history record
1540

    
1541
        vm->cp_history();
1542

    
1543
        vm->set_stime(the_time);
1544

    
1545
        vm->set_running_stime(the_time);
1546

    
1547
        vmpool->update_history(vm);
1548

    
1549
        //-----------------------------------------------
1550

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

    
1557
        vm->clear_attach_nic();
1558
    }
1559

    
1560
    vmpool->update(vm);
1561

    
1562
    vm->unlock();
1563

    
1564
    return 0;
1565
}
1566

    
1567
/* -------------------------------------------------------------------------- */
1568
/* -------------------------------------------------------------------------- */
1569

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

    
1577
    VirtualMachine * vm = vmpool->get(vid, true);
1578

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

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

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

    
1596
        NebulaLog::log("DiM", Log::ERROR, error_str);
1597

    
1598
        vm->unlock();
1599
        return -1;
1600
    }
1601

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

    
1608
        NebulaLog::log("DiM", Log::ERROR, error_str);
1609

    
1610
        vm->unlock();
1611
        return -1;
1612
    }
1613

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

    
1619
        // Close current history record
1620

    
1621
        vm->set_vm_info();
1622

    
1623
        vm->set_running_etime(the_time);
1624

    
1625
        vm->set_etime(the_time);
1626

    
1627
        vm->set_action(History::NIC_DETACH_ACTION);
1628
        vm->set_reason(History::USER);
1629

    
1630
        vmpool->update_history(vm);
1631

    
1632
        // Open a new history record
1633

    
1634
        vm->cp_history();
1635

    
1636
        vm->set_stime(the_time);
1637

    
1638
        vm->set_running_stime(the_time);
1639

    
1640
        vmpool->update_history(vm);
1641

    
1642
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1643

    
1644
        vm->set_resched(false);
1645

    
1646
        vmpool->update(vm);
1647

    
1648
        vm->unlock();
1649

    
1650
        //---------------------------------------------------
1651

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

    
1658
        vmpool->delete_attach_nic(vid);
1659

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

    
1663
    return 0;
1664
}
1665

    
1666
/* -------------------------------------------------------------------------- */
1667
/* -------------------------------------------------------------------------- */
1668

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

    
1679
    VirtualMachine * vm = vmpool->get(vid, true);
1680

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

    
1687
        NebulaLog::log("DiM", Log::ERROR, error_str);
1688

    
1689
        return -1;
1690
    }
1691

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

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

    
1703
        NebulaLog::log("DiM", Log::ERROR, error_str);
1704

    
1705
        vm->unlock();
1706

    
1707
        return -1;
1708
    }
1709

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

    
1713
    snap_id = vm->new_disk_snapshot(did, name, error_str);
1714

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

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

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

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

    
1738
        default: break;
1739
    }
1740

    
1741
    vmpool->update(vm);
1742

    
1743
    vm->unlock();
1744

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

    
1752
        case VirtualMachine::ACTIVE:
1753
            the_time = time(0);
1754

    
1755
            // Close current history record
1756

    
1757
            vm->set_running_etime(the_time);
1758

    
1759
            vm->set_etime(the_time);
1760

    
1761
            vm->set_action(History::DISK_SNAPSHOT_CREATE_ACTION);
1762
            vm->set_reason(History::USER);
1763

    
1764
            vmpool->update_history(vm);
1765

    
1766
            // Open a new history record
1767

    
1768
            vm->cp_history();
1769

    
1770
            vm->set_stime(the_time);
1771

    
1772
            vm->set_running_stime(the_time);
1773

    
1774
            vmpool->update_history(vm);
1775

    
1776
            vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_CREATE, vid);
1777
            break;
1778

    
1779
        default: break;
1780
    }
1781

    
1782
    return 0;
1783
}
1784

    
1785
/* -------------------------------------------------------------------------- */
1786
/* -------------------------------------------------------------------------- */
1787

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

    
1796
    VirtualMachine * vm = vmpool->get(vid, true);
1797

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

    
1804
        NebulaLog::log("DiM", Log::ERROR, error_str);
1805

    
1806
        return -1;
1807
    }
1808

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

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

    
1820
        NebulaLog::log("DiM", Log::ERROR, error_str);
1821

    
1822
        vm->unlock();
1823
        return -1;
1824
    }
1825

    
1826
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1827

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

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

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

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

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

    
1857
        default: break;
1858
    }
1859

    
1860
    vmpool->update(vm);
1861

    
1862
    vm->unlock();
1863

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

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

    
1875
        default: break;
1876
    }
1877

    
1878
    return 0;
1879
}
1880

    
1881
/* -------------------------------------------------------------------------- */
1882
/* -------------------------------------------------------------------------- */
1883

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

    
1893
    VirtualMachine * vm = vmpool->get(vid, true);
1894

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

    
1901
        NebulaLog::log("DiM", Log::ERROR, error_str);
1902

    
1903
        return -1;
1904
    }
1905

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

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

    
1917
        NebulaLog::log("DiM", Log::ERROR, error_str);
1918

    
1919
        vm->unlock();
1920
        return -1;
1921
    }
1922

    
1923
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1924

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

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

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

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

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

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

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

    
1963
        default: break;
1964
    }
1965

    
1966
    vmpool->update(vm);
1967

    
1968
    vm->unlock();
1969

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

    
1975
            // Close current history record
1976

    
1977
            vm->set_running_etime(the_time);
1978

    
1979
            vm->set_etime(the_time);
1980

    
1981
            vm->set_action(History::DISK_SNAPSHOT_DELETE_ACTION);
1982
            vm->set_reason(History::USER);
1983

    
1984
            vmpool->update_history(vm);
1985

    
1986
            // Open a new history record
1987

    
1988
            vm->cp_history();
1989

    
1990
            vm->set_stime(the_time);
1991

    
1992
            vm->set_running_stime(the_time);
1993

    
1994
            vmpool->update_history(vm);
1995

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

    
2001
        default: break;
2002
    }
2003

    
2004
    return 0;
2005
}
2006