vagrant-azure 1.3.0 → 2.0.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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