Skip to content

Commit 9ddc51e

Browse files
author
Miha Pleško
committed
Power operations on VM: start, stop and suspend
With this commit we implement power operations on a VM. Signed-off-by: Miha Pleško <miha.plesko@xlab.si>
1 parent c53a6fe commit 9ddc51e

File tree

5 files changed

+88
-35
lines changed

5 files changed

+88
-35
lines changed

app/models/manageiq/providers/azure_stack/cloud_manager/vm.rb

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
class ManageIQ::Providers::AzureStack::CloudManager::Vm < ManageIQ::Providers::CloudManager::Vm
2+
include ManageIQ::Providers::AzureStack::EmsRefMixin
23

34
POWER_STATES = {
45
'PowerState/running' => 'on',
@@ -10,37 +11,27 @@ class ManageIQ::Providers::AzureStack::CloudManager::Vm < ManageIQ::Providers::C
1011
'PowerState/unknown' => 'unknown'
1112
}.freeze
1213

13-
def provider_object(connection = nil)
14-
connection ||= ext_management_system.connect
15-
# find vm instance via connection and return it
16-
# connection.find_instance(ems_ref)
17-
# but we return just an object for now
18-
OpenStruct.new
19-
end
20-
2114
def raw_start
22-
with_provider_object(&:start)
23-
# Temporarily update state for quick UI response until refresh comes along
24-
update_attributes!(:raw_power_state => "on")
15+
with_provider_connection(:service => :Compute) do |client|
16+
client.virtual_machines.start(resource_group_name(ems_ref), name)
17+
end
18+
update!(:raw_power_state => 'PowerState/running')
2519
end
2620

2721
def raw_stop
28-
with_provider_object(&:stop)
29-
# Temporarily update state for quick UI response until refresh comes along
30-
update_attributes!(:raw_power_state => "off")
31-
end
32-
33-
def raw_pause
34-
with_provider_object(&:pause)
35-
# Temporarily update state for quick UI response until refresh comes along
36-
update_attributes!(:raw_power_state => "paused")
22+
with_provider_connection(:service => :Compute) do |client|
23+
client.virtual_machines.deallocate(resource_group_name(ems_ref), name)
24+
end
25+
update!(:raw_power_state => 'PowerState/deallocated')
3726
end
3827

3928
def raw_suspend
40-
with_provider_object(&:suspend)
41-
# Temporarily update state for quick UI response until refresh comes along
42-
update_attributes!(:raw_power_state => "suspended")
29+
with_provider_connection(:service => :Compute) do |client|
30+
client.virtual_machines.stop(resource_group_name(ems_ref), name)
31+
end
32+
update!(:raw_power_state => 'PowerState/stopped')
4333
end
34+
alias raw_pause raw_suspend
4435

4536
def self.calculate_power_state(raw_power_state)
4637
# https://docs.microsoft.com/en-us/azure/virtual-machines/windows/states-lifecycle
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module ManageIQ::Providers::AzureStack::EmsRefMixin
2+
extend ActiveSupport::Concern
3+
4+
def resource_group_name(ems_ref)
5+
if (match = ems_ref.match(%r{/subscriptions/[^/]+/resourceGroups/(?<name>[^/]+)/.+}i))
6+
match[:name].downcase
7+
end
8+
end
9+
10+
def resource_group_id(ems_ref)
11+
if (match = ems_ref.match(%r{(?<id>/subscriptions/[^/]+/resourceGroups/[^/]+)/.+}i))
12+
match[:id].downcase
13+
end
14+
end
15+
end

app/models/manageiq/providers/azure_stack/inventory/collector.rb

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
class ManageIQ::Providers::AzureStack::Inventory::Collector < ManageIQ::Providers::Inventory::Collector
22
require_nested :CloudManager
33

4+
include ManageIQ::Providers::AzureStack::EmsRefMixin
5+
46
def initialize(manager, refresh_target)
57
super(manager, refresh_target)
68
@token = nil
@@ -24,18 +26,6 @@ def with_shared_token
2426
client
2527
end
2628

27-
def resource_group_name(ems_ref)
28-
if (match = ems_ref.match(%r{/subscriptions/[^/]+/resourceGroups/(?<name>[^/]+)/.+}))
29-
match[:name].downcase
30-
end
31-
end
32-
33-
def resource_group_id(ems_ref)
34-
if (match = ems_ref.match(%r{(?<id>/subscriptions/[^/]+/resourceGroups/[^/]+)/.+}))
35-
match[:id].downcase
36-
end
37-
end
38-
3929
def raw_power_state(instance_view)
4030
instance_view&.statuses&.detect { |s| s.code.start_with?('PowerState/') }&.code
4131
end

spec/factories/vm.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FactoryBot.define do
2+
factory :vm_azure_stack, :class => 'ManageIQ::Providers::AzureStack::CloudManager::Vm', :parent => :vm_cloud do
3+
sequence(:name) { |n| "VM#{n}" }
4+
sequence(:ems_ref) do |n|
5+
"/subscriptions/11111111-2222-3333-4444-555555555555/resourceGroups/RESOURCE_GROUP/providers/Microsoft.Compute/virtualMachines/VM#{n}"
6+
end
7+
raw_power_state { 'PowerState/running' }
8+
end
9+
end
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
describe ManageIQ::Providers::AzureStack::CloudManager::Vm do
2+
before { allow(subject).to receive(:with_provider_connection).with(:service => :Compute).and_yield(client) }
3+
4+
let(:client) { double('compute', :virtual_machines => actions) }
5+
let(:actions) { double('actions') }
6+
7+
subject { FactoryBot.create(:vm_azure_stack, :raw_power_state => 'unknown') }
8+
9+
describe '#raw_start' do
10+
it 'invokes' do
11+
expect(subject.power_state).to eq('unknown')
12+
expect(actions).to receive(:start).with('resource_group', subject.name)
13+
subject.raw_start
14+
subject.reload
15+
expect(subject.power_state).to eq('on')
16+
end
17+
end
18+
19+
describe '#raw_stop' do
20+
it 'invokes' do
21+
expect(subject.power_state).to eq('unknown')
22+
expect(actions).to receive(:deallocate).with('resource_group', subject.name)
23+
subject.raw_stop
24+
subject.reload
25+
expect(subject.power_state).to eq('off')
26+
end
27+
end
28+
29+
describe '#raw_suspend' do
30+
it 'invokes' do
31+
expect(subject.power_state).to eq('unknown')
32+
expect(actions).to receive(:stop).with('resource_group', subject.name)
33+
subject.raw_suspend
34+
subject.reload
35+
expect(subject.power_state).to eq('suspended')
36+
end
37+
end
38+
39+
describe '#raw_pause' do
40+
it 'invokes' do
41+
expect(subject.power_state).to eq('unknown')
42+
expect(actions).to receive(:stop).with('resource_group', subject.name)
43+
subject.raw_pause
44+
subject.reload
45+
expect(subject.power_state).to eq('suspended')
46+
end
47+
end
48+
end

0 commit comments

Comments
 (0)