vagrant-vmware-appcatalyst 1.0.1

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 (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,34 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Action
17
+ class PowerOn
18
+ def initialize(app, env)
19
+ @app = app
20
+ @logger = Log4r::Logger.new('vagrant_appcatalyst::action::power_on')
21
+ end
22
+
23
+ def call(env)
24
+ begin
25
+ env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'on')
26
+ rescue Errors::UnattendedCodeError
27
+ raise Errors::PowerOnNotAllowed
28
+ end
29
+ @app.call(env)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,56 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Action
17
+ class ReadSSHInfo
18
+ def initialize(app, env, port = 22)
19
+ @app = app
20
+ @port = port
21
+ @logger = Log4r::Logger.new('vagrant_appcatalyst::action::read_ssh_info')
22
+ end
23
+
24
+ def call(env)
25
+ env[:machine_ssh_info] = read_ssh_info(env)
26
+
27
+ @app.call env
28
+ end
29
+
30
+ def read_ssh_info(env)
31
+ return nil if env[:machine].id.nil?
32
+
33
+ begin
34
+ ipaddress = env[:appcatalyst_cnx].get_vm_ipaddress(env[:machine].id)
35
+ rescue Errors::UnattendedCodeError
36
+ @retries ||= 0
37
+ if @retries < 60
38
+ @retries += 1
39
+ sleep 2
40
+ retry
41
+ else
42
+ raise Errors::UnattendedCodeError,
43
+ :message => "Can't look up ip address for this VM"
44
+ end
45
+ end
46
+
47
+ # If we are here, then SSH is ready, continue
48
+ {
49
+ :host => ipaddress['message'],
50
+ :port => 22
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,72 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Action
17
+ class ReadState
18
+ def initialize(app, env)
19
+ @app = app
20
+ @logger = Log4r::Logger.new('vagrant_appcatalyst::action::read_state')
21
+ end
22
+
23
+ def call(env)
24
+ env[:machine_state_id] = read_state(env)
25
+
26
+ @app.call env
27
+ end
28
+
29
+ def read_state(env)
30
+ vm_name = env[:machine].name
31
+
32
+ if env[:machine].id.nil?
33
+ @logger.info("VM [#{vm_name}] is not created yet")
34
+ return :not_created
35
+ end
36
+
37
+ power_state = env[:appcatalyst_cnx].get_vm_power(env[:machine].id)
38
+
39
+ case power_state['message']
40
+ when 'powering on'
41
+ @logger.info("VM [#{vm_name}] is running")
42
+ return :running
43
+ when 'powered on'
44
+ @logger.info("VM [#{vm_name}] is running")
45
+ return :running
46
+ when 'powering off'
47
+ @logger.info("VM [#{vm_name}] is stopped")
48
+ return :stopped
49
+ when 'powered off'
50
+ @logger.info("VM [#{vm_name}] is stopped")
51
+ return :stopped
52
+ when 'suspended'
53
+ @logger.info("VM [#{vm_name}] is suspended")
54
+ return :suspended
55
+ when 'suspending'
56
+ @logger.info("VM [#{vm_name}] is suspended")
57
+ return :suspended
58
+ when 'tools_running'
59
+ @logger.info("VM [#{vm_name}] is running")
60
+ return :running
61
+ when 'blocked on msg'
62
+ @logger.info("VM [#{vm_name}] is stopped")
63
+ return :stopped
64
+ else
65
+ @logger.info("VM [#{vm_name}] is in an unknown state")
66
+ return :unknown
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,31 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Action
17
+ class Resume
18
+ def initialize(app, env)
19
+ @app = app
20
+ @logger = Log4r::Logger.new('vagrant_appcatalyst::action::resume')
21
+ end
22
+
23
+ def call(env)
24
+ env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'resume')
25
+
26
+ @app.call(env)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Action
17
+ class Suspend
18
+ def initialize(app, env)
19
+ @app = app
20
+ @logger = Log4r::Logger.new('vagrant_appcatalyst::action::suspend')
21
+ end
22
+
23
+ def call(env)
24
+ env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'suspend')
25
+
26
+ @app.call(env)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,100 @@
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 distributed
9
+ # under the License is distributed on an "AS IS" BASIS, without warranties or
10
+ # conditions of any kind, EITHER EXPRESS OR IMPLIED. See the License for the
11
+ # specific language governing permissions and limitations under the License.
12
+
13
+ module VagrantPlugins
14
+ module AppCatalyst
15
+ module Cap
16
+ class MountAppCatalystSharedFolder
17
+ def self.mount_appcatalyst_shared_folder(machine, name, guestpath, options)
18
+ expanded_guest_path = machine.guest.capability(
19
+ :shell_expand_guest_path, guestpath)
20
+
21
+ mount_commands = []
22
+
23
+ if options[:owner].is_a? Integer
24
+ mount_uid = options[:owner]
25
+ else
26
+ mount_uid = "`id -u #{options[:owner]}`"
27
+ end
28
+
29
+ if options[:group].is_a? Integer
30
+ mount_gid = options[:group]
31
+ mount_gid_old = options[:group]
32
+ else
33
+ mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
34
+ mount_gid_old = "`id -g #{options[:group]}`"
35
+ end
36
+
37
+ # First mount command uses getent to get the group
38
+ mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
39
+ mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options]
40
+ mount_commands << "mount -t vmhgfs #{mount_options} .host:/#{name} #{expanded_guest_path}"
41
+
42
+ # Second mount command uses the old style `id -g`
43
+ mount_options = "-o uid=#{mount_uid},gid=#{mount_gid_old}"
44
+ mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options]
45
+ mount_commands << "mount -t vmhgfs #{mount_options} .host:/#{name} #{expanded_guest_path}"
46
+
47
+ # Create the guest path if it doesn't exist
48
+ machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
49
+
50
+ # Attempt to mount the folder. We retry here a few times because
51
+ # it can fail early on.
52
+ attempts = 0
53
+ loop do
54
+ success = true
55
+
56
+ stderr = ""
57
+ mount_commands.each do |command|
58
+ no_such_device = false
59
+ stderr = ""
60
+ status = machine.communicate.sudo(command, error_check: false) do |type, data|
61
+ if type == :stderr
62
+ no_such_device = true if data =~ /No such device/i
63
+ stderr += data.to_s
64
+ end
65
+ end
66
+
67
+ success = status == 0 && !no_such_device
68
+ break if success
69
+ end
70
+
71
+ break if success
72
+
73
+ attempts += 1
74
+ if attempts > 10
75
+ raise Vagrant::Errors::LinuxMountFailed,
76
+ command: mount_commands.join("\n"),
77
+ output: stderr
78
+ end
79
+
80
+ sleep(2*attempts)
81
+ end
82
+
83
+ # Emit an upstart event if we can
84
+ if machine.communicate.test("test -x /sbin/initctl")
85
+ machine.communicate.sudo(
86
+ "/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}")
87
+ end
88
+ end
89
+
90
+ def self.unmount_appcatalyst_shared_folder(machine, guestpath, options)
91
+ result = machine.communicate.sudo(
92
+ "umount #{guestpath}", error_check: false)
93
+ if result == 0
94
+ machine.communicate.sudo("rmdir #{guestpath}", error_check: false)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,31 @@
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
+ module VagrantPlugins
15
+ module AppCatalyst
16
+ module Cap
17
+ module PublicAddress
18
+ def self.public_address(machine)
19
+ # Initial try for vagrant share feature.
20
+ # It seems ssh_info[:port] is given automatically.
21
+ # I think this feature was built planning that the port forwarding
22
+ # and networking was done on the vagrant machine, which isn't the
23
+ # case in vagrant-vmware-appcatalyst
24
+
25
+ ssh_info = machine.ssh_info
26
+ ssh_info[:host]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
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
+ class Config < Vagrant.plugin('2', :config)
19
+ # login attributes
20
+
21
+ # Add extra configuration K/V pairs to VMX
22
+ #
23
+ # @return [Hash]
24
+ attr_accessor :vmx
25
+
26
+ # REST API daemon port, default 8080
27
+ #
28
+ # @return [String]
29
+ attr_accessor :rest_port
30
+
31
+ def initialize
32
+ self.vmx = {}
33
+ end
34
+
35
+ def validate(machine)
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,131 @@
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 'log4r'
15
+ require 'vagrant/util/busy'
16
+ require 'vagrant/util/platform'
17
+ require 'vagrant/util/retryable'
18
+ require 'vagrant/util/subprocess'
19
+
20
+ module VagrantPlugins
21
+ module AppCatalyst
22
+ module Driver
23
+ # Main class to access AppCatalyst rest APIs
24
+ class Base
25
+ include Vagrant::Util::Retryable
26
+
27
+ def initialize
28
+ @logger = Log4r::Logger.new('vagrant::provider::appcatalyst::base')
29
+ @interrupted = false
30
+ end
31
+
32
+ # Fetch details about a given VM
33
+ def get_vm(vm_id)
34
+ end
35
+
36
+ def get_vm_power(vm_id)
37
+ end
38
+
39
+ def get_vm_ipaddress(vm_id)
40
+ end
41
+
42
+ def set_vm_power(vm_id, operation)
43
+ end
44
+
45
+ def delete_vm(vm_id)
46
+ end
47
+
48
+ def import_vm(vm_id, name, source_reference, tag)
49
+ end
50
+
51
+ def list_vms
52
+ end
53
+
54
+ def get_vm_shared_folders(vm_id)
55
+ end
56
+
57
+ def set_vm_shared_folders(vm_id, operation)
58
+ end
59
+
60
+ def add_vm_shared_folder(vm_id, guest_path, host_path, flags)
61
+ end
62
+
63
+ def get_vm_shared_folder(vm_id, shared_folder_id)
64
+ end
65
+
66
+ def delete_vm_shared_folder(vm_id, shared_folder_id)
67
+ end
68
+
69
+ def clone_vm_in_directory(src, dest)
70
+ end
71
+
72
+ def set_vmx_value(vmx_file, key, value)
73
+ end
74
+
75
+ private
76
+
77
+ ##
78
+ # Sends a synchronous request to the AppCatalyst API and returns the
79
+ # response as parsed XML + headers using HTTPClient.
80
+ def send_request(params, payload = nil, content_type = nil)
81
+ # Create a new HTTP client
82
+ clnt = HTTPClient.new
83
+
84
+ extheader = {}
85
+ extheader['accept'] = "application/json"
86
+ extheader['Content-Type'] = content_type unless content_type.nil?
87
+
88
+ url = "#{@endpoint}#{params['command']}"
89
+
90
+ @logger.debug("[#{Time.now.ctime}] -> SEND #{params['method'].upcase} #{url}")
91
+ if payload
92
+ @logger.debug('SEND HEADERS')
93
+ @logger.debug(extheader)
94
+ @logger.debug('SEND BODY')
95
+ @logger.debug(payload)
96
+ end
97
+
98
+ begin
99
+ response = clnt.request(
100
+ params['method'],
101
+ url,
102
+ nil,
103
+ payload,
104
+ extheader
105
+ )
106
+
107
+ @logger.debug("[#{Time.now.ctime}] <- RECV #{response.status}")
108
+ @logger.debug('RECV HEADERS')
109
+ @logger.debug(response.headers)
110
+ @logger.debug('RECV BODY') if response.body.length > 0
111
+ @logger.debug(response.body) if response.body.length > 0
112
+
113
+ unless response.ok?
114
+ error_response = JSON.parse(response.body)
115
+ fail Errors::UnattendedCodeError,
116
+ :message => "#{error_response['code']}: #{error_response['message']}"
117
+ end
118
+
119
+ if response.body.length > 0
120
+ [JSON.parse(response.body), response.headers]
121
+ else
122
+ ['', response.headers]
123
+ end
124
+ rescue SocketError, Errno::EADDRNOTAVAIL, Errno::ETIMEDOUT, Errno::ECONNREFUSED
125
+ raise Errors::EndpointUnavailable
126
+ end
127
+ end
128
+ end # class
129
+ end
130
+ end
131
+ end