vagrant-azure 1.3.0 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +5 -6
  5. data/LICENSE +21 -4
  6. data/README.md +36 -178
  7. data/Rakefile +3 -5
  8. data/example_box/Vagrantfile +7 -8
  9. data/lib/vagrant-azure/action/connect_azure.rb +9 -30
  10. data/lib/vagrant-azure/action/is_created.rb +19 -0
  11. data/lib/vagrant-azure/action/is_stopped.rb +19 -0
  12. data/lib/vagrant-azure/action/message_already_created.rb +19 -0
  13. data/lib/vagrant-azure/action/message_not_created.rb +19 -0
  14. data/lib/vagrant-azure/action/message_will_not_destroy.rb +19 -0
  15. data/lib/vagrant-azure/action/read_ssh_info.rb +13 -33
  16. data/lib/vagrant-azure/action/read_state.rb +28 -26
  17. data/lib/vagrant-azure/action/restart_vm.rb +11 -11
  18. data/lib/vagrant-azure/action/run_instance.rb +164 -80
  19. data/lib/vagrant-azure/action/start_instance.rb +34 -15
  20. data/lib/vagrant-azure/action/stop_instance.rb +36 -21
  21. data/lib/vagrant-azure/action/terminate_instance.rb +18 -14
  22. data/lib/vagrant-azure/action/wait_for_state.rb +17 -23
  23. data/lib/vagrant-azure/action.rb +49 -124
  24. data/lib/vagrant-azure/config.rb +107 -111
  25. data/lib/vagrant-azure/errors.rb +9 -11
  26. data/lib/vagrant-azure/plugin.rb +8 -32
  27. data/lib/vagrant-azure/provider.rb +7 -29
  28. data/lib/vagrant-azure/services/azure_resource_manager.rb +80 -0
  29. data/lib/vagrant-azure/util/machine_id_helper.rb +20 -0
  30. data/lib/vagrant-azure/util/timer.rb +15 -0
  31. data/lib/vagrant-azure/util/vm_await.rb +36 -0
  32. data/lib/vagrant-azure/util/vm_status_translator.rb +59 -0
  33. data/lib/vagrant-azure/version.rb +5 -7
  34. data/lib/vagrant-azure.rb +4 -9
  35. data/locales/en.yml +74 -3
  36. data/spec/spec_helper.rb +40 -0
  37. data/spec/vagrant-azure/config_spec.rb +18 -0
  38. data/spec/vagrant-azure/services/azure_resource_manager_spec.rb +19 -0
  39. data/templates/arm/deployment.json.erb +264 -0
  40. data/vagrant-azure.gemspec +19 -14
  41. metadata +96 -51
  42. data/lib/vagrant-azure/action/os_type.rb +0 -34
  43. data/lib/vagrant-azure/action/powershell_run.rb +0 -28
  44. data/lib/vagrant-azure/action/rdp.rb +0 -63
  45. data/lib/vagrant-azure/action/read_winrm_info.rb +0 -57
  46. data/lib/vagrant-azure/action/sync_folders.rb +0 -64
  47. data/lib/vagrant-azure/action/vagrant_azure_service.rb +0 -44
  48. data/lib/vagrant-azure/capabilities/winrm.rb +0 -12
  49. data/lib/vagrant-azure/command/powershell.rb +0 -43
  50. data/lib/vagrant-azure/command/rdp.rb +0 -24
  51. data/lib/vagrant-azure/driver.rb +0 -48
  52. data/lib/vagrant-azure/monkey_patch/winrm.rb +0 -12
@@ -1,46 +1,48 @@
1
- #--------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache License, Version 2.0.
4
- # See License.txt in the project root for license information.
5
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
6
4
  require 'log4r'
5
+ require 'vagrant-azure/util/vm_status_translator'
6
+ require 'vagrant-azure/util/machine_id_helper'
7
7
 
8
8
  module VagrantPlugins
9
- module WinAzure
9
+ module Azure
10
10
  module Action
11
11
  class ReadState
12
+ include VagrantPlugins::Azure::Util::VMStatusTranslator
13
+ include VagrantPlugins::Azure::Util::MachineIdHelper
14
+
12
15
  def initialize(app, env)
13
16
  @app = app
14
17
  @logger = Log4r::Logger.new('vagrant_azure::action::read_state')
15
18
  end
16
19
 
17
20
  def call(env)
18
- env[:machine_state_id] = read_state(env)
19
-
21
+ env[:machine_state_id] = read_state(env[:azure_arm_service], env[:machine])
20
22
  @app.call(env)
21
23
  end
22
24
 
23
- def read_state(env)
24
- env[:machine].id = "#{env[:machine].provider_config.vm_name}@#{env[:machine].provider_config.cloud_service_name}" unless env[:machine].id
25
-
26
- env[:machine].id =~ /@/
27
-
28
- env[:ui].info "Attempting to read state for #{$`} in #{$'}"
29
-
30
- vm = env[:azure_vm_service].get_virtual_machine($`, $')
31
-
32
- if vm.nil? || \
33
- !vm.instance_of?(Azure::VirtualMachineManagement::VirtualMachine) || \
34
- [ :DeletingVM ].include?(vm.status.to_sym)
35
- # Machine can't be found
36
- @logger.info 'Machine cannot be found'
37
- env[:machine].id = nil
38
- return :NotCreated
25
+ def read_state(azure, machine)
26
+ return :not_created if machine.id.nil?
27
+
28
+ # Find the machine
29
+ parsed = parse_machine_id(machine.id)
30
+ vm = nil
31
+ begin
32
+ vm = azure.compute.virtual_machines.get(parsed[:group], parsed[:name], 'instanceView').value!.body
33
+ rescue MsRestAzure::AzureOperationError => ex
34
+ if vm.nil? || tearing_down?(vm.properties.instance_view.statuses)
35
+ # The machine can't be found
36
+ @logger.info('Machine not found or terminated, assuming it got destroyed.')
37
+ machine.id = nil
38
+ return :not_created
39
+ end
39
40
  end
40
41
 
41
- env[:ui].info "VM Status: #{vm.status.to_sym}"
42
- return vm.status.to_sym
42
+ # Return the state
43
+ power_state(vm.properties.instance_view.statuses)
43
44
  end
45
+
44
46
  end
45
47
  end
46
48
  end
@@ -1,25 +1,25 @@
1
- #--------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache License, Version 2.0.
4
- # See License.txt in the project root for license information.
5
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
6
4
  require 'log4r'
5
+ require 'vagrant-azure/util/machine_id_helper'
7
6
 
8
7
  module VagrantPlugins
9
- module WinAzure
8
+ module Azure
10
9
  module Action
11
10
  class RestartVM
11
+ include VagrantPlugins::Azure::Util::MachineIdHelper
12
+
12
13
  def initialize(app, env)
13
14
  @app = app
14
15
  @logger = Log4r::Logger.new('vagrant_azure::action::restart_vm')
15
16
  end
16
17
 
17
18
  def call(env)
18
- env[:machine].id =~ /@/
19
-
20
- env[:ui].info "Restarting #{$`} in #{$'}"
21
- env[:azure_vm_service].restart_virtual_machine($`, $')
22
-
19
+ parsed = parse_machine_id(env[:machine].id)
20
+ env[:ui].info(I18n.t('vagrant_azure.restarting', parsed))
21
+ env[:azure_arm_service].compute.virtual_machines.restart(parsed[:group], parsed[:name])
22
+ env[:ui].info(I18n.t('vagrant_azure.restarted', parsed))
23
23
  @app.call(env)
24
24
  end
25
25
  end
@@ -1,20 +1,20 @@
1
- #---------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache License, Version 2.0.
4
- # See License.txt in the project root for license information.
5
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
6
4
  require 'log4r'
7
5
  require 'json'
8
- require 'azure'
9
- require 'openssl'
10
-
11
- require 'vagrant/util/retryable'
6
+ require 'azure_mgmt_resources'
7
+ require 'vagrant/util/template_renderer'
8
+ require 'vagrant-azure/util/timer'
9
+ require 'vagrant-azure/util/machine_id_helper'
10
+ require 'haikunator'
12
11
 
13
12
  module VagrantPlugins
14
- module WinAzure
13
+ module Azure
15
14
  module Action
16
15
  class RunInstance
17
16
  include Vagrant::Util::Retryable
17
+ include VagrantPlugins::Azure::Util::MachineIdHelper
18
18
 
19
19
  def initialize(app, env)
20
20
  @app = app
@@ -22,97 +22,181 @@ module VagrantPlugins
22
22
  end
23
23
 
24
24
  def call(env)
25
- config = env[:machine].provider_config
26
-
27
- # Add the mandatory parameters and options
28
- params = {
29
- vm_name: config.vm_name,
30
- vm_user: config.vm_user,
31
- image: config.vm_image
32
- }
33
-
34
- options = {
35
- cloud_service_name: config.cloud_service_name
25
+ # Initialize metrics if they haven't been
26
+ env[:metrics] ||= {}
27
+
28
+ machine = env[:machine]
29
+
30
+ # Get the configs
31
+ config = machine.provider_config
32
+ endpoint = config.endpoint
33
+ resource_group_name = config.resource_group_name
34
+ location = config.location
35
+ vm_name = config.vm_name
36
+ vm_password = config.vm_password
37
+ vm_size = config.vm_size
38
+ vm_image_urn = config.vm_image_urn
39
+ virtual_network_name = config.virtual_network_name
40
+ subnet_name = config.subnet_name
41
+ tcp_endpoints = config.tcp_endpoints
42
+ availability_set_name = config.availability_set_name
43
+
44
+ # Launch!
45
+ env[:ui].info(I18n.t('vagrant_azure.launching_instance'))
46
+ env[:ui].info(" -- Management Endpoint: #{endpoint}")
47
+ env[:ui].info(" -- Subscription Id: #{config.subscription_id}")
48
+ env[:ui].info(" -- Resource Group Name: #{resource_group_name}")
49
+ env[:ui].info(" -- Location: #{location}")
50
+ env[:ui].info(" -- VM Name: #{vm_name}")
51
+ env[:ui].info(" -- VM Size: #{vm_size}")
52
+ env[:ui].info(" -- Image URN: #{vm_image_urn}")
53
+ env[:ui].info(" -- Virtual Network Name: #{virtual_network_name}") if virtual_network_name
54
+ env[:ui].info(" -- Subnet Name: #{subnet_name}") if subnet_name
55
+ env[:ui].info(" -- TCP Endpoints: #{tcp_endpoints}") if tcp_endpoints
56
+ env[:ui].info(" -- Availability Set Name: #{availability_set_name}") if availability_set_name
57
+
58
+ image_publisher, image_offer, image_sku, image_version = vm_image_urn.split(':')
59
+
60
+ azure = env[:azure_arm_service]
61
+ image_details = nil
62
+ env[:metrics]['get_image_details'] = Util::Timer.time do
63
+ image_details = get_image_details(azure, location, image_publisher, image_offer, image_sku, image_version)
64
+ end
65
+ @logger.info("Time to fetch os image details: #{env[:metrics]['get_image_details']}")
66
+
67
+ deployment_params = {
68
+ dnsLabelPrefix: Haikunator.haikunate(100),
69
+ vmSize: vm_size,
70
+ vmName: vm_name,
71
+ imagePublisher: image_publisher,
72
+ imageOffer: image_offer,
73
+ imageSku: image_sku,
74
+ imageVersion: image_version,
75
+ subnetName: subnet_name,
76
+ virtualNetworkName: virtual_network_name
36
77
  }
37
78
 
79
+ if get_image_os(image_details) != 'Windows'
80
+ private_key_paths = machine.config.ssh.private_key_path
81
+ if private_key_paths.empty?
82
+ raise I18n.t('vagrant_azure.private_key_not_specified')
83
+ end
38
84
 
39
- # Add the optional parameters and options if not nil
40
- params[:password] = config.vm_password unless config.vm_password.nil?
41
- params[:location] = config.vm_location unless config.vm_location.nil?
42
- params[:affinity_group] = config.vm_affinity_group unless config.vm_affinity_group.nil?
85
+ paths_to_pub = private_key_paths.map{ |k| File.expand_path( k + '.pub') }.select{ |p| File.exists?(p) }
86
+ raise I18n.t('vagrant_azure.public_key_path_private_key', private_key_paths.join(', ')) if paths_to_pub.empty?
87
+ deployment_params.merge!(sshKeyData: File.read(paths_to_pub.first))
88
+ end
43
89
 
44
- options[:storage_account_name] = config.storage_acct_name unless config.storage_acct_name.nil?
45
- options[:deployment_name] = config.deployment_name unless config.deployment_name.nil?
46
- options[:tcp_endpoints] = config.tcp_endpoints unless config.tcp_endpoints.nil?
90
+ template_params = {
91
+ operating_system: get_image_os(image_details)
92
+ }
47
93
 
48
- unless config.private_key_file.nil? && env[:machine].config.ssh.private_key_path.nil?
49
- options[:private_key_file] = File.expand_path(config.private_key_file || env[:machine].config.ssh.private_key_path.first)
94
+ env[:ui].info(" -- Create or Update of Resource Group: #{resource_group_name}")
95
+ env[:metrics]['put_resource_group'] = Util::Timer.time do
96
+ put_resource_group(azure, resource_group_name, location)
50
97
  end
98
+ @logger.info("Time to create resource group: #{env[:metrics]['put_resource_group']}")
51
99
 
52
- options[:ssh_port] = config.ssh_port unless config.ssh_port.nil?
53
- options[:vm_size] = config.vm_size unless config.vm_size.nil?
54
- options[:winrm_transport] = config.winrm_transport unless config.winrm_transport.nil?
55
- options[:winrm_http_port] = config.winrm_http_port unless config.winrm_http_port.nil?
56
- options[:winrm_https_port] = config.winrm_https_port unless config.winrm_https_port.nil?
57
- options[:availability_set_name] = config.availability_set_name unless config.availability_set_name.nil?
58
- options[:virtual_network_name] = config.vm_virtual_network_name unless config.vm_virtual_network_name.nil?
100
+ deployment_params = build_deployment_params(template_params, deployment_params.reject{|_,v| v.nil?})
59
101
 
60
-
61
- if params[:password] && options[:private_key_file]
62
- env[:ui].warn('You specified both a password and a private key file. The password will be used rather than ' +
63
- 'the private key. If you would like to use asymmetric key auth, do not specify a password.')
102
+ env[:ui].info('Starting deployment')
103
+ env[:metrics]['deployment_time'] = Util::Timer.time do
104
+ put_deployment(azure, resource_group_name, deployment_params)
64
105
  end
65
-
66
- add_role = false
67
-
68
- env[:ui].info(params.inspect)
69
- env[:ui].info(options.inspect)
70
-
71
- server = VagrantPlugins::WinAzure::CLOUD_SERVICE_SEMAPHORE.synchronize do
72
- # Check if the cloud service exists and if yes, does it contain
73
- # a deployment.
74
- if config.cloud_service_name && !config.cloud_service_name.empty?
75
- begin
76
- cloud_service = Azure::BaseManagement::ManagementHttpRequest.new(
77
- :get,
78
- "/services/hostedservices/#{config.cloud_service_name}?embed-detail=true"
79
- ).call
80
-
81
- deployments = cloud_service.css 'HostedService Deployments Deployment'
82
-
83
- # Lets see if any deployments exist. Set add_role = true if yes.
84
- # We're not worried about deployment slots, because the SDK has
85
- # hard coded 'Production' as deployment slot and you can have only
86
- # one deployment per deployment slot.
87
- add_role = deployments.length == 1
88
- rescue Exception => e
89
- add_role = false
106
+ env[:ui].info('Finished deploying')
107
+
108
+ # Immediately save the ID since it is created at this point.
109
+ env[:machine].id = serialize_machine_id(resource_group_name, vm_name, location)
110
+
111
+ @logger.info("Time to deploy: #{env[:metrics]['deployment_time']}")
112
+ unless env[:interrupted]
113
+ env[:metrics]['instance_ssh_time'] = Util::Timer.time do
114
+ # Wait for SSH to be ready.
115
+ env[:ui].info(I18n.t('vagrant_azure.waiting_for_ssh'))
116
+ network_ready_retries = 0
117
+ network_ready_retries_max = 10
118
+ while true
119
+ break if env[:interrupted]
120
+ begin
121
+ break if env[:machine].communicate.ready?
122
+ rescue Exception => e
123
+ if network_ready_retries < network_ready_retries_max
124
+ network_ready_retries += 1
125
+ @logger.warn(I18n.t('vagrant_azure.waiting_for_ssh, retrying'))
126
+ else
127
+ raise e
128
+ end
129
+ end
130
+ sleep 2
90
131
  end
91
132
  end
92
133
 
93
- env[:ui].info("Add Role? - #{add_role}")
134
+ @logger.info("Time for SSH ready: #{env[:metrics]['instance_ssh_time']}")
94
135
 
95
- if add_role
96
- env[:azure_vm_service].add_role(params.clone.merge(cloud_service_name: config.cloud_service_name), options)
97
- else
98
- env[:azure_vm_service].create_virtual_machine(params, options)
99
- end
136
+ # Ready and booted!
137
+ env[:ui].info(I18n.t('vagrant_azure.ready'))
100
138
  end
101
139
 
102
- if server.nil?
103
- raise Errors::CreateVMFailure
140
+ # Terminate the instance if we were interrupted
141
+ terminate(env) if env[:interrupted]
142
+
143
+ @app.call(env)
144
+ end
145
+
146
+ def get_image_os(image_details)
147
+ image_details.properties.os_disk_image.operating_system
148
+ end
149
+
150
+ def get_image_details(azure, location, publisher, offer, sku, version)
151
+ if version == 'latest'
152
+ latest = azure.compute.virtual_machine_images.list(location, publisher, offer, sku).value!.body.last
153
+ azure.compute.virtual_machine_images.get(location, publisher, offer, sku, latest.name).value!.body
154
+ else
155
+ azure.compute.virtual_machine_images.get(location, publisher, offer, sku, version).value!.body
104
156
  end
157
+ end
105
158
 
106
- # The Ruby SDK returns any exception encountered on create virtual
107
- # machine as a string.
159
+ def put_deployment(azure, rg_name, params)
160
+ azure.resources.deployments.create_or_update(rg_name, 'vagrant', params).value!.body
161
+ end
108
162
 
109
- if server.instance_of? String
110
- raise Errors::ServerNotCreated, message: server
163
+ def put_resource_group(azure, name, location)
164
+ params = ::Azure::ARM::Resources::Models::ResourceGroup.new.tap do |rg|
165
+ rg.location = location
111
166
  end
112
167
 
113
- env[:machine].id = "#{server.vm_name}@#{server.cloud_service_name}"
168
+ azure.resources.resource_groups.create_or_update(name, params).value!.body
169
+ end
114
170
 
115
- @app.call(env)
171
+ # This method generates the deployment template
172
+ def render_deployment_template(options)
173
+ Vagrant::Util::TemplateRenderer.render('arm/deployment.json', options.merge(template_root: template_root))
174
+ end
175
+
176
+ def build_deployment_params(template_params, deployment_params)
177
+ params = ::Azure::ARM::Resources::Models::Deployment.new
178
+ params.properties = ::Azure::ARM::Resources::Models::DeploymentProperties.new
179
+ params.properties.template = JSON.parse(render_deployment_template(template_params))
180
+ params.properties.mode = ::Azure::ARM::Resources::Models::DeploymentMode::Incremental
181
+ params.properties.parameters = build_parameters(deployment_params)
182
+ params
183
+ end
184
+
185
+ def build_parameters(options)
186
+ Hash[*options.map{ |k, v| [k, {value: v}] }.flatten]
187
+ end
188
+
189
+ # Used to find the base location of aws-vagrant templates
190
+ def template_root
191
+ Azure.source_root.join('templates')
192
+ end
193
+
194
+ def terminate(env)
195
+ destroy_env = env.dup
196
+ destroy_env.delete(:interrupted)
197
+ destroy_env[:config_validate] = false
198
+ destroy_env[:force_confirm_destroy] = true
199
+ env[:action_runner].run(Action.action_destroy, destroy_env)
116
200
  end
117
201
  end
118
202
  end
@@ -1,32 +1,51 @@
1
- #--------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache License, Version 2.0.
4
- # See License.txt in the project root for license information.
5
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
6
4
  require 'log4r'
5
+ require 'vagrant-azure/util/machine_id_helper'
6
+ require 'vagrant-azure/util/vm_status_translator'
7
+ require 'vagrant/util/retryable'
8
+ require 'vagrant-azure/util/timer'
9
+ require 'vagrant-azure/util/vm_await'
7
10
 
8
- # require 'vagrant/util/retryable'
9
-
10
- # Barebones basic implemenation. This a work in progress in very early stages
11
11
  module VagrantPlugins
12
- module WinAzure
12
+ module Azure
13
13
  module Action
14
14
  # This starts a stopped instance
15
15
  class StartInstance
16
+ include VagrantPlugins::Azure::Util::MachineIdHelper
17
+ include VagrantPlugins::Azure::Util::VMStatusTranslator
18
+ include VagrantPlugins::Azure::Util::VMAwait
16
19
 
17
20
  def initialize(app, env)
18
21
  @app = app
19
- @logger = Log4r::Logger.new('vagrant_azure:action::start_instance')
22
+ @logger = Log4r::Logger.new('vagrant_azure::action::start_instance')
20
23
  end
21
24
 
22
25
  def call(env)
23
- env[:machine].id = "#{env[:machine].provider_config.vm_name}@#{env[:machine].provider_config.cloud_service_name}" unless env[:machine].id
24
- env[:machine].id =~ /@/
26
+ env[:metrics] ||= {}
27
+
28
+ parsed = parse_machine_id(env[:machine].id)
29
+ azure = env[:azure_arm_service]
30
+ env[:ui].info(I18n.t('vagrant_azure.starting', parsed))
31
+ azure.compute.virtual_machines.start(parsed[:group], parsed[:name])
32
+
33
+ # Wait for the instance to be ready first
34
+ env[:metrics]['instance_ready_time'] = Util::Timer.time do
25
35
 
26
- VagrantPlugins::WinAzure::CLOUD_SERVICE_SEMAPHORE.synchronize do
27
- env[:ui].info "Attempting to start '#{$`}' in '#{$'}'"
28
- env[:azure_vm_service].start_virtual_machine($`, $')
36
+ env[:ui].info(I18n.t('vagrant_azure.waiting_for_ready'))
37
+
38
+ task = await_true(env) do |vm|
39
+ running?(vm.properties.instance_view.statuses)
40
+ end
41
+
42
+ if task.value
43
+ env[:ui].info(I18n.t('vagrant_azure.started', parsed))
44
+ else
45
+ raise I18n.t('vagrant_azure.errors.failed_starting', parsed) unless env[:interrupted]
46
+ end
29
47
  end
48
+
30
49
  @app.call(env)
31
50
  end
32
51
  end
@@ -1,15 +1,19 @@
1
- #--------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache License, Version 2.0.
4
- # See License.txt in the project root for license information.
5
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
6
4
  require 'log4r'
5
+ require 'vagrant-azure/util/machine_id_helper'
6
+ require 'vagrant-azure/util/vm_await'
7
+ require 'vagrant-azure/util/vm_status_translator'
8
+ require 'vagrant-azure/util/timer'
7
9
 
8
- # Barebones basic implemenation. This a work in progress in very early stages
9
10
  module VagrantPlugins
10
- module WinAzure
11
+ module Azure
11
12
  module Action
12
13
  class StopInstance
14
+ include VagrantPlugins::Azure::Util::MachineIdHelper
15
+ include VagrantPlugins::Azure::Util::VMAwait
16
+ include VagrantPlugins::Azure::Util::VMStatusTranslator
13
17
 
14
18
  def initialize(app, env)
15
19
  @app = app
@@ -17,23 +21,34 @@ module VagrantPlugins
17
21
  end
18
22
 
19
23
  def call(env)
20
- if env[:machine].state.id == :StoppedDeallocated
21
- env[:ui].info(
22
- I18n.t('vagrant_azure.already_status', :status => 'stopped.')
23
- )
24
+ env[:metrics] ||= {}
25
+
26
+ parsed = parse_machine_id(env[:machine].id)
27
+ if env[:machine].state.id == :stopped
28
+ env[:ui].info(I18n.t('vagrant_azure.already_status', :status => 'stopped.'))
24
29
  else
25
- env[:machine].id =~ /@/
26
- VagrantPlugins::WinAzure::CLOUD_SERVICE_SEMAPHORE.synchronize do
27
- env[:ui].info(
28
- I18n.t(
29
- 'vagrant_azure.stopping',
30
- :vm_name => $`,
31
- :cloud_service_name => $'
32
- )
33
- )
34
- env[:azure_vm_service].shutdown_virtual_machine($`, $')
30
+ env[:ui].info(I18n.t('vagrant_azure.stopping', parsed))
31
+ env[:azure_arm_service].compute.virtual_machines.power_off(parsed[:group], parsed[:name])
32
+
33
+ # Wait for the instance to be ready first
34
+ env[:metrics]['instance_stop_time'] = Util::Timer.time do
35
+
36
+ env[:ui].info(I18n.t('vagrant_azure.waiting_for_stop'))
37
+
38
+ task = await_true(env) do |vm|
39
+ stopped?(vm.properties.instance_view.statuses)
40
+ end
41
+
42
+ if task.value
43
+ env[:ui].info(I18n.t('vagrant_azure.stopped', parsed))
44
+ else
45
+ raise I18n.t('vagrant_azure.errors.failed_starting', parsed) unless env[:interrupted]
46
+ end
35
47
  end
48
+
49
+ env[:ui].info(I18n.t('vagrant_azure.stopped', parsed))
36
50
  end
51
+
37
52
  @app.call(env)
38
53
  end
39
54
  end
@@ -1,30 +1,34 @@
1
- #--------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Open Technologies, Inc.
3
- # All Rights Reserved. Licensed under the Apache 2.0 License.
4
- #--------------------------------------------------------------------------
1
+ # encoding: utf-8
2
+ # Copyright (c) Microsoft Corporation. All rights reserved.
3
+ # Licensed under the MIT License. See License in the project root for license information.
5
4
  require 'log4r'
5
+ require 'vagrant-azure/util/machine_id_helper'
6
6
 
7
7
  module VagrantPlugins
8
- module WinAzure
8
+ module Azure
9
9
  module Action
10
10
  class TerminateInstance
11
+ include VagrantPlugins::Azure::Util::MachineIdHelper
12
+
11
13
  def initialize(app, env)
12
14
  @app = app
13
15
  @logger = Log4r::Logger.new('vagrant_azure::action::terminate_instance')
14
16
  end
15
17
 
16
18
  def call(env)
17
- env[:machine].id =~ /@/
18
-
19
- vm = env[:azure_vm_service].get_virtual_machine($`, $')
19
+ parsed = parse_machine_id(env[:machine].id)
20
20
 
21
- if vm.nil?
22
- # machine not found. assuming it was not created or destroyed
23
- env[:ui].info (I18n.t('vagrant_azure.not_created'))
24
- else
25
- env[:azure_vm_service].delete_virtual_machine($`, $')
26
- env[:machine].id = nil
21
+ begin
22
+ env[:ui].info(I18n.t('vagrant_azure.terminating', parsed))
23
+ env[:azure_arm_service].resources.resource_groups.delete(parsed[:group]).value!.body
24
+ rescue MsRestAzure::AzureOperationError => ex
25
+ unless ex.response.status == 404
26
+ raise ex
27
+ end
27
28
  end
29
+ env[:ui].info(I18n.t('vagrant_azure.terminated', parsed))
30
+
31
+ env[:machine].id = nil
28
32
 
29
33
  @app.call(env)
30
34
  end