vagrant-vmware-appcatalyst 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/.rubocop.yml +34 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +177 -0
  6. data/README.md +72 -0
  7. data/lib/vagrant-vmware-appcatalyst.rb +30 -0
  8. data/lib/vagrant-vmware-appcatalyst/action.rb +249 -0
  9. data/lib/vagrant-vmware-appcatalyst/action/connect_appcatalyst.rb +45 -0
  10. data/lib/vagrant-vmware-appcatalyst/action/destroy_vm.rb +33 -0
  11. data/lib/vagrant-vmware-appcatalyst/action/import.rb +101 -0
  12. data/lib/vagrant-vmware-appcatalyst/action/is_created.rb +34 -0
  13. data/lib/vagrant-vmware-appcatalyst/action/is_paused.rb +33 -0
  14. data/lib/vagrant-vmware-appcatalyst/action/is_running.rb +32 -0
  15. data/lib/vagrant-vmware-appcatalyst/action/message_already_running.rb +29 -0
  16. data/lib/vagrant-vmware-appcatalyst/action/message_not_created.rb +29 -0
  17. data/lib/vagrant-vmware-appcatalyst/action/message_not_running.rb +29 -0
  18. data/lib/vagrant-vmware-appcatalyst/action/message_not_supported.rb +29 -0
  19. data/lib/vagrant-vmware-appcatalyst/action/message_will_not_destroy.rb +30 -0
  20. data/lib/vagrant-vmware-appcatalyst/action/power_off.rb +40 -0
  21. data/lib/vagrant-vmware-appcatalyst/action/power_on.rb +34 -0
  22. data/lib/vagrant-vmware-appcatalyst/action/read_ssh_info.rb +56 -0
  23. data/lib/vagrant-vmware-appcatalyst/action/read_state.rb +72 -0
  24. data/lib/vagrant-vmware-appcatalyst/action/resume.rb +31 -0
  25. data/lib/vagrant-vmware-appcatalyst/action/suspend.rb +31 -0
  26. data/lib/vagrant-vmware-appcatalyst/cap/mount_appcatalyst_shared_folder.rb +100 -0
  27. data/lib/vagrant-vmware-appcatalyst/cap/public_address.rb +31 -0
  28. data/lib/vagrant-vmware-appcatalyst/config.rb +40 -0
  29. data/lib/vagrant-vmware-appcatalyst/driver/base.rb +131 -0
  30. data/lib/vagrant-vmware-appcatalyst/driver/meta.rb +106 -0
  31. data/lib/vagrant-vmware-appcatalyst/driver/version_1_0.rb +223 -0
  32. data/lib/vagrant-vmware-appcatalyst/errors.rb +44 -0
  33. data/lib/vagrant-vmware-appcatalyst/plugin.rb +111 -0
  34. data/lib/vagrant-vmware-appcatalyst/provider.rb +60 -0
  35. data/lib/vagrant-vmware-appcatalyst/synced_folder.rb +123 -0
  36. data/lib/vagrant-vmware-appcatalyst/version.rb +18 -0
  37. data/locales/en.yml +29 -0
  38. data/vagrant-vmware-appcatalyst.gemspec +40 -0
  39. metadata +165 -0
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ # use this file except in compliance with the License. You may obtain a copy of
6
+ # the License at http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, without
10
+ # warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
11
+ # License for the specific language governing permissions and limitations under
12
+ # the License.
13
+
14
+ require 'forwardable'
15
+ require 'log4r'
16
+ require 'httpclient'
17
+ require 'json'
18
+
19
+ require File.expand_path('../base', __FILE__)
20
+
21
+ module VagrantPlugins
22
+ module AppCatalyst
23
+ module Driver
24
+ class Meta < Base
25
+ extend Forwardable
26
+ attr_reader :endpoint
27
+ attr_reader :version
28
+
29
+ def initialize(endpoint)
30
+ super()
31
+
32
+ @logger = Log4r::Logger.new('vagrant::provider::appcatalyst::meta')
33
+
34
+ @endpoint = endpoint
35
+
36
+ # Read and assign the version of AppCatalyst we know which
37
+ # specific driver to instantiate.
38
+ @logger.debug("Asking API Version with host_url: #{@endpoint}")
39
+ @version = get_api_version(@endpoint) || ''
40
+
41
+ # Instantiate the proper version driver for AppCatalyst
42
+ @logger.debug("Finding driver for AppCatalyst version: #{@version}")
43
+ driver_map = {
44
+ '1.0.0' => Version_1_0
45
+ }
46
+
47
+ driver_klass = nil
48
+ driver_map.each do |key, klass|
49
+ if @version.start_with?(key)
50
+ driver_klass = klass
51
+ break
52
+ end
53
+ end
54
+
55
+ unless driver_klass
56
+ supported_versions = driver_map.keys.sort.join(', ')
57
+ fail Errors::AppCatalystInvalidVersion,
58
+ :supported_versions => supported_versions
59
+ end
60
+
61
+ @logger.info("Using AppCatalyst driver: #{driver_klass}")
62
+ @driver = driver_klass.new(@endpoint)
63
+ end
64
+
65
+ def_delegators :@driver,
66
+ :get_vm,
67
+ :get_vm_power,
68
+ :get_vm_ipaddress,
69
+ :set_vm_power,
70
+ :delete_vm,
71
+ :import_vm,
72
+ :list_vm,
73
+ :get_vm_shared_folders,
74
+ :set_vm_shared_folders,
75
+ :add_vm_shared_folder,
76
+ :get_vm_shared_folder,
77
+ :delete_vm_shared_folder,
78
+ :clone_vm_in_directory,
79
+ :set_vmx_value
80
+ protected
81
+
82
+ def get_api_version(endpoint)
83
+ # Create a new HTTP client
84
+ clnt = HTTPClient.new
85
+ uri = URI(endpoint)
86
+ url = "#{uri.scheme}://#{uri.host}:#{uri.port}/json/swagger.json"
87
+
88
+ begin
89
+ response = clnt.request('GET', url, nil, nil, nil)
90
+ unless response.ok?
91
+ fail Errors::UnattendedCodeError,
92
+ :message => response.status + ' ' + response.reason
93
+ end
94
+
95
+ api_definition = JSON.parse(response.body)
96
+
97
+ api_definition['info']['version']
98
+
99
+ rescue SocketError, Errno::EADDRNOTAVAIL, Errno::ETIMEDOUT, Errno::ECONNREFUSED
100
+ raise Errors::EndpointUnavailable
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,223 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ # use this file except in compliance with the License. You may obtain a copy of
6
+ # the License at http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, without
10
+ # warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
11
+ # License for the specific language governing permissions and limitations under
12
+ # the License.
13
+
14
+ require 'uri'
15
+ require 'vagrant/util/platform'
16
+ require 'log4r'
17
+
18
+ module VagrantPlugins
19
+ module AppCatalyst
20
+ module Driver
21
+ # Main class to access AppCatalyst rest APIs
22
+ class Version_1_0 < Base
23
+
24
+ ##
25
+ # Init the driver with the Vagrantfile information
26
+ def initialize(endpoint)
27
+ super()
28
+
29
+ @logger = Log4r::Logger.new('vagrant::provider::appcatalyst::driver_1_0')
30
+ @logger.debug("AppCatalyst Driver 1.0 loaded")
31
+ @endpoint = endpoint
32
+ end
33
+
34
+ ##
35
+ # Fetch details about a given VM
36
+ def get_vm(vm_id)
37
+ params = {
38
+ 'method' => :get,
39
+ 'command' => "/api/vms/#{vm_id}"
40
+ }
41
+
42
+ response, _headers = send_request(params)
43
+
44
+ response
45
+ end
46
+
47
+ def get_vm_power(vm_id)
48
+ params = {
49
+ 'method' => :get,
50
+ 'command' => "/api/vms/power/#{vm_id}"
51
+ }
52
+
53
+ response, _headers = send_request(params)
54
+
55
+ response
56
+ end
57
+
58
+ def get_vm_ipaddress(vm_id)
59
+ params = {
60
+ 'method' => :get,
61
+ 'command' => "/api/vms/#{vm_id}/ipaddress"
62
+ }
63
+
64
+ response, _headers = send_request(params)
65
+
66
+ response
67
+ end
68
+
69
+ def set_vm_power(vm_id, operation)
70
+ params = {
71
+ 'method' => :patch,
72
+ 'command' => "/api/vms/power/#{vm_id}"
73
+ }
74
+
75
+ response, _headers = send_request(
76
+ params,
77
+ operation,
78
+ 'application/json'
79
+ )
80
+
81
+ response
82
+ end
83
+
84
+ def delete_vm(vm_id)
85
+ params = {
86
+ 'method' => :delete,
87
+ 'command' => "/api/vms/#{vm_id}"
88
+ }
89
+
90
+ _response, _headers = send_request(params)
91
+ end
92
+
93
+ def import_vm(vm_id, name, source_reference, tag)
94
+ @logger.debug("Importing #{name}")
95
+ vm_to_import = {
96
+ 'id' => vm_id,
97
+ 'name' => name,
98
+ 'sourceReference' => source_reference,
99
+ 'tag' => tag
100
+ }
101
+
102
+ params = {
103
+ 'method' => :post,
104
+ 'command' => '/api/vms'
105
+ }
106
+
107
+ @logger.debug("JSON stuff #{JSON.generate(vm_to_import)}")
108
+ response, _headers = send_request(
109
+ params,
110
+ JSON.generate(vm_to_import),
111
+ 'application/json'
112
+ )
113
+
114
+ response
115
+ end
116
+
117
+ def list_vms
118
+ params = {
119
+ 'method' => :get,
120
+ 'command' => '/api/vms'
121
+ }
122
+
123
+ response, _headers = send_request(params)
124
+
125
+ response
126
+ end
127
+
128
+ def get_vm_shared_folders(vm_id)
129
+ params = {
130
+ 'method' => :get,
131
+ 'command' => "/api/vms/#{vm_id}/folders"
132
+ }
133
+
134
+ response, _headers = send_request(params)
135
+
136
+ response
137
+ end
138
+
139
+ def set_vm_shared_folders(vm_id, operation)
140
+ params = {
141
+ 'method' => :patch,
142
+ 'command' => "/api/vms/#{vm_id}/folders"
143
+ }
144
+
145
+ response, _headers = send_request(
146
+ params,
147
+ operation,
148
+ 'application/json'
149
+ )
150
+
151
+ response
152
+ end
153
+
154
+ def add_vm_shared_folder(vm_id, guest_path, host_path, flags)
155
+ @logger.debug("Adding Shared Folder #{guest_path} to #{vm_id}")
156
+ shared_folder_to_add = {
157
+ 'guestPath' => guest_path,
158
+ 'hostPath' => host_path,
159
+ 'flags' => flags
160
+ }
161
+
162
+ params = {
163
+ 'method' => :post,
164
+ 'command' => "/api/vms/#{vm_id}/folders"
165
+ }
166
+
167
+ @logger.debug("JSON stuff #{JSON.generate(shared_folder_to_add)}")
168
+ response, _headers = send_request(
169
+ params,
170
+ JSON.generate(shared_folder_to_add),
171
+ 'application/json'
172
+ )
173
+
174
+ response
175
+ end
176
+
177
+ def get_vm_shared_folder(vm_id, shared_folder_id)
178
+ params = {
179
+ 'method' => :get,
180
+ 'command' => "/api/vms/#{vm_id}/folders/#{shared_folder_id}"
181
+ }
182
+
183
+ response, _headers = send_request(params)
184
+
185
+ response
186
+ end
187
+
188
+ def delete_vm_shared_folder(vm_id, shared_folder_id)
189
+ params = {
190
+ 'method' => :delete,
191
+ 'command' => "/api/vms/#{vm_id}/folders/#{shared_folder_id}"
192
+ }
193
+
194
+ _response, _headers = send_request(params)
195
+ end
196
+
197
+ def clone_vm_in_directory(src, dest)
198
+ @logger.debug("Cloning VM from #{src} to #{dest}")
199
+ FileUtils.cp_r("#{src}/.", dest)
200
+ end
201
+
202
+ def set_vmx_value(vmx_file, key, value)
203
+ # read VMX in a hash
204
+ temp_vmx = Hash[File.read(vmx_file).scan(/^(.+?)\s*=\s*"(.*?)"\s*$/)]
205
+ vmx = Hash[temp_vmx.map { |k, v| v.class == Array ? [k, v.map { |r| f r }.to_a] : [k.downcase, v]}]
206
+ @logger.debug("Setting #{key} = #{value} in VMX")
207
+ # Set the key/value
208
+ vmx[key.downcase] = value
209
+
210
+ # Open file for writing
211
+ f = File.open(vmx_file, 'w')
212
+
213
+ # Write file in order
214
+ vmx.sort.map do |k, v|
215
+ f.write("#{k} = \"#{v}\"\n")
216
+ end
217
+
218
+ f.close
219
+ end
220
+ end # Class Version 5.1
221
+ end # Module Driver
222
+ end # module AppCatalyst
223
+ end # Module VagrantPlugins
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ # use this file except in compliance with the License. You may obtain a copy of
6
+ # the License at http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, without
10
+ # warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
11
+ # License for the specific language governing permissions and limitations under
12
+ # the License.
13
+
14
+ require 'vagrant'
15
+
16
+ module VagrantPlugins
17
+ module AppCatalyst
18
+ module Errors
19
+ # Generic Errors during Vagrant execution
20
+ class AppCatalystGenericError < Vagrant::Errors::VagrantError
21
+ error_namespace('vagrant_appcatalyst.errors')
22
+ end
23
+ class AppCatalystOldVersion < AppCatalystGenericError
24
+ error_key(:appcatalyst_old_version)
25
+ end
26
+ # Errors in the REST API communication
27
+ class AppCatalystRestError < Vagrant::Errors::VagrantError
28
+ error_namespace('vagrant_appcatalyst.errors.rest_errors')
29
+ end
30
+ class UnattendedCodeError < AppCatalystRestError
31
+ error_key(:unattended_code_error)
32
+ end
33
+ class EndpointUnavailable < AppCatalystRestError
34
+ error_key(:endpoint_unavailable)
35
+ end
36
+ class AppCatalystViolationError < Vagrant::Errors::VagrantError
37
+ error_namespace('vagrant_appcatalyst.errors.violations')
38
+ end
39
+ class PowerOnNotAllowed < AppCatalystViolationError
40
+ error_key(:poweron_not_allowed)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ # use this file except in compliance with the License. You may obtain a copy of
6
+ # the License at http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, without
10
+ # warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the
11
+ # License for the specific language governing permissions and limitations under
12
+ # the License.
13
+
14
+ begin
15
+ require 'vagrant'
16
+ rescue LoadError
17
+ raise 'The Vagrant AppCatalyst plugin must be run within Vagrant.'
18
+ end
19
+
20
+ if Vagrant::VERSION < '1.6.3'
21
+ fail 'The Vagrant AppCatalyst plugin is only compatible with Vagrant 1.6.3+'
22
+ end
23
+
24
+ module VagrantPlugins
25
+ module AppCatalyst
26
+ class Plugin < Vagrant.plugin('2')
27
+ name 'VMware AppCatalyst Provider'
28
+ description 'Allows Vagrant to manage machines with VMware AppCatalyst®'
29
+
30
+ config(:vmware_appcatalyst, :provider) do
31
+ require_relative 'config'
32
+ Config
33
+ end
34
+
35
+ # We provide support for multiple box formats.
36
+ provider(
37
+ :vmware_appcatalyst,
38
+ box_format: %w(vmware_desktop vmware_fusion vmware_workstation),
39
+ parallel: true
40
+ ) do
41
+ setup_logging
42
+ setup_i18n
43
+
44
+ # Return the provider
45
+ require_relative 'provider'
46
+ Provider
47
+ end
48
+
49
+ # Add vagrant share support
50
+ provider_capability('vmware_appcatalyst', 'public_address') do
51
+ require_relative 'cap/public_address'
52
+ Cap::PublicAddress
53
+ end
54
+
55
+ synced_folder(:vmware_appcatalyst) do
56
+ require File.expand_path('../synced_folder', __FILE__)
57
+ SyncedFolder
58
+ end
59
+
60
+ # Add vmware shared folders mount capability to linux
61
+ guest_capability('linux', 'mount_appcatalyst_shared_folder') do
62
+ require_relative 'cap/mount_appcatalyst_shared_folder'
63
+ Cap::MountAppCatalystSharedFolder
64
+ end
65
+
66
+ guest_capability('linux', 'unmount_appcatalyst_shared_folder') do
67
+ require_relative 'cap/mount_appcatalyst_shared_folder'
68
+ Cap::MountAppCatalystSharedFolder
69
+ end
70
+
71
+ def self.setup_i18n
72
+ I18n.load_path << File.expand_path('locales/en.yml', AppCatalyst.source_root)
73
+ I18n.reload!
74
+ end
75
+
76
+ # This sets up our log level to be whatever VAGRANT_LOG is.
77
+ def self.setup_logging
78
+ require 'log4r'
79
+
80
+ level = nil
81
+ begin
82
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
83
+ rescue NameError
84
+ # This means that the logging constant wasn't found,
85
+ # which is fine. We just keep `level` as `nil`. But
86
+ # we tell the user.
87
+ level = nil
88
+ end
89
+
90
+ # Some constants, such as 'true' resolve to booleans, so the
91
+ # above error checking doesn't catch it. This will check to make
92
+ # sure that the log level is an integer, as Log4r requires.
93
+ level = nil unless level.is_a?(Integer)
94
+
95
+ # Set the logging level on all 'vagrant' namespaced
96
+ # logs as long as we have a valid level.
97
+ if level
98
+ logger = Log4r::Logger.new('vagrant_appcatalyst')
99
+ logger.outputters = Log4r::Outputter.stderr
100
+ logger.level = level
101
+ # logger = nil
102
+ end
103
+ end
104
+ end
105
+
106
+ module Driver
107
+ autoload :Meta, File.expand_path('../driver/meta', __FILE__)
108
+ autoload :Version_1_0, File.expand_path('../driver/version_1_0', __FILE__)
109
+ end
110
+ end
111
+ end