Statistics
| Branch: | Tag: | Revision:

one / src / dm / DispatchManagerActions.cc @ e484ecbb

History | View | Annotate | Download (46.8 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
    vector<Attribute *> pci;
96

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

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

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

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

    
105
    vmpool->update(vm);
106

    
107
    vm->set_stime(the_time);
108

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

    
112
    vm->set_running_stime(the_time);
113

    
114
    vm->set_last_poll(0);
115

    
116
    vmpool->update_history(vm);
117

    
118
    vm->unlock();
119

    
120
    return 0;
121
}
122

    
123
/* -------------------------------------------------------------------------- */
124
/* -------------------------------------------------------------------------- */
125

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

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

    
137
    vid = vm->get_oid();
138

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

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

    
155
    vm->unlock();
156

    
157
    return 0;
158

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

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

    
168
/* -------------------------------------------------------------------------- */
169
/* -------------------------------------------------------------------------- */
170

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

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

    
182
    vid = vm->get_oid();
183

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

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

    
197
    vm->unlock();
198

    
199
    return 0;
200

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

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

    
210
/* ************************************************************************** */
211
/* ************************************************************************** */
212

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

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

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

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

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

    
250
    vm->unlock();
251

    
252
    return 0;
253

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

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

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

    
267
/* -------------------------------------------------------------------------- */
268
/* -------------------------------------------------------------------------- */
269

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

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

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

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

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

    
306
    vm->unlock();
307

    
308
    return 0;
309

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

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

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

    
323
/* -------------------------------------------------------------------------- */
324
/* -------------------------------------------------------------------------- */
325

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

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

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

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

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

    
361
    vm->unlock();
362

    
363
    return 0;
364

    
365
error:
366

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

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

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

    
379
/* -------------------------------------------------------------------------- */
380
/* -------------------------------------------------------------------------- */
381

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

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

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

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

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

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

    
409
    vm->unlock();
410

    
411
    return 0;
412

    
413
error:
414

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

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

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

    
427
/* -------------------------------------------------------------------------- */
428
/* -------------------------------------------------------------------------- */
429

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

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

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

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

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

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

    
457
    vm->unlock();
458

    
459
    return 0;
460

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

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

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

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

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

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

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

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

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

    
504
    vm->unlock();
505

    
506
    return 0;
507

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

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

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

    
521
/* -------------------------------------------------------------------------- */
522
/* -------------------------------------------------------------------------- */
523

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

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

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

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

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

    
550
    vm->unlock();
551

    
552
    return 0;
553

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

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

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

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

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

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

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

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

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

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

    
608
    vm->unlock();
609

    
610
    return 0;
611

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

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

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

    
625
/* -------------------------------------------------------------------------- */
626
/* -------------------------------------------------------------------------- */
627

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

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

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

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

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

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

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

    
666
    vm->unlock();
667

    
668
    return 0;
669

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

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

    
679
    vm->unlock();
680

    
681
    return -2;
682
}
683

    
684
/* -------------------------------------------------------------------------- */
685
/* -------------------------------------------------------------------------- */
686

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

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

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

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

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

    
716
    vm->unlock();
717

    
718
    return 0;
719

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

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

    
729
    vm->unlock();
730

    
731
    return -2;
732
}
733

    
734
/* -------------------------------------------------------------------------- */
735
/* -------------------------------------------------------------------------- */
736

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

    
741
    int uid;
742
    int gid;
743

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

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

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

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

    
757
    vm->unlock();
758

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

    
761
    delete tmpl;
762
}
763

    
764
/* -------------------------------------------------------------------------- */
765
/* -------------------------------------------------------------------------- */
766

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

    
775
    vector<Attribute *> pci;
776

    
777
    VirtualMachine::VmState state;
778
    bool is_public_host = false;
779
    int  host_id = -1;
780

    
781
    vm = vmpool->get(vid,true);
782

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

    
788
    if(vm->hasHistory())
789
    {
790
        host_id = vm->get_hid();
791
    }
792

    
793
    vm->unlock();
794

    
795
    if(host_id != -1)
796
    {
797
        host = hpool->get(host_id,true);
798
        if ( host == 0 )
799
        {
800
            oss << "Error getting host " << host_id;
801
            NebulaLog::log("DiM",Log::ERROR,oss);
802
            return -1;
803
        }
804
        is_public_host = host->is_public_cloud();
805
        host->unlock();
806
    }
807

    
808
    vm = vmpool->get(vid,true);
809

    
810
    state = vm->get_state();
811

    
812
    oss << "Finalizing VM " << vid;
813
    NebulaLog::log("DiM",Log::DEBUG,oss);
814

    
815
    switch (state)
816
    {
817
        case VirtualMachine::SUSPENDED:
818
        case VirtualMachine::POWEROFF:
819
            int cpu, mem, disk;
820

    
821
            vm->get_requirements(cpu, mem, disk, pci);
822
            hpool->del_capacity(vm->get_hid(),vm->get_oid(),cpu,mem,disk,pci);
823

    
824
            if (is_public_host)
825
            {
826
                vmm->trigger(VirtualMachineManager::CLEANUP,vid);
827
            }
828
            else
829
            {
830
                tm->trigger(TransferManager::EPILOG_DELETE,vid);
831
            }
832

    
833
            finalize_cleanup(vm);
834
        break;
835

    
836
        case VirtualMachine::STOPPED:
837
        case VirtualMachine::UNDEPLOYED:
838
            if (is_public_host)
839
            {
840
                vmm->trigger(VirtualMachineManager::CLEANUP,vid);
841
            }
842
            else
843
            {
844
                tm->trigger(TransferManager::EPILOG_DELETE,vid);
845
            }
846

    
847
            finalize_cleanup(vm);
848
        break;
849

    
850
        case VirtualMachine::INIT:
851
        case VirtualMachine::PENDING:
852
        case VirtualMachine::HOLD:
853
            finalize_cleanup(vm);
854
        break;
855

    
856
        case VirtualMachine::ACTIVE:
857
            lcm->trigger(LifeCycleManager::DELETE,vid);
858
            vm->unlock();
859
        break;
860

    
861
        case VirtualMachine::DONE:
862
            vm->unlock();
863
        break;
864
    }
865

    
866
    return 0;
867
}
868

    
869
/* -------------------------------------------------------------------------- */
870
/* -------------------------------------------------------------------------- */
871

    
872
int DispatchManager::resubmit(
873
    int     vid,
874
    string& error_str)
875
{
876
    VirtualMachine * vm;
877
    ostringstream    oss;
878
    int              rc = 0;
879

    
880
    vm = vmpool->get(vid,true);
881

    
882
    if ( vm == 0 )
883
    {
884
        return -1;
885
    }
886

    
887
    switch (vm->get_state())
888
    {
889
        case VirtualMachine::POWEROFF:
890
            error_str = "Cannot delete-recreate a powered off VM. Resume it first";
891
            NebulaLog::log("DiM",Log::ERROR,error_str);
892
            rc = -2;
893
        break;
894

    
895
        case VirtualMachine::SUSPENDED:
896
            error_str = "Cannot delete-recreate a suspended VM. Resume it first";
897
            NebulaLog::log("DiM",Log::ERROR,error_str);
898
            rc = -2;
899
        break;
900

    
901
        case VirtualMachine::INIT: // No need to do nothing here
902
        case VirtualMachine::PENDING:
903
        break;
904

    
905
        case VirtualMachine::HOLD: // Move the VM to PENDING in any of these
906
        case VirtualMachine::STOPPED:
907
        case VirtualMachine::UNDEPLOYED:
908
            if (vm->hasHistory())
909
            {
910
                vm->set_action(History::DELETE_RECREATE_ACTION);
911
                vmpool->update_history(vm);
912
            }
913

    
914
            vm->set_state(VirtualMachine::LCM_INIT);
915
            vm->set_state(VirtualMachine::PENDING);
916

    
917
            vmpool->update(vm);
918
        break;
919

    
920
        case VirtualMachine::ACTIVE: //Cleanup VM resources before PENDING
921
            lcm->trigger(LifeCycleManager::CLEAN, vid);
922
        break;
923

    
924
        case VirtualMachine::DONE:
925
            error_str = "Cannot delete-recreate a VM already in DONE state";
926
            NebulaLog::log("DiM",Log::ERROR,error_str);
927
            rc = -2;
928
        break;
929
    }
930

    
931
    vm->unlock();
932

    
933
    return rc;
934
}
935

    
936
/* -------------------------------------------------------------------------- */
937
/* -------------------------------------------------------------------------- */
938

    
939
int DispatchManager::attach(int vid,
940
                            VirtualMachineTemplate * tmpl,
941
                            string &                 error_str)
942
{
943
    ostringstream oss;
944

    
945
    int max_disk_id;
946
    int uid;
947
    int oid;
948
    int image_id;
949
    int image_cluster_id;
950

    
951
    set<string>       used_targets;
952
    VectorAttribute * disk;
953
    Snapshots *       snap;
954

    
955
    VirtualMachine * vm = vmpool->get(vid, true);
956

    
957
    if ( vm == 0 )
958
    {
959
        oss << "Could not attach a new disk to VM " << vid
960
            << ", VM does not exist" ;
961
        error_str = oss.str();
962

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

    
965
        return -1;
966
    }
967

    
968
    if ( vm->get_state()     == VirtualMachine::ACTIVE &&
969
         vm->get_lcm_state() == VirtualMachine::RUNNING )
970
    {
971
        vm->set_state(VirtualMachine::HOTPLUG);
972
    }
973
    else if ( vm->get_state() == VirtualMachine::POWEROFF )
974
    {
975
        vm->set_state(VirtualMachine::ACTIVE);
976
        vm->set_state(VirtualMachine::HOTPLUG_PROLOG_POWEROFF);
977
    }
978
    else
979
    {
980
        oss << "Could not attach a new disk to VM " << vid << ", wrong state "
981
            << vm->state_str() << ".";
982
        error_str = oss.str();
983

    
984
        NebulaLog::log("DiM", Log::ERROR, error_str);
985

    
986
        vm->unlock();
987
        return -1;
988
    }
989

    
990
    vm->get_disk_info(max_disk_id, used_targets);
991

    
992
    vm->set_resched(false);
993

    
994
    uid = vm->get_uid();
995
    oid = vm->get_oid();
996

    
997
    vmpool->update(vm);
998

    
999
    vm->unlock();
1000

    
1001
    disk = VirtualMachine::set_up_attach_disk(oid,
1002
                                              tmpl,
1003
                                              used_targets,
1004
                                              max_disk_id,
1005
                                              uid,
1006
                                              image_id,
1007
                                              &snap,
1008
                                              error_str);
1009
    vm = vmpool->get(vid, true);
1010

    
1011
    if ( vm == 0 )
1012
    {
1013
                if ( disk != 0 )
1014
                {
1015
                        imagem->release_image(oid, image_id, false);
1016

    
1017
                        delete snap;
1018
                        delete disk;
1019
                }
1020

    
1021
        error_str = "VM does not exist after setting its state to HOTPLUG.";
1022

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

    
1027
    if ( disk == 0 )
1028
    {
1029
        if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1030
        {
1031
            vm->set_state(VirtualMachine::RUNNING);
1032
        }
1033
        else
1034
        {
1035
            vm->set_state(VirtualMachine::LCM_INIT);
1036
            vm->set_state(VirtualMachine::POWEROFF);
1037
        }
1038

    
1039
        vmpool->update(vm);
1040

    
1041
        vm->unlock();
1042

    
1043
        NebulaLog::log("DiM", Log::ERROR, error_str);
1044
        return -1;
1045
    }
1046

    
1047
    // Check that we don't have a cluster incompatibility.
1048
    if (disk->vector_value("CLUSTER_ID", image_cluster_id) == 0)
1049
    {
1050
      if (vm->get_cid() != image_cluster_id)
1051
      {
1052
          imagem->release_image(oid, image_id, false);
1053

    
1054
          delete snap;
1055
          delete disk;
1056

    
1057
          if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1058
          {
1059
              vm->set_state(VirtualMachine::RUNNING);
1060
          }
1061
          else
1062
          {
1063
              vm->set_state(VirtualMachine::LCM_INIT);
1064
              vm->set_state(VirtualMachine::POWEROFF);
1065
          }
1066

    
1067
          vmpool->update(vm);
1068

    
1069
          vm->unlock();
1070

    
1071
          error_str = "Could not attach disk because of cluster incompatibility.";
1072

    
1073
          NebulaLog::log("DiM", Log::ERROR, error_str);
1074
          return -1;
1075
      }
1076
    }
1077

    
1078
    // Set the VM info in the history before the disk is attached to the
1079
    // VM template
1080
    vm->set_vm_info();
1081

    
1082
    vm->set_attach_disk(disk, snap);
1083

    
1084
    if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG )
1085
    {
1086
        time_t the_time = time(0);
1087

    
1088
        // Close current history record
1089

    
1090
        vm->set_running_etime(the_time);
1091

    
1092
        vm->set_etime(the_time);
1093

    
1094
        vm->set_action(History::DISK_ATTACH_ACTION);
1095
        vm->set_reason(History::USER);
1096

    
1097
        vmpool->update_history(vm);
1098

    
1099
        // Open a new history record
1100

    
1101
        vm->cp_history();
1102

    
1103
        vm->set_stime(the_time);
1104

    
1105
        vm->set_running_stime(the_time);
1106

    
1107
        vmpool->update_history(vm);
1108

    
1109
        //-----------------------------------------------
1110

    
1111
        vmm->trigger(VirtualMachineManager::ATTACH,vid);
1112
    }
1113
    else
1114
    {
1115
        tm->trigger(TransferManager::PROLOG_ATTACH, vid);
1116
    }
1117

    
1118
    vmpool->update(vm);
1119

    
1120
    vm->unlock();
1121

    
1122
    return 0;
1123
}
1124

    
1125
/* -------------------------------------------------------------------------- */
1126
/* -------------------------------------------------------------------------- */
1127

    
1128
int DispatchManager::detach(
1129
    int      vid,
1130
    int      disk_id,
1131
    string&  error_str)
1132
{
1133
    ostringstream oss;
1134

    
1135
    VirtualMachine * vm = vmpool->get(vid, true);
1136

    
1137
    if ( vm == 0 )
1138
    {
1139
        oss << "VirtualMachine " << vid << " no longer exists";
1140
        error_str = oss.str();
1141

    
1142
        NebulaLog::log("DiM", Log::ERROR, error_str);
1143
        return -1;
1144
    }
1145

    
1146
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1147
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1148
        vm->get_state()       != VirtualMachine::POWEROFF)
1149
    {
1150
        oss << "Could not detach disk from VM " << vid << ", wrong state "
1151
            << vm->state_str() << ".";
1152
        error_str = oss.str();
1153

    
1154
        NebulaLog::log("DiM", Log::ERROR, error_str);
1155

    
1156
        vm->unlock();
1157
        return -1;
1158
    }
1159

    
1160
    if ( vm->set_attach_disk(disk_id) == -1 )
1161
    {
1162
        oss << "Could not detach disk with DISK_ID " << disk_id
1163
            << ", it does not exist.";
1164
        error_str = oss.str();
1165

    
1166
        NebulaLog::log("DiM", Log::ERROR, error_str);
1167

    
1168
        vm->unlock();
1169
        return -1;
1170
    }
1171

    
1172
    vm->set_resched(false);
1173

    
1174
    if ( vm->get_state() == VirtualMachine::ACTIVE &&
1175
         vm->get_lcm_state() == VirtualMachine::RUNNING )
1176
    {
1177
        time_t the_time = time(0);
1178

    
1179
        // Close current history record
1180

    
1181
        vm->set_vm_info();
1182

    
1183
        vm->set_running_etime(the_time);
1184

    
1185
        vm->set_etime(the_time);
1186

    
1187
        vm->set_action(History::DISK_DETACH_ACTION);
1188
        vm->set_reason(History::USER);
1189

    
1190
        vmpool->update_history(vm);
1191

    
1192
        // Open a new history record
1193

    
1194
        vm->cp_history();
1195

    
1196
        vm->set_stime(the_time);
1197

    
1198
        vm->set_running_stime(the_time);
1199

    
1200
        vmpool->update_history(vm);
1201

    
1202
        //---------------------------------------------------
1203

    
1204
        vm->set_state(VirtualMachine::HOTPLUG);
1205

    
1206
        vmm->trigger(VirtualMachineManager::DETACH,vid);
1207
    }
1208
    else
1209
    {
1210
        vm->set_state(VirtualMachine::ACTIVE);
1211
        vm->set_state(VirtualMachine::HOTPLUG_EPILOG_POWEROFF);
1212

    
1213
        tm->trigger(TransferManager::EPILOG_DETACH, vid);
1214
    }
1215

    
1216
    vmpool->update(vm);
1217

    
1218
    vm->unlock();
1219

    
1220
    return 0;
1221
}
1222

    
1223
/* -------------------------------------------------------------------------- */
1224
/* -------------------------------------------------------------------------- */
1225

    
1226
int DispatchManager::snapshot_create(
1227
    int     vid,
1228
    string& name,
1229
    int&    snap_id,
1230
    string& error_str)
1231
{
1232
    ostringstream oss;
1233

    
1234
    VirtualMachine * vm = vmpool->get(vid, true);
1235

    
1236
    if ( vm == 0 )
1237
    {
1238
        oss << "Could not create a new snapshot for VM " << vid
1239
            << ", VM does not exist" ;
1240
        error_str = oss.str();
1241

    
1242
        NebulaLog::log("DiM", Log::ERROR, error_str);
1243

    
1244
        return -1;
1245
    }
1246

    
1247
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1248
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1249
    {
1250
        oss << "Could not create a new snapshot for VM " << vid
1251
            << ", wrong state " << vm->state_str() << ".";
1252
        error_str = oss.str();
1253

    
1254
        NebulaLog::log("DiM", Log::ERROR, error_str);
1255

    
1256
        vm->unlock();
1257
        return -1;
1258
    }
1259

    
1260
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1261

    
1262
    vm->set_resched(false);
1263

    
1264
    vm->new_snapshot(name, snap_id);
1265

    
1266
    vmpool->update(vm);
1267

    
1268
    vm->unlock();
1269

    
1270
    vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
1271

    
1272
    return 0;
1273
}
1274

    
1275
/* -------------------------------------------------------------------------- */
1276
/* -------------------------------------------------------------------------- */
1277

    
1278
int DispatchManager::snapshot_revert(
1279
    int         vid,
1280
    int         snap_id,
1281
    string&     error_str)
1282
{
1283
    ostringstream oss;
1284

    
1285
    int rc;
1286

    
1287
    VirtualMachine * vm = vmpool->get(vid, true);
1288

    
1289
    if ( vm == 0 )
1290
    {
1291
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1292
            << ", VM does not exist" ;
1293
        error_str = oss.str();
1294

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

    
1297
        return -1;
1298
    }
1299

    
1300
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1301
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1302
    {
1303
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1304
            << ", wrong state " << vm->state_str() << ".";
1305
        error_str = oss.str();
1306

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

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

    
1313

    
1314
    rc = vm->set_active_snapshot(snap_id);
1315

    
1316
    if ( rc == -1 )
1317
    {
1318
        oss << "Could not revert VM " << vid << " to snapshot " << snap_id
1319
            << ", it does not exist.";
1320
        error_str = oss.str();
1321

    
1322
        NebulaLog::log("DiM", Log::ERROR, error_str);
1323

    
1324
        vm->unlock();
1325
        return -1;
1326
    }
1327

    
1328
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1329

    
1330
    vm->set_resched(false);
1331

    
1332
    vmpool->update(vm);
1333

    
1334
    vm->unlock();
1335

    
1336
    vmm->trigger(VirtualMachineManager::SNAPSHOT_REVERT,vid);
1337

    
1338
    return 0;
1339
}
1340

    
1341
/* -------------------------------------------------------------------------- */
1342
/* -------------------------------------------------------------------------- */
1343

    
1344
int DispatchManager::snapshot_delete(
1345
    int         vid,
1346
    int         snap_id,
1347
    string&     error_str)
1348
{
1349
    ostringstream oss;
1350

    
1351
    int rc;
1352

    
1353
    VirtualMachine * vm = vmpool->get(vid, true);
1354

    
1355
    if ( vm == 0 )
1356
    {
1357
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1358
            << ", VM does not exist" ;
1359
        error_str = oss.str();
1360

    
1361
        NebulaLog::log("DiM", Log::ERROR, error_str);
1362

    
1363
        return -1;
1364
    }
1365

    
1366
    if ( vm->get_state()     != VirtualMachine::ACTIVE ||
1367
         vm->get_lcm_state() != VirtualMachine::RUNNING )
1368
    {
1369
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1370
            << ", wrong state " << vm->state_str() << ".";
1371
        error_str = oss.str();
1372

    
1373
        NebulaLog::log("DiM", Log::ERROR, error_str);
1374

    
1375
        vm->unlock();
1376
        return -1;
1377
    }
1378

    
1379
    rc = vm->set_active_snapshot(snap_id);
1380

    
1381
    if ( rc == -1 )
1382
    {
1383
        oss << "Could not delete snapshot " << snap_id << " for VM " << vid
1384
            << ", it does not exist.";
1385
        error_str = oss.str();
1386

    
1387
        NebulaLog::log("DiM", Log::ERROR, error_str);
1388

    
1389
        vm->unlock();
1390
        return -1;
1391
    }
1392

    
1393
    vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
1394

    
1395
    vm->set_resched(false);
1396

    
1397
    vmpool->update(vm);
1398

    
1399
    vm->unlock();
1400

    
1401
    vmm->trigger(VirtualMachineManager::SNAPSHOT_DELETE,vid);
1402

    
1403
    return 0;
1404
}
1405

    
1406
/* -------------------------------------------------------------------------- */
1407
/* -------------------------------------------------------------------------- */
1408

    
1409
int DispatchManager::attach_nic(
1410
        int                     vid,
1411
        VirtualMachineTemplate* tmpl,
1412
        string &                error_str)
1413
{
1414
    ostringstream oss;
1415

    
1416
    int max_nic_id;
1417
    int uid;
1418
    int oid;
1419
    int rc;
1420

    
1421
    set<int> vm_sgs;
1422

    
1423
    VectorAttribute *        nic;
1424
    vector<VectorAttribute*> sg_rules;
1425

    
1426
    VirtualMachine * vm = vmpool->get(vid, true);
1427

    
1428
    if ( vm == 0 )
1429
    {
1430
        oss << "Could not add a new NIC to VM " << vid
1431
            << ", VM does not exist" ;
1432
        error_str = oss.str();
1433

    
1434
        NebulaLog::log("DiM", Log::ERROR, error_str);
1435

    
1436
        return -1;
1437
    }
1438

    
1439
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1440
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1441
        vm->get_state()       != VirtualMachine::POWEROFF )
1442
    {
1443
        oss << "Could not add a new NIC to VM " << vid << ", wrong state "
1444
            << vm->state_str() << ".";
1445
        error_str = oss.str();
1446

    
1447
        NebulaLog::log("DiM", Log::ERROR, error_str);
1448

    
1449
        vm->unlock();
1450
        return -1;
1451
    }
1452

    
1453
    nic = vm->get_attach_nic_info(tmpl, max_nic_id, error_str);
1454

    
1455
    if ( nic == 0 )
1456
    {
1457
        vm->unlock();
1458

    
1459
        NebulaLog::log("DiM", Log::ERROR, error_str);
1460
        return -1;
1461
    }
1462

    
1463
    vm->get_security_groups(vm_sgs);
1464

    
1465
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1466
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1467
    {
1468
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1469
    }
1470

    
1471
    vm->set_resched(false);
1472

    
1473
    uid = vm->get_uid();
1474
    oid = vm->get_oid();
1475

    
1476
    vmpool->update(vm);
1477

    
1478
    vm->unlock();
1479

    
1480
    rc = VirtualMachine::set_up_attach_nic(oid,
1481
                                    vm_sgs,
1482
                                    nic,
1483
                                    sg_rules,
1484
                                    max_nic_id,
1485
                                    uid,
1486
                                    error_str);
1487
    vm = vmpool->get(vid, true);
1488

    
1489
    if ( vm == 0 )
1490
    {
1491
        delete nic;
1492

    
1493
        if ( rc == 0 )
1494
        {
1495
            VirtualMachine::release_network_leases(nic, vid);
1496

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

    
1504
        oss << "Could not attach a new NIC to VM " << vid
1505
            << ", VM does not exist after setting its state to HOTPLUG." ;
1506
        error_str = oss.str();
1507

    
1508
        NebulaLog::log("DiM", Log::ERROR, error_str);
1509

    
1510
        return -1;
1511
    }
1512

    
1513
    if ( rc != 0 )
1514
    {
1515
        delete nic;
1516

    
1517
        vector<VectorAttribute*>::iterator it;
1518
        for(it = sg_rules.begin(); it != sg_rules.end(); it++)
1519
        {
1520
            delete *it;
1521
        }
1522

    
1523
        if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1524
        {
1525
            vm->set_state(VirtualMachine::RUNNING);
1526
        }
1527

    
1528
        vmpool->update(vm);
1529

    
1530
        vm->unlock();
1531

    
1532
        NebulaLog::log("DiM", Log::ERROR, error_str);
1533

    
1534
        return -1;
1535
    }
1536

    
1537
    // Set the VM info in the history before the nic is attached to the
1538
    // VM template
1539
    vm->set_vm_info();
1540

    
1541
    vm->set_attach_nic(nic, sg_rules);
1542

    
1543
    if (vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC)
1544
    {
1545
        time_t the_time = time(0);
1546

    
1547
        // Close current history record
1548

    
1549
        vm->set_running_etime(the_time);
1550

    
1551
        vm->set_etime(the_time);
1552

    
1553
        vm->set_action(History::NIC_ATTACH_ACTION);
1554
        vm->set_reason(History::USER);
1555

    
1556
        vmpool->update_history(vm);
1557

    
1558
        // Open a new history record
1559

    
1560
        vm->cp_history();
1561

    
1562
        vm->set_stime(the_time);
1563

    
1564
        vm->set_running_stime(the_time);
1565

    
1566
        vmpool->update_history(vm);
1567

    
1568
        //-----------------------------------------------
1569

    
1570
        vmm->trigger(VirtualMachineManager::ATTACH_NIC,vid);
1571
    }
1572
    else
1573
    {
1574
        vm->log("DiM", Log::INFO, "VM NIC Successfully attached.");
1575

    
1576
        vm->clear_attach_nic();
1577
    }
1578

    
1579
    vmpool->update(vm);
1580

    
1581
    vm->unlock();
1582

    
1583
    return 0;
1584
}
1585

    
1586
/* -------------------------------------------------------------------------- */
1587
/* -------------------------------------------------------------------------- */
1588

    
1589
int DispatchManager::detach_nic(
1590
    int      vid,
1591
    int      nic_id,
1592
    string&  error_str)
1593
{
1594
    ostringstream oss;
1595

    
1596
    VirtualMachine * vm = vmpool->get(vid, true);
1597

    
1598
    if ( vm == 0 )
1599
    {
1600
        oss << "VirtualMachine " << vid << " no longer exists";
1601
        error_str = oss.str();
1602

    
1603
        NebulaLog::log("DiM", Log::ERROR, error_str);
1604
        return -1;
1605
    }
1606

    
1607
    if (( vm->get_state()     != VirtualMachine::ACTIVE ||
1608
          vm->get_lcm_state() != VirtualMachine::RUNNING ) &&
1609
        vm->get_state()       != VirtualMachine::POWEROFF )
1610
    {
1611
        oss << "Could not detach NIC from VM " << vid << ", wrong state "
1612
            << vm->state_str() << ".";
1613
        error_str = oss.str();
1614

    
1615
        NebulaLog::log("DiM", Log::ERROR, error_str);
1616

    
1617
        vm->unlock();
1618
        return -1;
1619
    }
1620

    
1621
    if ( vm->set_attach_nic(nic_id) == -1 )
1622
    {
1623
        oss << "Could not detach NIC with NIC_ID " << nic_id
1624
            << ", it does not exist.";
1625
        error_str = oss.str();
1626

    
1627
        NebulaLog::log("DiM", Log::ERROR, error_str);
1628

    
1629
        vm->unlock();
1630
        return -1;
1631
    }
1632

    
1633
    if (vm->get_state()     == VirtualMachine::ACTIVE &&
1634
        vm->get_lcm_state() == VirtualMachine::RUNNING )
1635
    {
1636
        time_t the_time = time(0);
1637

    
1638
        // Close current history record
1639

    
1640
        vm->set_vm_info();
1641

    
1642
        vm->set_running_etime(the_time);
1643

    
1644
        vm->set_etime(the_time);
1645

    
1646
        vm->set_action(History::NIC_DETACH_ACTION);
1647
        vm->set_reason(History::USER);
1648

    
1649
        vmpool->update_history(vm);
1650

    
1651
        // Open a new history record
1652

    
1653
        vm->cp_history();
1654

    
1655
        vm->set_stime(the_time);
1656

    
1657
        vm->set_running_stime(the_time);
1658

    
1659
        vmpool->update_history(vm);
1660

    
1661
        vm->set_state(VirtualMachine::HOTPLUG_NIC);
1662

    
1663
        vm->set_resched(false);
1664

    
1665
        vmpool->update(vm);
1666

    
1667
        vm->unlock();
1668

    
1669
        //---------------------------------------------------
1670

    
1671
        vmm->trigger(VirtualMachineManager::DETACH_NIC,vid);
1672
    }
1673
    else
1674
    {
1675
        vm->unlock();
1676

    
1677
        vmpool->delete_attach_nic(vid);
1678

    
1679
        vm->log("DiM", Log::INFO, "VM NIC Successfully detached.");
1680
    }
1681

    
1682
    return 0;
1683
}
1684

    
1685
/* -------------------------------------------------------------------------- */
1686
/* -------------------------------------------------------------------------- */
1687

    
1688
int DispatchManager::disk_snapshot_create(
1689
        int           vid,
1690
        int           did,
1691
        const string& name,
1692
        int&          snap_id,
1693
        string&       error_str)
1694
{
1695
    ostringstream oss;
1696
    time_t        the_time;
1697

    
1698
    VirtualMachine * vm = vmpool->get(vid, true);
1699

    
1700
    if ( vm == 0 )
1701
    {
1702
        oss << "Could not create a new disk snapshot for VM " << vid
1703
            << ", VM does not exist" ;
1704
        error_str = oss.str();
1705

    
1706
        NebulaLog::log("DiM", Log::ERROR, error_str);
1707

    
1708
        return -1;
1709
    }
1710

    
1711
    VirtualMachine::VmState  state  = vm->get_state();
1712
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1713

    
1714
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1715
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1716
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1717
    {
1718
        oss << "Could not create a new snapshot for VM " << vid
1719
            << ", wrong state " << vm->state_str() << ".";
1720
        error_str = oss.str();
1721

    
1722
        NebulaLog::log("DiM", Log::ERROR, error_str);
1723

    
1724
        vm->unlock();
1725

    
1726
        return -1;
1727
    }
1728

    
1729
    // Set the VM info in the history before the snapshot is added to VM
1730
    vm->set_vm_info();
1731

    
1732
    snap_id = vm->new_disk_snapshot(did, name, error_str);
1733

    
1734
    if (snap_id == -1)
1735
    {
1736
        vm->unlock();
1737
        return -1;
1738
    }
1739

    
1740
    switch(state)
1741
    {
1742
        case VirtualMachine::POWEROFF:
1743
            vm->set_state(VirtualMachine::ACTIVE);
1744
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_POWEROFF);
1745
            break;
1746

    
1747
        case VirtualMachine::SUSPENDED:
1748
            vm->set_state(VirtualMachine::ACTIVE);
1749
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_SUSPENDED);
1750
            break;
1751

    
1752
        case VirtualMachine::ACTIVE:
1753
            vm->set_state(VirtualMachine::ACTIVE);
1754
            vm->set_state(VirtualMachine::DISK_SNAPSHOT);
1755
            break;
1756

    
1757
        default: break;
1758
    }
1759

    
1760
    vmpool->update(vm);
1761

    
1762
    vm->unlock();
1763

    
1764
    switch(state)
1765
    {
1766
        case VirtualMachine::POWEROFF:
1767
        case VirtualMachine::SUSPENDED:
1768
            tm->trigger(TransferManager::SNAPSHOT_CREATE,vid);
1769
            break;
1770

    
1771
        case VirtualMachine::ACTIVE:
1772
            the_time = time(0);
1773

    
1774
            // Close current history record
1775

    
1776
            vm->set_running_etime(the_time);
1777

    
1778
            vm->set_etime(the_time);
1779

    
1780
            vm->set_action(History::DISK_SNAPSHOT_CREATE_ACTION);
1781
            vm->set_reason(History::USER);
1782

    
1783
            vmpool->update_history(vm);
1784

    
1785
            // Open a new history record
1786

    
1787
            vm->cp_history();
1788

    
1789
            vm->set_stime(the_time);
1790

    
1791
            vm->set_running_stime(the_time);
1792

    
1793
            vmpool->update_history(vm);
1794

    
1795
            vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_CREATE, vid);
1796
            break;
1797

    
1798
        default: break;
1799
    }
1800

    
1801
    return 0;
1802
}
1803

    
1804
/* -------------------------------------------------------------------------- */
1805
/* -------------------------------------------------------------------------- */
1806

    
1807
int DispatchManager::disk_snapshot_revert(
1808
        int           vid,
1809
        int           did,
1810
        int           snap_id,
1811
        string&       error_str)
1812
{
1813
    ostringstream oss;
1814

    
1815
    VirtualMachine * vm = vmpool->get(vid, true);
1816

    
1817
    if ( vm == 0 )
1818
    {
1819
        oss << "Could not revert to disk snapshot for VM " << vid
1820
            << ", VM does not exist" ;
1821
        error_str = oss.str();
1822

    
1823
        NebulaLog::log("DiM", Log::ERROR, error_str);
1824

    
1825
        return -1;
1826
    }
1827

    
1828
    VirtualMachine::VmState  state  = vm->get_state();
1829
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1830

    
1831
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1832
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1833
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1834
    {
1835
        oss << "Could not revert to disk snapshot for VM " << vid
1836
            << ", wrong state " << vm->state_str() << ".";
1837
        error_str = oss.str();
1838

    
1839
        NebulaLog::log("DiM", Log::ERROR, error_str);
1840

    
1841
        vm->unlock();
1842
        return -1;
1843
    }
1844

    
1845
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1846

    
1847
    if (snaps == 0)
1848
    {
1849
        vm->unlock();
1850
        return -1;
1851
    }
1852

    
1853
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1854
    {
1855
        vm->unlock();
1856
        return -1;
1857
    }
1858

    
1859
    switch(state)
1860
    {
1861
        case VirtualMachine::POWEROFF:
1862
            vm->set_state(VirtualMachine::ACTIVE);
1863
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_POWEROFF);
1864
            break;
1865

    
1866
        case VirtualMachine::SUSPENDED:
1867
            vm->set_state(VirtualMachine::ACTIVE);
1868
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT_SUSPENDED);
1869
            break;
1870

    
1871
        case VirtualMachine::ACTIVE:
1872
            vm->set_state(VirtualMachine::ACTIVE);
1873
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_REVERT);
1874
            break;
1875

    
1876
        default: break;
1877
    }
1878

    
1879
    vmpool->update(vm);
1880

    
1881
    vm->unlock();
1882

    
1883
    switch(state)
1884
    {
1885
        case VirtualMachine::POWEROFF:
1886
        case VirtualMachine::SUSPENDED:
1887
            tm->trigger(TransferManager::SNAPSHOT_REVERT, vid);
1888
            break;
1889

    
1890
        case VirtualMachine::ACTIVE:
1891
            vmm->trigger(VirtualMachineManager::DISK_SNAPSHOT_REVERT, vid);
1892
            break;
1893

    
1894
        default: break;
1895
    }
1896

    
1897
    return 0;
1898
}
1899

    
1900
/* -------------------------------------------------------------------------- */
1901
/* -------------------------------------------------------------------------- */
1902

    
1903
int DispatchManager::disk_snapshot_delete(
1904
        int           vid,
1905
        int           did,
1906
        int           snap_id,
1907
        string&       error_str)
1908
{
1909
    ostringstream oss;
1910
    time_t        the_time;
1911

    
1912
    VirtualMachine * vm = vmpool->get(vid, true);
1913

    
1914
    if ( vm == 0 )
1915
    {
1916
        oss << "Could not delete disk snapshot from VM " << vid
1917
            << ", VM does not exist" ;
1918
        error_str = oss.str();
1919

    
1920
        NebulaLog::log("DiM", Log::ERROR, error_str);
1921

    
1922
        return -1;
1923
    }
1924

    
1925
    VirtualMachine::VmState  state  = vm->get_state();
1926
    VirtualMachine::LcmState lstate = vm->get_lcm_state();
1927

    
1928
    if ((state !=VirtualMachine::POWEROFF || lstate !=VirtualMachine::LCM_INIT)&&
1929
        (state !=VirtualMachine::SUSPENDED|| lstate !=VirtualMachine::LCM_INIT)&&
1930
        (state !=VirtualMachine::ACTIVE   || lstate !=VirtualMachine::RUNNING))
1931
    {
1932
        oss << "Could not delete disk snapshot from VM " << vid
1933
            << ", wrong state " << vm->state_str() << ".";
1934
        error_str = oss.str();
1935

    
1936
        NebulaLog::log("DiM", Log::ERROR, error_str);
1937

    
1938
        vm->unlock();
1939
        return -1;
1940
    }
1941

    
1942
    const Snapshots * snaps = vm->get_disk_snapshots(did, error_str);
1943

    
1944
    if (snaps == 0)
1945
    {
1946
        vm->unlock();
1947
        return -1;
1948
    }
1949

    
1950
    if (!snaps->test_delete(snap_id, error_str))
1951
    {
1952
        vm->unlock();
1953
        return -1;
1954
    }
1955

    
1956
    if (vm->set_snapshot_disk(did, snap_id) == -1)
1957
    {
1958
        vm->unlock();
1959
        return -1;
1960
    }
1961

    
1962
    // Set the VM info in the history before the snapshot is removed from the VM
1963
    vm->set_vm_info();
1964

    
1965
    switch(state)
1966
    {
1967
        case VirtualMachine::POWEROFF:
1968
            vm->set_state(VirtualMachine::ACTIVE);
1969
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_POWEROFF);
1970
            break;
1971

    
1972
        case VirtualMachine::SUSPENDED:
1973
            vm->set_state(VirtualMachine::ACTIVE);
1974
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE_SUSPENDED);
1975
            break;
1976

    
1977
        case VirtualMachine::ACTIVE:
1978
            vm->set_state(VirtualMachine::ACTIVE);
1979
            vm->set_state(VirtualMachine::DISK_SNAPSHOT_DELETE);
1980
            break;
1981

    
1982
        default: break;
1983
    }
1984

    
1985
    vmpool->update(vm);
1986

    
1987
    vm->unlock();
1988

    
1989
    switch(state)
1990
    {
1991
        case VirtualMachine::ACTIVE:
1992
            the_time = time(0);
1993

    
1994
            // Close current history record
1995

    
1996
            vm->set_running_etime(the_time);
1997

    
1998
            vm->set_etime(the_time);
1999

    
2000
            vm->set_action(History::DISK_SNAPSHOT_DELETE_ACTION);
2001
            vm->set_reason(History::USER);
2002

    
2003
            vmpool->update_history(vm);
2004

    
2005
            // Open a new history record
2006

    
2007
            vm->cp_history();
2008

    
2009
            vm->set_stime(the_time);
2010

    
2011
            vm->set_running_stime(the_time);
2012

    
2013
            vmpool->update_history(vm);
2014

    
2015
        case VirtualMachine::POWEROFF:
2016
        case VirtualMachine::SUSPENDED:
2017
            tm->trigger(TransferManager::SNAPSHOT_DELETE, vid);
2018
            break;
2019

    
2020
        default: break;
2021
    }
2022

    
2023
    return 0;
2024
}
2025