0001-Implemented-CPU-and-memory-hotplugging.patch

Sylvain Baubeau, 05/09/2012 09:18 AM

Download (65.2 KB)

View differences:

TODO
1
About the scale-in features:
2

  
3
-(Implement KVM's scaling methods)
4
-If we want VCPU hotpluging to be more useful, we must also take care of scaling the CPU share on the hypervisor
5
-Check/Separate variable used to monitor used memory and variable used to set new memory amount
6

  
7
-Check the aftermath of adding new states to the LCM
8
-Register VM changes to either the VM history or to new VM attributes
9
-Find a better way to inform the user in case of scale-in failure
10
-Extend polling/monitoring to get number of VCPUs
11
-When a scaling attempt fails, force a poll request
12
-Write tests
include/DispatchManager.h
219 219
    int reboot(
220 220
        int vid);
221 221

  
222
     /**
223
     *  Change the amount of memory of the VM online.
224
     *  The VM MUST have its mutex locked. If the function fails
225
     *  the calling funtion is responsible for recovering from the error.
226
     *    @param vm pointer to a VirtualMachine with its mutex locked.
227
     *    @return 0 on success
228
     */
229
    int memset(
230
        VirtualMachine * vm);
231

  
232
     /**
233
     *  Change the number of VCPUs of the VM online.
234
     *  The VM MUST have its mutex locked. If the function fails
235
     *  the calling funtion is responsible for recovering from the error.
236
     *    @param vm pointer to a VirtualMachine with its mutex locked.
237
     *    @return 0 on success
238
     */
239
    int vcpuset(
240
        VirtualMachine * vm);
241

  
222 242
private:
223 243
    /**
224 244
     *  Thread id for the Dispatch Manager
include/LifeCycleManager.h
53 53
        CANCEL_FAILURE,   /**< Sent by the VMM when a cancel action fails     */
54 54
        MONITOR_FAILURE,  /**< Sent by the VMM when a VM has failed while active */
55 55
        MONITOR_SUSPEND,  /**< Sent by the VMM when a VM is paused while active */
56
        MONITOR_DONE,     /**< Sent by the VMM when a VM is not found */
56
        MONITOR_DONE,     /**< Sent by the VMM when a VM is not found         */
57
        SCALE_MEMORY_SUCCESS,/**< Sent by the VMM when a memory scaling action succeeds*/
58
        SCALE_MEMORY_FAILURE,/**< Sent by the VMM when a memory scaling action fails*/
59
        SCALE_VCPU_SUCCESS,/**< Sent by the VMM when a vcpu scaling action succeeds*/
60
        SCALE_VCPU_FAILURE,/**< Sent by the VMM when a vcpu scaling action fails*/
57 61
        PROLOG_SUCCESS,   /**< Sent by the TM when the prolog phase succeeds  */
58 62
        PROLOG_FAILURE,   /**< Sent by the TM when the prolog phase fails     */
59 63
        EPILOG_SUCCESS,   /**< Sent by the TM when the epilog phase succeeds  */
......
70 74
        REBOOT,           /**< Sent by the DM to reboot a running VM          */
71 75
        DELETE,           /**< Sent by the DM to delete a VM                  */
72 76
        CLEAN,            /**< Sent by the DM to cleanup a VM for resubmission*/
77
        SCALE_MEMORY,     /**< Sent by the DM to change VM memory size        */
78
        SCALE_VCPU,       /**< Sent by the DM to change VM number of VCPUs    */
73 79
        FINALIZE
74 80
    };
75 81

  
......
165 171

  
166 172
    void monitor_done_action(int vid);
167 173

  
174
    void scale_memory_success_action(int vid);
175

  
176
    void scale_memory_failure_action(int vid);
177

  
178
    void scale_vcpu_success_action(int vid);
179

  
180
    void scale_vcpu_failure_action(int vid);
181

  
168 182
    void prolog_success_action(int vid);
169 183

  
170 184
    void prolog_failure_action(int vid);
......
201 215

  
202 216
    void clean_action(int vid);
203 217

  
218
    void scale_memory_action(int vid);
219

  
220
    void scale_vcpu_action(int vid);
221

  
204 222
    void timer_action();
205 223
};
206 224

  
include/RequestManagerVirtualMachine.h
144 144
/* -------------------------------------------------------------------------- */
145 145
/* -------------------------------------------------------------------------- */
146 146

  
147
class VirtualMachineMemSet : public RequestManagerVirtualMachine
148
{
149
public:
150
    VirtualMachineMemSet():
151
        RequestManagerVirtualMachine("VirtualMachineMemSet",
152
                           "Change the amount of memory of the given VM online",
153
                           "A:siiss"){}; // FIXME What is that third argument?
154

  
155
    ~VirtualMachineMemSet(){};
156

  
157
    void request_execute(xmlrpc_c::paramList const& _paramList,
158
            RequestAttributes& att);
159
};
160

  
161
/* -------------------------------------------------------------------------- */
162
/* -------------------------------------------------------------------------- */
163
/* -------------------------------------------------------------------------- */
164

  
165
class VirtualMachineVcpuSet : public RequestManagerVirtualMachine
166
{
167
public:
168
    VirtualMachineVcpuSet():
169
        RequestManagerVirtualMachine("VirtualMachineVcpuSet",
170
                           "Change the number of VCPUs of the given VM online",
171
                           "A:siiss"){}; // FIXME What is that third argument?
172

  
173
    ~VirtualMachineVcpuSet(){};
174

  
175
    void request_execute(xmlrpc_c::paramList const& _paramList,
176
            RequestAttributes& att);
177
};
178

  
179
/* -------------------------------------------------------------------------- */
180
/* -------------------------------------------------------------------------- */
181
/* -------------------------------------------------------------------------- */
182

  
147 183
#endif
include/VirtualMachine.h
164 164
    void update_info(
165 165
        const int _memory,
166 166
        const int _cpu,
167
        const int _vcpu,
167 168
        const int _net_tx,
168 169
        const int _net_rx)
169 170
    {
......
177 178
            cpu    = _cpu;
178 179
        }
179 180

  
181
        if (_vcpu != -1)
182
        {
183
            vcpu    = _vcpu;
184
        }
185

  
180 186
        if (_net_tx != -1)
181 187
        {
182 188
            net_tx = _net_tx;
......
538 544
     *    @return 0 on success.
539 545
     */
540 546
    int  parse_template_attribute(const string& attribute, string& parsed);
541
    
547

  
542 548
    /**
543 549
     *  Factory method for virtual machine templates
544 550
     */
......
615 621
     */
616 622
    void get_requirements (int& cpu, int& memory, int& disk);
617 623

  
624
     /**
625
     *  Get the VM's amount of memory.
626
     *    @return the amount of memory in MB
627
     */
628
    const string get_memory()
629
    {
630
        ostringstream oss;
631
        oss << memory;
632
        return oss.str();
633
    }
634

  
635
     /**
636
     *  Get the VM's number of VCPUs.
637
     *    @return the number of VCPUs
638
     */
639
    const string get_vcpu()
640
    {
641
        ostringstream oss;
642
        oss << vcpu;
643
        return oss.str();
644
    }
645

  
618 646
    // ------------------------------------------------------------------------
619 647
    // Network Leases & Disk Images
620 648
    // ------------------------------------------------------------------------
......
685 713
     *    @param  ar the AuthRequest object
686 714
     *    @param  tmpl the virtual machine template
687 715
     */
688
    static void set_auth_request(int uid, 
689
                                 AuthRequest& ar, 
716
    static void set_auth_request(int uid,
717
                                 AuthRequest& ar,
690 718
                                 VirtualMachineTemplate *tmpl);
691 719
private:
692 720

  
......
746 774
    int         cpu;
747 775

  
748 776
    /**
777
     *  VCPU number
778
     */
779
    int         vcpu;
780

  
781
    /**
749 782
     *  Network usage, transmitted Kilobytes
750 783
     */
751 784
    int         net_tx;
......
906 939
    // Constructor
907 940
    //**************************************************************************
908 941

  
909
    VirtualMachine(int id, 
942
    VirtualMachine(int id,
910 943
                   int uid,
911
                   int gid, 
944
                   int gid,
912 945
                   const string& uname,
913 946
                   const string& gname,
914 947
                   VirtualMachineTemplate * _vm_template);
include/VirtualMachineManager.h
36 36
        VirtualMachinePool *      _vmpool,
37 37
        HostPool *                _hpool,
38 38
        time_t                    _timer_period,
39
        time_t                    _poll_period,        
40
        int                       _vm_limit,        
39
        time_t                    _poll_period,
40
        int                       _vm_limit,
41 41
        vector<const Attribute*>& _mads);
42 42

  
43 43
    ~VirtualMachineManager(){};
......
52 52
        MIGRATE,
53 53
        RESTORE,
54 54
        REBOOT,
55
        SCALE_MEMORY,
56
        SCALE_VCPU,
55 57
        POLL,
56 58
        TIMER,
57 59
        DRIVER_CANCEL,
......
62 64
     *  Triggers specific actions to the Virtual Machine Manager. This function
63 65
     *  wraps the ActionManager trigger function.
64 66
     *    @param action the VMM action
65
     *    @param vid VM unique id. This is the argument of the passed to the 
67
     *    @param vid VM unique id. This is the argument of the passed to the
66 68
     *    invoked action.
67 69
     */
68 70
    virtual void trigger(
......
70 72
        int     vid);
71 73

  
72 74
    /**
73
     *  This functions starts the associated listener thread, and creates a 
75
     *  This functions starts the associated listener thread, and creates a
74 76
     *  new thread for the Virtual Machine Manager. This thread will wait in
75 77
     *  an action loop till it receives ACTION_FINALIZE.
76 78
     *    @return 0 on success.
......
85 87
    {
86 88
        return vmm_thread;
87 89
    };
88
    
90

  
89 91
    /**
90 92
     *  Loads Virtual Machine Manager Mads defined in configuration file
91
     *   @param uid of the user executing the driver. When uid is 0 the nebula 
93
     *   @param uid of the user executing the driver. When uid is 0 the nebula
92 94
     *   identity will be used. Otherwise the Mad will be loaded through the
93
     *   sudo application. 
95
     *   sudo application.
94 96
     */
95 97
    void load_mads(int uid);
96
    
98

  
97 99
private:
98 100
    /**
99 101
     *  Thread id for the Virtual Machine Manager
......
109 111
     *  Pointer to the Host Pool, to access hosts
110 112
     */
111 113
    HostPool *              hpool;
112
        
114

  
113 115
    /**
114 116
     *  Timer period for the Virtual Machine Manager.
115 117
     */
......
131 133
    ActionManager           am;
132 134

  
133 135
    /**
134
     *  Function to execute the Manager action loop method within a new pthread 
136
     *  Function to execute the Manager action loop method within a new pthread
135 137
     * (requires C linkage)
136 138
     */
137 139
    friend void * vmm_action_loop(void *arg);
......
153 155
    };
154 156

  
155 157
    /**
156
     *  Returns a pointer to a Virtual Machine Manager driver. The driver is 
158
     *  Returns a pointer to a Virtual Machine Manager driver. The driver is
157 159
     *  searched by its name.
158 160
     *    @param name the name of the driver
159 161
     *    @return the VM driver owned by uid with attribute name equal to value
......
166 168
        return static_cast<const VirtualMachineManagerDriver *>
167 169
               (MadManager::get(0,_name,name));
168 170
    };
169
    
171

  
170 172
    /**
171 173
     *  The action function executed when an action is triggered.
172 174
     *    @param action the name of the action
......
194 196
     *    @param hostname of the host to perform the action
195 197
     *    @param net_drv name of the vlan driver
196 198
     *    @param m_hostname name of the host to migrate the VM
197
     *    @param m_net_drv name of the vlan driver 
199
     *    @param m_net_drv name of the vlan driver
198 200
     *    @param domain domain id as returned by the hypervisor
199 201
     *    @param dfile deployment file to boot the VM
200 202
     *    @param cfile checkpoint file to save the VM
......
206 208
        const string& m_hostname,
207 209
        const string& m_net_drv,
208 210
        const string& domain,
211
        const string& memory,
212
        const string& vcpu,
209 213
        const string& ldfile,
210 214
        const string& rdfile,
211 215
        const string& cfile,
212 216
        const string& tmpl);
213
 
217

  
214 218
    /**
215 219
     *  Function executed when a DEPLOY action is received. It deploys a VM on
216 220
     *  a Host.
......
220 224
        int vid);
221 225

  
222 226
    /**
223
     *  Function to stop a running VM and generate a checkpoint file. This 
227
     *  Function to stop a running VM and generate a checkpoint file. This
224 228
     *  function is executed when a SAVE action is triggered.
225 229
     *    @param vid the id of the VM.
226 230
     */
......
271 275
        int vid);
272 276

  
273 277
    /**
278
     *  Scale the memory of a running VM.
279
     *    @param vid the id of the VM.
280
     */
281
    void scale_memory_action(
282
        int vid);
283

  
284
    /**
285
     *  Scale the number of vcpu of a running VM.
286
     *    @param vid the id of the VM.
287
     */
288
    void scale_vcpu_action(
289
        int vid);
290

  
291
    /**
274 292
     *  Polls a VM.
275 293
     *    @param vid the id of the VM.
276 294
     */
277 295
    void poll_action(
278 296
        int vid);
279
    
297

  
280 298
    /**
281 299
     *  This function is executed periodically to poll the running VMs
282 300
     */
include/VirtualMachineManagerDriver.h
30 30
 *  VirtualMachineManagerDriver provides a base class to implement VM Manager
31 31
 *  Drivers. This class implements the protocol and recover functions
32 32
 *  from the Mad interface. Classes derived from the VirtualMachineManagerDriver
33
 *  must implement the deployment function to generate specific VM  
33
 *  must implement the deployment function to generate specific VM
34 34
 *  deployment information for the unerlying MAD.
35 35
 */
36 36
class VirtualMachineManagerDriver : public Mad
......
53 53
        string&     message);
54 54

  
55 55
    /**
56
     *  TODO: What do we need here? just poll the active VMs to recover 
56
     *  TODO: What do we need here? just poll the active VMs to recover
57 57
     *  connections? Or an specific recover action from the MAD?
58 58
     */
59 59
    void recover();
......
67 67
    virtual int deployment_description(
68 68
        const VirtualMachine *  vm,
69 69
        const string&           file_name) const = 0;
70
    
71
protected:	
70

  
71
protected:
72 72
    /**
73
     *  Gets a configuration attr from driver configuration file (single 
73
     *  Gets a configuration attr from driver configuration file (single
74 74
     *  version)
75 75
     *    @param name of config attribute
76 76
     *    @param value of the attribute
77 77
     */
78 78
    void get_default(
79
    	const char *  name, 
79
      const char *  name,
80 80
        string&       value) const
81 81
    {
82
    	string sn = name;
83
    	
84
    	driver_conf.get(sn,value);
85
    }    
82
      string sn = name;
83

  
84
      driver_conf.get(sn,value);
85
    }
86 86

  
87 87
    /**
88
     *  Gets a configuration attr from driver configuration file (vector 
88
     *  Gets a configuration attr from driver configuration file (vector
89 89
     *  version)
90 90
     *    @param name of config vector attribute for the domain
91 91
     *    @param vname of the attribute
......
95 95
    	const char *  name,
96 96
    	const char *  vname,
97 97
        string&       value) const;
98
    
99
private:	
100
	/**	
98

  
99
private:
100
	/**
101 101
	 *  Configuration file for the driver
102 102
	 */
103 103
	Template	driver_conf;
104
	
104

  
105 105
    /**
106 106
     *  Pointer to the Virtual Machine Pool, to access VMs
107 107
     */
108 108
    VirtualMachinePool * vmpool;
109 109

  
110 110
    friend class VirtualMachineManager;
111
      
111

  
112 112
    /**
113 113
     *  Sends a deploy request to the MAD: "DEPLOY ID XML_DRV_MSG"
114 114
     *    @param oid the virtual machine id.
......
182 182
        const string& drv_msg) const;
183 183

  
184 184
    /**
185
     *  Sends a scale memory request to the MAD: "SCALE_MEMORY ID MEMORY"
186
     *    @param oid the virtual machine id.
187
     *    @param drv_msg xml data for the mad operation
188
     */
189
    void scale_memory (
190
        const int     oid,
191
        const string& drv_msg) const;
192

  
193
    /**
194
     *  Sends a scale vcpu request to the MAD: "SCALE_VCPU ID VCPU"
195
     *    @param oid the virtual machine id.
196
     *    @param drv_msg xml data for the mad operation
197
     */
198
    void scale_vcpu (
199
        const int     oid,
200
        const string& drv_msg) const;
201

  
202
    /**
185 203
     *  Sends a poll request to the MAD: "POLL ID XML_DRV_MSG"
186 204
     *    @param oid the virtual machine id.
187 205
     *    @param drv_msg xml data for the mad operation
install.sh
670 670
                    src/vmm_mad/remotes/xen/save \
671 671
                    src/vmm_mad/remotes/xen/poll \
672 672
                    src/vmm_mad/remotes/xen/poll_ganglia \
673
                    src/vmm_mad/remotes/xen/shutdown"
673
                    src/vmm_mad/remotes/xen/shutdown \
674
                    src/vmm_mad/remotes/xen/scale_memory \
675
                    src/vmm_mad/remotes/xen/scale_vcpu"
674 676

  
675 677
#-------------------------------------------------------------------------------
676 678
# VMM Driver VMWARE scripts, to be installed under $REMOTES_LOCATION/vmm/vmware
share/man/onevm.1
388 388
.IP "" 0
389 389

  
390 390
.
391
.IP "\(bu" 4
392
memset \fIrange|vmid_list\fR \fImemory\fR
393
.
394
.IP "" 4
395
.
396
.nf
397

  
398
Change the amount of memory of the given VM online
399

  
400
States: RUNNING
401
.
402
.fi
403
.
404
.IP "" 0
405

  
406
.
407
.IP "\(bu" 4
408
vcpuset \fIrange|vmid_list\fR \fIvcpu\fR
409
.
410
.IP "" 4
411
.
412
.nf
413

  
414
Change the number of VCPUs of the given VM online
415

  
416
States: RUNNING
417
.
418
.fi
419
.
420
.IP "" 0
421

  
422
.
391 423
.IP "" 0
392 424
.
393 425
.SH "ARGUMENT FORMATS"
......
523 555
.IP "" 0
524 556

  
525 557
.
558
.IP "\(bu" 4
559
memory
560
.
561
.IP "" 4
562
.
563
.nf
564

  
565
OpenNebula VM amount of memory
566
.
567
.fi
568
.
569
.IP "" 0
570

  
571
.
572
.IP "\(bu" 4
573
vcpu
574
.
575
.IP "" 4
576
.
577
.nf
578

  
579
OpenNebula VM number of VPUs
580
.
581
.fi
582
.
583
.IP "" 0
584

  
585
.
526 586
.IP "" 0
527 587
.
528 588
.SH "LICENSE"
src/cli/one_helper/onevm_helper.rb
103 103
        end
104 104

  
105 105
        table
106
		end
107

  
108
    def memory_to_i(memory)
109
        if memory.match(/^[0123456789]+$/)
110
            return 0,memory.to_i
111
        else
112
            return -1,"amount memory must be a positive number"
113
        end
114
    end
115

  
116
    def vcpu_to_i(vcpu)
117
        if vcpu.match(/^[0123456789]+$/)
118
            return 0,vcpu.to_i
119
        else
120
            return -1,"number of vcpus must be a positive number"
121
        end
122
    end
123

  
124
    def self.memory_to_i_desc
125
        "OpenNebula VM amount of memory"
126
    end
127

  
128
    def self.vcpu_to_i_desc
129
        "OpenNebula VM number of VPUs"
106 130
    end
107 131

  
108 132
    private
src/cli/onevm
77 77
        helper.filterflag_to_i(arg)
78 78
    end
79 79

  
80
    set :format, :memory, OneVMHelper.memory_to_i_desc do |arg|
81
        helper.memory_to_i(arg)
82
    end
83

  
84
    set :format, :vcpu, OneVMHelper.vcpu_to_i_desc do |arg|
85
        helper.vcpu_to_i(arg)
86
    end
87

  
80 88
    ########################################################################
81 89
    # Commands
82 90
    ########################################################################
......
380 388
            :options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do
381 389
        helper.list_pool(options, true, args[0])
382 390
    end
391

  
392
    memset_desc = <<-EOT.unindent
393
        Change the amount of memory of the given VM online
394

  
395
        States: RUNNING
396
    EOT
397

  
398
    command :memset, memset_desc, [:range,:vmid_list], :memory do
399
        helper.perform_actions(args[0],options,"Hot resizing memory") do |vm|
400
            vm.memset(args[1])
401
        end
402
    end
403

  
404
    vcpuset_desc = <<-EOT.unindent
405
        Change the number of VCPUs of the given VM online
406

  
407
        States: RUNNING
408
    EOT
409

  
410
    command :vcpuset, vcpuset_desc, [:range,:vmid_list], :vcpu do
411
        helper.perform_actions(args[0],options,"Hotpluging/Hotunplugin VCPUs") do |vm|
412
            vm.vcpuset(args[1])
413
        end
414
    end
383 415
end
src/dm/DispatchManagerActions.cc
697 697

  
698 698
    return rc;
699 699
}
700

  
701
/* -------------------------------------------------------------------------- */
702
/* -------------------------------------------------------------------------- */
703

  
704
int DispatchManager::memset (
705
    VirtualMachine *    vm)
706
{
707
    ostringstream oss;
708
    int           vid;
709

  
710
    if ( vm == 0 )
711
    {
712
        return -1;
713
    }
714

  
715
    vid = vm->get_oid();
716

  
717
    oss << "Scaling memory of VM " << vid;
718
    NebulaLog::log("DiM",Log::DEBUG,oss);
719

  
720
    if ( vm->get_state() == VirtualMachine::RUNNING )
721
    {
722
        Nebula&             nd  = Nebula::instance();
723
        LifeCycleManager *  lcm = nd.get_lcm();
724

  
725
        lcm->trigger(LifeCycleManager::SCALE_MEMORY,vid);
726
    }
727
    else
728
    {
729
        goto error;
730
    }
731

  
732
    vm->unlock();
733

  
734
    return 0;
735

  
736
error:
737

  
738
    oss.str("");
739
    oss << "Could not scale the memory of VM " << vid << ", wrong state.";
740
    NebulaLog::log("DiM",Log::ERROR,oss);
741

  
742
    vm->unlock();
743
    return -1;
744
}
745

  
746
/* -------------------------------------------------------------------------- */
747
/* -------------------------------------------------------------------------- */
748

  
749
int DispatchManager::vcpuset (
750
    VirtualMachine *    vm)
751
{
752
    ostringstream oss;
753
    int           vid;
754

  
755
    if ( vm == 0 )
756
    {
757
        return -1;
758
    }
759

  
760
    vid = vm->get_oid();
761

  
762
    oss << "Scaling the number of VCPUs of VM " << vid;
763
    NebulaLog::log("DiM",Log::DEBUG,oss);
764

  
765
    if ( vm->get_state() == VirtualMachine::RUNNING )
766
    {
767
        Nebula&             nd  = Nebula::instance();
768
        LifeCycleManager *  lcm = nd.get_lcm();
769

  
770
        lcm->trigger(LifeCycleManager::SCALE_VCPU,vid);
771
    }
772
    else
773
    {
774
        goto error;
775
    }
776

  
777
    vm->unlock();
778

  
779
    return 0;
780

  
781
error:
782

  
783
    oss.str("");
784
    oss << "Could not scale the number of VCPUs of VM " << vid << ", wrong state.";
785
    NebulaLog::log("DiM",Log::ERROR,oss);
786

  
787
    vm->unlock();
788
    return -1;
789
}
src/lcm/LifeCycleActions.cc
580 580

  
581 581
/* -------------------------------------------------------------------------- */
582 582
/* -------------------------------------------------------------------------- */
583
void  LifeCycleManager::scale_memory_action(int vid)
584
{
585
    VirtualMachine * vm;
586

  
587
    vm = vmpool->get(vid,true);
588

  
589
    if ( vm == 0 )
590
    {
591
        return;
592
    }
593

  
594
    if (vm->get_state() == VirtualMachine::ACTIVE &&
595
        vm->get_lcm_state() == VirtualMachine::RUNNING)
596
    {
597
        Nebula&           nd = Nebula::instance();
598
        VirtualMachineManager * vmm = nd.get_vmm();
599

  
600
        vm->log("LCM",Log::INFO,"Attempting to scale VM's memory");
601

  
602
        vmm->trigger(VirtualMachineManager::SCALE_MEMORY,vid);
603
    }
604
    else
605
    {
606
        vm->log("LCM", Log::ERROR, "scale_memory_action, VM in a wrong state.");
607
    }
608

  
609
    vm->unlock();
610

  
611
    return;
612
}
613

  
614
/* -------------------------------------------------------------------------- */
615
/* -------------------------------------------------------------------------- */
616
void  LifeCycleManager::scale_vcpu_action(int vid)
617
{
618
    VirtualMachine * vm;
619

  
620
    vm = vmpool->get(vid,true);
621

  
622
    if ( vm == 0 )
623
    {
624
        return;
625
    }
626

  
627
    if (vm->get_state() == VirtualMachine::ACTIVE &&
628
        vm->get_lcm_state() == VirtualMachine::RUNNING)
629
    {
630
        Nebula&           nd = Nebula::instance();
631
        VirtualMachineManager * vmm = nd.get_vmm();
632

  
633
        vm->log("LCM",Log::INFO,"Attempting to scale VM's number of VCPUs");
634

  
635
        vmm->trigger(VirtualMachineManager::SCALE_VCPU,vid);
636
    }
637
    else
638
    {
639
        vm->log("LCM", Log::ERROR, "scale_vcpu_action, VM in a wrong state.");
640
    }
641

  
642
    vm->unlock();
643

  
644
    return;
645
}
646

  
647
/* -------------------------------------------------------------------------- */
648
/* -------------------------------------------------------------------------- */
583 649

  
584 650
void  LifeCycleManager::clean_up_vm(VirtualMachine * vm)
585 651
{
......
696 762
        case VirtualMachine::FAILURE:
697 763
            tm->trigger(TransferManager::EPILOG_DELETE,vid);
698 764
        break;
699
        
765

  
700 766
        default: //LCM_INIT,CLEANUP
701 767
        break;
702 768
    }
src/lcm/LifeCycleManager.cc
113 113
        aname = "MONITOR_DONE";
114 114
        break;
115 115

  
116
    case SCALE_MEMORY_SUCCESS:
117
        aname = "SCALE_MEMORY_SUCCESS";
118
        break;
119

  
120
    case SCALE_MEMORY_FAILURE:
121
        aname = "SCALE_MEMORY_FAILURE";
122
        break;
123

  
124
    case SCALE_VCPU_SUCCESS:
125
        aname = "SCALE_VCPU_SUCCESS";
126
        break;
127

  
128
    case SCALE_VCPU_FAILURE:
129
        aname = "SCALE_VCPU_FAILURE";
130
        break;
131

  
116 132
    case PROLOG_SUCCESS:
117 133
        aname = "PROLOG_SUCCESS";
118 134
        break;
......
177 193
        aname = "CLEAN";
178 194
        break;
179 195

  
196
    case SCALE_MEMORY:
197
        aname = "SCALE_MEMORY";
198
        break;
199

  
200
    case SCALE_VCPU:
201
        aname = "SCALE_VCPU";
202
        break;
203

  
180 204
    case FINALIZE:
181 205
        aname = ACTION_FINALIZE;
182 206
        break;
......
250 274
    {
251 275
        monitor_done_action(vid);
252 276
    }
277
    else if (action == "SCALE_MEMORY_SUCCESS")
278
    {
279
        scale_memory_success_action(vid);
280
    }
281
    else if (action == "SCALE_MEMORY_FAILURE")
282
    {
283
        scale_memory_failure_action(vid);
284
    }
285
    else if (action == "SCALE_VCPU_SUCCESS")
286
    {
287
        scale_vcpu_success_action(vid);
288
    }
289
    else if (action == "SCALE_VCPU_FAILURE")
290
    {
291
        scale_vcpu_failure_action(vid);
292
    }
253 293
    else if (action == "PROLOG_SUCCESS")
254 294
    {
255 295
        prolog_success_action(vid);
......
314 354
    {
315 355
        clean_action(vid);
316 356
    }
357
    else if (action == "SCALE_MEMORY")
358
    {
359
        scale_memory_action(vid);
360
    }
361
    else if (action == "SCALE_VCPU")
362
    {
363
        scale_vcpu_action(vid);
364
    }
317 365
    else if (action == ACTION_FINALIZE)
318 366
    {
319 367
        NebulaLog::log("LCM",Log::INFO,"Stopping Life-cycle Manager...");
src/lcm/LifeCycleStates.cc
771 771
    vm->unlock();
772 772
}
773 773

  
774
/* -------------------------------------------------------------------------- */
775
/* -------------------------------------------------------------------------- */
776

  
777
void  LifeCycleManager::scale_memory_success_action(int vid)
778
{
779
    Nebula&             nd = Nebula::instance();
780
    VirtualMachine *    vm;
781

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

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

  
789
    vm->log("LCM", Log::INFO, "Attempt to scale VM memory succeed");
790

  
791
    vm->unlock();
792
}
793

  
794
/* -------------------------------------------------------------------------- */
795
/* -------------------------------------------------------------------------- */
796

  
797
void  LifeCycleManager::scale_memory_failure_action(int vid)
798
{
799
    Nebula&             nd = Nebula::instance();
800
    VirtualMachine *    vm;
801

  
802
    vm = vmpool->get(vid,true);
803

  
804
    if ( vm == 0 )
805
    {
806
        return;
807
    }
808

  
809
    /**
810
     * In case of failure, we can't do much...
811
     * - In case the VM's still running, we don't want to mark it
812
     *   as failed and/or unsable.
813
     * - If the amount of memory effectively changed but not enought
814
     *   to reach the target, we want to take into account the biggest
815
     *   possible amount of memory the VM is using to not mess with
816
     *   the scheduler.
817
     *
818
     * I'm not aware of a better way to inform the user of the failure
819
     * than using the logging mechanism.
820
     *
821
     * FIXME Better inform the user of the failure
822
     */
823

  
824
    // FIXME In case of scaling down, save the previous amount of memory
825

  
826
    vm->log("LCM", Log::ERROR, "Attempt to scale VM memory failed");
827

  
828
    vm->unlock();
829
}
830

  
831
/* -------------------------------------------------------------------------- */
832
/* -------------------------------------------------------------------------- */
833

  
834
void  LifeCycleManager::scale_vcpu_success_action(int vid)
835
{
836
    Nebula&             nd = Nebula::instance();
837
    VirtualMachine *    vm;
838

  
839
    vm = vmpool->get(vid,true);
840

  
841
    if ( vm == 0 )
842
    {
843
        return;
844
    }
845

  
846
    vm->log("LCM", Log::INFO, "Attempt to scale VM number of VCPUs succeed");
847

  
848
    vm->unlock();
849
}
850

  
851
/* -------------------------------------------------------------------------- */
852
/* -------------------------------------------------------------------------- */
853

  
854
void  LifeCycleManager::scale_vcpu_failure_action(int vid)
855
{
856
    Nebula&             nd = Nebula::instance();
857
    VirtualMachine *    vm;
858

  
859
    int memory = -1;
860
    int cpu    = -1;
861
    int net_tx = -1;
862
    int net_rx = -1;
863

  
864
    vm = vmpool->get(vid,true);
865

  
866
    if ( vm == 0 )
867
    {
868
        return;
869
    }
870

  
871
     /**
872
     * In case of failure, we can't do much...
873
     * - In case the VM's still running, we don't want to mark it
874
     *   as failed and/or unsable.
875
     * - We don't know how many VCPUs the VM has access to. As the
876
     *   number of VCPUs doesn't have an impact on VM scheduling (AFAIK)
877
     *   we set it to 0 so that the user might see that something went
878
     *   wrong.
879
     *
880
     * I'm not aware of a better way to inform the user of the failure
881
     * than using the logging mechanism.
882
     *
883
     * FIXME Better inform the user of the failure
884
     */
885

  
886
    vm->get_template_attribute("MEMORY",memory);
887
    vm->get_template_attribute("CPU",cpu);
888
    vm->get_template_attribute("NET_TX",net_tx);
889
    vm->get_template_attribute("NET_RX",net_rx);
890

  
891
    vm->update_info(memory,cpu,0,net_tx,net_rx);
892

  
893
    vm->log("LCM", Log::ERROR, "Attempt to scale VM number of VCPUs failed");
894

  
895
    vm->unlock();
896
}
774 897

  
775 898
/* -------------------------------------------------------------------------- */
776 899
/* -------------------------------------------------------------------------- */
src/mad/ruby/VirtualMachineDriver.rb
30 30

  
31 31
    # Virtual Machine Driver Protocol constants
32 32
    ACTION = {
33
        :deploy     => "DEPLOY",
34
        :shutdown   => "SHUTDOWN",
35
        :reboot     => "REBOOT",
36
        :cancel     => "CANCEL",
37
        :save       => "SAVE",
38
        :restore    => "RESTORE",
39
        :migrate    => "MIGRATE",
40
        :poll       => "POLL",
41
        :log        => "LOG"
33
        :deploy         => "DEPLOY",
34
        :shutdown       => "SHUTDOWN",
35
        :reboot         => "REBOOT",
36
        :cancel         => "CANCEL",
37
        :save           => "SAVE",
38
        :restore        => "RESTORE",
39
        :migrate        => "MIGRATE",
40
        :poll           => "POLL",
41
        :log            => "LOG",
42
        :scale_memory   => "SCALE_MEMORY",
43
        :scale_vcpu     => "SCALE_VCPU"
42 44
    }
43 45

  
44 46
    POLL_ATTRIBUTE = {
......
75 77

  
76 78
        @hosts   = Array.new
77 79

  
78
        register_action(ACTION[:deploy].to_sym,     method("deploy"))
79
        register_action(ACTION[:shutdown].to_sym,   method("shutdown"))
80
        register_action(ACTION[:reboot].to_sym,     method("reboot"))
81
        register_action(ACTION[:cancel].to_sym,     method("cancel"))
82
        register_action(ACTION[:save].to_sym,       method("save"))
83
        register_action(ACTION[:restore].to_sym,    method("restore"))
84
        register_action(ACTION[:migrate].to_sym,    method("migrate"))
85
        register_action(ACTION[:poll].to_sym,       method("poll"))
80
        register_action(ACTION[:deploy].to_sym,         method("deploy"))
81
        register_action(ACTION[:shutdown].to_sym,       method("shutdown"))
82
        register_action(ACTION[:reboot].to_sym,         method("reboot"))
83
        register_action(ACTION[:cancel].to_sym,         method("cancel"))
84
        register_action(ACTION[:save].to_sym,           method("save"))
85
        register_action(ACTION[:restore].to_sym,        method("restore"))
86
        register_action(ACTION[:migrate].to_sym,        method("migrate"))
87
        register_action(ACTION[:scale_memory].to_sym,   method("scale_memory"))
88
        register_action(ACTION[:scale_vcpu].to_sym,     method("scale_vcpu"))
89
        register_action(ACTION[:poll].to_sym,           method("poll"))
86 90
    end
87 91

  
88 92
    # Decodes the encoded XML driver message received from the core
......
142 146
        send_message(ACTION[:migrate],RESULT[:failure],id,error)
143 147
    end
144 148

  
149
    def scale_memory(id, drv_message)
150
        error = "Action not implemented by driver #{self.class}"
151
        send_message(ACTION[:scale_memory],RESULT[:failure],id,error)
152
    end
153

  
154
    def scale_vcpu(id, drv_message)
155
        error = "Action not implemented by driver #{self.class}"
156
        send_message(ACTION[:scale_vcpu],RESULT[:failure],id,error)
157
    end
158

  
145 159
    def poll(id, drv_message)
146 160
        error = "Action not implemented by driver #{self.class}"
147 161
        send_message(ACTION[:poll],RESULT[:failure],id,error)
......
234 248
            send_message(ACTION[:migrate],RESULT[:success],id)
235 249
        end
236 250

  
251
        def scale_memory(id, host, deploy_id, memory)
252
            send_message(ACTION[:scale_memory],RESULT[:success],id)
253
        end
254

  
255
        def scale_vcpu(id, host, deploy_id, vcpu)
256
            send_message(ACTION[:scale_vcpu],RESULT[:success],id)
257
        end
258

  
237 259
        def poll(id, host, deploy_id, not_used)
238 260
            # monitor_info: string in the form "VAR=VAL VAR=VAL ... VAR=VAL"
239 261
            # known VAR are in POLL_ATTRIBUTES. VM states VM_STATES
src/oca/ruby/OpenNebula/VirtualMachine.rb
33 33
            :savedisk => "vm.savedisk",
34 34
            :chown    => "vm.chown",
35 35
            :chmod    => "vm.chmod",
36
            :memset   => "vm.memset",
37
            :vcpuset  => "vm.vcpuset",
36 38
        }
37 39

  
38
        VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED}
40
        VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED MUTATING}
39 41

  
40 42
        LCM_STATE=%w{LCM_INIT PROLOG BOOT RUNNING MIGRATE SAVE_STOP SAVE_SUSPEND
41 43
            SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG
......
49 51
            "STOPPED"   => "stop",
50 52
            "SUSPENDED" => "susp",
51 53
            "DONE"      => "done",
52
            "FAILED"    => "fail"
54
            "FAILED"    => "fail",
55
            "MUTATING"  => "muta"
53 56
        }
54 57

  
55 58
        SHORT_LCM_STATES={
......
265 268
                group_m, group_a, other_u, other_m, other_a)
266 269
        end
267 270

  
271
        # Change the amount of memory of the given VM online
272
        def memset(memory)
273
            return Error.new('ID not defined') if !@pe_id
274

  
275
            rc = @client.call(VM_METHODS[:memset], @pe_id, memory.to_i)
276
            rc = nil if !OpenNebula.is_error?(rc)
277

  
278
            return rc
279
        end
280

  
281
        # Change the number of VPUs of the given VM online
282
        def vcpuset(vcpu)
283
            return Error.new('ID not defined') if !@pe_id
284

  
285
            rc = @client.call(VM_METHODS[:vcpuset], @pe_id, vcpu.to_i)
286
            rc = nil if !OpenNebula.is_error?(rc)
287

  
288
            return rc
289
        end
290

  
268 291
        #######################################################################
269 292
        # Helpers to get VirtualMachine information
270 293
        #######################################################################
src/rm/RequestManager.cc
242 242
    xmlrpc_c::methodPtr vm_migrate(new VirtualMachineMigrate());
243 243
    xmlrpc_c::methodPtr vm_action(new VirtualMachineAction()); 
244 244
    xmlrpc_c::methodPtr vm_savedisk(new VirtualMachineSaveDisk());
245
    xmlrpc_c::methodPtr vm_memset(new VirtualMachineMemSet());
246
    xmlrpc_c::methodPtr vm_vcpuset(new VirtualMachineVcpuSet());
245 247

  
246 248
    // VirtualNetwork Methods
247 249
    xmlrpc_c::methodPtr vn_addleases(new VirtualNetworkAddLeases());
......
345 347
    RequestManagerRegistry.addMethod("one.vm.info", vm_info);
346 348
    RequestManagerRegistry.addMethod("one.vm.chown", vm_chown);
347 349
    RequestManagerRegistry.addMethod("one.vm.chmod", vm_chmod);
350
    RequestManagerRegistry.addMethod("one.vm.memset", vm_memset);
351
    RequestManagerRegistry.addMethod("one.vm.vcpuset", vm_vcpuset);
348 352

  
349 353
    RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
350 354

  
src/rm/RequestManagerVirtualMachine.cc
17 17
#include "RequestManagerVirtualMachine.h"
18 18
#include "PoolObjectAuth.h"
19 19
#include "Nebula.h"
20
#include "ostream"
20 21

  
21 22
/* -------------------------------------------------------------------------- */
22 23
/* -------------------------------------------------------------------------- */
......
86 87
/* -------------------------------------------------------------------------- */
87 88
/* -------------------------------------------------------------------------- */
88 89

  
89
int RequestManagerVirtualMachine::get_host_information(int hid, 
90
                                                string& name, 
90
int RequestManagerVirtualMachine::get_host_information(int hid,
91
                                                string& name,
91 92
                                                string& vmm,
92 93
                                                string& vnm,
93 94
                                                RequestAttributes& att,
......
553 554

  
554 555
/* -------------------------------------------------------------------------- */
555 556
/* -------------------------------------------------------------------------- */
557

  
558
void VirtualMachineMemSet::request_execute(xmlrpc_c::paramList const& paramList,
559
                                             RequestAttributes& att)
560
{
561
    Nebula&     nd    = Nebula::instance();
562
    DispatchManager *   dm = nd.get_dm();
563

  
564
    int    id      = xmlrpc_c::value_int(paramList.getInt(1));
565
    int    memory  = xmlrpc_c::value_int(paramList.getInt(2));
566

  
567
    VirtualMachine * vm;
568
    string           vm_owner;
569

  
570
    int           rc;
571
    string        error_str;
572
    char *        error_char;
573

  
574
    if ( vm_authorization(id, 0, att, 0, 0) == false )
575
    {
576
        return;
577
    }
578

  
579
    if ( (vm = get_vm(id, att)) == 0 )
580
    {
581
        return;
582
    }
583

  
584
    if ( vm->get_state() != VirtualMachine::RUNNING )
585
    {
586
        failure_response(ACTION,
587
                request_error("Wrong state to perform action",""),
588
                att);
589

  
590
        vm->unlock();
591
        return;
592
    }
593

  
594
    // TODO Log action in VM History or in other VM attributes
595

  
596
    vm->update_info(memory,-1,-1,-1,-1);
597

  
598
    dm->memset(vm);
599

  
600
    vm->unlock();
601

  
602
    success_response(id, att);
603
}
604

  
605
/* -------------------------------------------------------------------------- */
606
/* -------------------------------------------------------------------------- */
607

  
608
void VirtualMachineVcpuSet::request_execute(xmlrpc_c::paramList const& paramList,
609
                                             RequestAttributes& att)
610
{
611
    Nebula&     nd    = Nebula::instance();
612
    DispatchManager *   dm = nd.get_dm();
613

  
614
    int    id      = xmlrpc_c::value_int(paramList.getInt(1));
615
    int    vcpu  = xmlrpc_c::value_int(paramList.getInt(2));
616

  
617
    VirtualMachine * vm;
618
    string           vm_owner;
619

  
620
    int           rc;
621
    string        error_str;
622
    char *        error_char;
623

  
624
    if ( vm_authorization(id, 0, att, 0, 0) == false )
625
    {
626
        return;
627
    }
628

  
629
    if ( (vm = get_vm(id, att)) == 0 )
630
    {
631
        return;
632
    }
633

  
634
    if ( vm->get_state() != VirtualMachine::RUNNING )
635
    {
636
        failure_response(ACTION,
637
                request_error("Wrong state to perform action",""),
638
                att);
639

  
640
        vm->unlock();
641
        return;
642
    }
643

  
644
    // TODO Log action in VM History or in other VM attributes
645

  
646
    vm->update_info(-1,-1,vcpu,-1,-1);
647

  
648
    dm->vcpuset(vm);
649

  
650
    vm->unlock();
651

  
652
    success_response(id, att);
653
}
654

  
655
/* -------------------------------------------------------------------------- */
656
/* -------------------------------------------------------------------------- */
src/vm/VirtualMachine.cc
52 52
        deploy_id(""),
53 53
        memory(0),
54 54
        cpu(0),
55
        vcpu(0),
55 56
        net_tx(0),
56 57
        net_rx(0),
57 58
        history(0),
......
1449 1450
        << "<DEPLOY_ID>" << deploy_id << "</DEPLOY_ID>"
1450 1451
        << "<MEMORY>"    << memory    << "</MEMORY>"
1451 1452
        << "<CPU>"       << cpu       << "</CPU>"
1453
        << "<VCPU>"      << vcpu      << "</VCPU>"
1452 1454
        << "<NET_TX>"    << net_tx    << "</NET_TX>"
1453 1455
        << "<NET_RX>"    << net_rx    << "</NET_RX>"
1454 1456
        << obj_template->to_xml(template_xml);
......
1517 1519

  
1518 1520
    rc += xpath(memory,    "/VM/MEMORY",   0);
1519 1521
    rc += xpath(cpu,       "/VM/CPU",      0);
1522
    rc += xpath(vcpu,      "/VM/VCPU",     0);
1520 1523
    rc += xpath(net_tx,    "/VM/NET_TX",   0);
1521 1524
    rc += xpath(net_rx,    "/VM/NET_RX",   0);
1522 1525

  
src/vmm/VirtualMachineManager.cc
146 146
        aname = "MIGRATE";
147 147
        break;
148 148

  
149
    case SCALE_MEMORY:
150
        aname = "SCALE_MEMORY";
151
        break;
152

  
153
    case SCALE_VCPU:
154
        aname = "SCALE_VCPU";
155
        break;
156

  
149 157
    case POLL:
150 158
        aname = "POLL";
151 159
        break;
......
180 188
        {
181 189
            return;
182 190
        }
183
        
191

  
184 192
        vid = -1;
185 193
    }
186 194
    else
......
222 230
    {
223 231
        migrate_action(vid);
224 232
    }
233
    else if (action == "SCALE_MEMORY")
234
    {
235
        scale_memory_action(vid);
236
    }
237
    else if (action == "SCALE_VCPU")
238
    {
239
        scale_vcpu_action(vid);
240
    }
225 241
    else if (action == "POLL")
226 242
    {
227 243
        poll_action(vid);
......
259 275
    const string& m_hostname,
... This diff was truncated because it exceeds the maximum size that can be displayed.