├── .gitignore ├── .rubocop.yml ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── lib ├── vagrant-vmware-appcatalyst.rb └── vagrant-vmware-appcatalyst │ ├── action.rb │ ├── action │ ├── connect_appcatalyst.rb │ ├── destroy_vm.rb │ ├── import.rb │ ├── is_created.rb │ ├── is_paused.rb │ ├── is_running.rb │ ├── message_already_running.rb │ ├── message_not_created.rb │ ├── message_not_running.rb │ ├── message_not_supported.rb │ ├── message_will_not_destroy.rb │ ├── power_off.rb │ ├── power_on.rb │ ├── read_ssh_info.rb │ ├── read_state.rb │ ├── resume.rb │ └── suspend.rb │ ├── cap │ ├── mount_appcatalyst_shared_folder.rb │ └── public_address.rb │ ├── config.rb │ ├── driver │ ├── base.rb │ ├── meta.rb │ └── version_1_0.rb │ ├── errors.rb │ ├── plugin.rb │ ├── provider.rb │ ├── synced_folder.rb │ └── version.rb ├── locales └── en.yml └── vagrant-vmware-appcatalyst.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /test/tmp/ 9 | /test/version_tmp/ 10 | /tmp/ 11 | 12 | ## Specific to RubyMotion: 13 | .dat* 14 | .repl_history 15 | build/ 16 | 17 | ## Documentation cache and generated files: 18 | /.yardoc/ 19 | /_yardoc/ 20 | /doc/ 21 | /rdoc/ 22 | 23 | ## Environment normalisation: 24 | /.bundle/ 25 | /lib/bundler/man/ 26 | 27 | # for a library or gem, you might want to ignore these files since the code is 28 | # intended to run in multiple environments; otherwise, check them in: 29 | # Gemfile.lock 30 | # .ruby-version 31 | # .ruby-gemset 32 | 33 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 34 | .rvmrc 35 | 36 | # Vagrant specifics 37 | Vagrantfile* 38 | vagrant*deb -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | MethodLength: 2 | CountComments: false # count full line comments? 3 | Enabled: false 4 | 5 | MethodName: 6 | EnforcedStyle: snake_case 7 | 8 | AccessorMethodName: 9 | Description: Check the naming of accessor methods for get_/set_. 10 | Enabled: false 11 | 12 | Encoding: 13 | Description: 'Use UTF-8 as the source file encoding.' 14 | Enabled: true 15 | 16 | HashSyntax: 17 | Description: >- 18 | Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax 19 | { :a => 1, :b => 2 }. 20 | Enabled: false 21 | EnforcedStyle: hash_rockets 22 | 23 | LineEndConcatenation: 24 | Description: 'Use \\ instead of + to concatenate two string literals at line end.' 25 | Enabled: true 26 | 27 | LineLength: 28 | Description: 'Limit lines to 80 characters.' 29 | Enabled: true 30 | Max: 80 31 | 32 | CyclomaticComplexity: 33 | Description: 'Avoid complex methods.' 34 | Enabled: false 35 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :plugins do 6 | gem 'vagrant-vmware-appcatalyst' , path: '.' 7 | end 8 | 9 | group :development do 10 | gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant.git' 11 | end 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AppCatalyst has been discontinued, this repository is for historical preservation only 2 | 3 | [Vagrant](http://www.vagrantup.com) provider for [VMware AppCatalyst®](https://communities.vmware.com/community/vmtn/devops/vmware-appcatalyst) [![Gem Version](https://badge.fury.io/rb/vagrant-vmware-appcatalyst.svg)](http://badge.fury.io/rb/vagrant-vmware-appcatalyst) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/vmware/vagrant-vmware-appcatalyst?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 4 | ============= 5 | 6 | This plugin supports `vmware_desktop`, `vmware_fusion` and `vmware_workstation` box type, the same used by Hashicorp plugins for VMware products. 7 | 8 | Install 9 | ------------- 10 | 11 | Latest version can be easily installed by running the following command: 12 | 13 | ```vagrant plugin install vagrant-vmware-appcatalyst``` 14 | 15 | Vagrant will download all the required gems during the installation process. 16 | 17 | After the install has completed a ```vagrant up --provider=vmware_appcatalyst``` will trigger the newly installed provider. 18 | 19 | *Note: The AppCatalyst Daemon must be running before bringing up a new vagrant box:* 20 | ```appcatalyst-daemon start``` 21 | 22 | Upgrade 23 | ------------- 24 | 25 | If you already have vagrant-vmware-appcatalyst installed you can update to the latest version available by issuing: 26 | 27 | ```vagrant plugin update vagrant-vmware-appcatalyst``` 28 | 29 | Vagrant will take care of the upgrade process. 30 | 31 | Configuration 32 | ------------- 33 | 34 | Here's a sample Vagrantfile that builds a docker host on AppCatalyst and starts a Wordpress container on port 80, make sure you replace the placeholders with your own values. 35 | 36 | ```ruby 37 | # Set our default provider for this Vagrantfile to 'vmware_appcatalyst' 38 | ENV['VAGRANT_DEFAULT_PROVIDER'] = 'vmware_appcatalyst' 39 | 40 | nodes = [ 41 | { hostname: 'gantry-test-1', box: 'hashicorp/precise64' }, 42 | { hostname: 'gantry-test-2', box: 'hashicorp/precise64' } 43 | ] 44 | 45 | Vagrant.configure('2') do |config| 46 | 47 | # Configure our boxes with 1 CPU and 384MB of RAM 48 | config.vm.provider 'vmware_appcatalyst' do |v| 49 | v.cpus = '1' 50 | v.memory = '384' 51 | end 52 | 53 | # Go through nodes and configure each of them.j 54 | nodes.each do |node| 55 | config.vm.define node[:hostname] do |node_config| 56 | node_config.vm.box = node[:box] 57 | node_config.vm.hostname = node[:hostname] 58 | node_config.vm.synced_folder('/Users/frapposelli/Development', '/development') 59 | end 60 | end 61 | end 62 | 63 | ``` 64 | 65 | Legal 66 | ----- 67 | 68 | Copyright © 2015 VMware, Inc. All Rights Reserved. 69 | 70 | Licensed under the Apache License, Version 2.0 (the “License”); you may not 71 | use this file except in compliance with the License. You may obtain a copy of 72 | the License at http://www.apache.org/licenses/LICENSE-2.0 73 | 74 | Unless required by applicable law or agreed to in writing, software distributed 75 | under the License is distributed on an “AS IS” BASIS, without warranties or 76 | conditions of any kind, EITHER EXPRESS OR IMPLIED. See the License for the 77 | specific language governing permissions and limitations under the License. 78 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'rspec/core/rake_task' 4 | 5 | Bundler::GemHelper.install_tasks 6 | # RSpec::Core::RakeTask.new 7 | # task :default => "spec" 8 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst.rb: -------------------------------------------------------------------------------- 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 'pathname' 15 | require 'vagrant-vmware-appcatalyst/plugin' 16 | 17 | module VagrantPlugins 18 | module AppCatalyst 19 | lib_path = Pathname.new(File.expand_path('../vagrant-vmware-appcatalyst', __FILE__)) 20 | autoload :Action, lib_path.join('action') 21 | autoload :Errors, lib_path.join('errors') 22 | 23 | # This returns the path to the source of this plugin. 24 | # 25 | # @return [Pathname] 26 | def self.source_root 27 | @source_root ||= Pathname.new(File.expand_path('../../', __FILE__)) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action.rb: -------------------------------------------------------------------------------- 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 'pathname' 15 | require 'vagrant/action/builder' 16 | 17 | module VagrantPlugins 18 | module AppCatalyst 19 | # This module dictates the actions to be performed by Vagrant when called 20 | # with a specific command 21 | module Action 22 | include Vagrant::Action::Builtin 23 | 24 | # Vagrant commands 25 | # This action boots the VM, assuming the VM is in a state that requires 26 | # a bootup (i.e. not saved). 27 | def self.action_boot 28 | Vagrant::Action::Builder.new.tap do |b| 29 | b.use ConfigValidate 30 | b.use PowerOn 31 | b.use WaitForCommunicator, [:starting, :running] 32 | b.use Provision 33 | b.use SetHostname 34 | b.use SyncedFolderCleanup 35 | b.use SyncedFolders 36 | end 37 | end 38 | 39 | def self.action_reload 40 | Vagrant::Action::Builder.new.tap do |b| 41 | b.use ConfigValidate 42 | b.use Call, IsCreated do |env, b2| 43 | unless env[:result] 44 | b2.use MessageNotCreated 45 | next 46 | end 47 | b2.use action_halt 48 | b2.use action_start 49 | end 50 | end 51 | end 52 | 53 | # This action starts a VM, assuming it is already imported and exists. 54 | # A precondition of this action is that the VM exists. 55 | def self.action_start 56 | Vagrant::Action::Builder.new.tap do |b| 57 | b.use ConnectAppCatalyst 58 | b.use ConfigValidate 59 | b.use BoxCheckOutdated 60 | b.use Call, IsRunning do |env, b2| 61 | # If the VM is running, then our work here is done, exit 62 | if env[:result] 63 | b2.use MessageAlreadyRunning 64 | next 65 | end 66 | 67 | b2.use action_boot 68 | end 69 | end 70 | end 71 | 72 | def self.action_halt 73 | Vagrant::Action::Builder.new.tap do |b| 74 | b.use ConfigValidate 75 | b.use ConnectAppCatalyst 76 | b.use PowerOff 77 | end 78 | end 79 | 80 | def self.action_suspend 81 | Vagrant::Action::Builder.new.tap do |b| 82 | b.use ConfigValidate 83 | b.use ConnectAppCatalyst 84 | b.use Suspend 85 | end 86 | end 87 | 88 | def self.action_resume 89 | Vagrant::Action::Builder.new.tap do |b| 90 | b.use ConfigValidate 91 | b.use ConnectAppCatalyst 92 | b.use Resume 93 | end 94 | end 95 | 96 | def self.action_destroy 97 | Vagrant::Action::Builder.new.tap do |b| 98 | b.use Call, DestroyConfirm do |env, b2| 99 | if env[:result] 100 | b2.use ConfigValidate 101 | b2.use ConnectAppCatalyst 102 | b2.use Call, IsCreated do |env2, b3| 103 | unless env2[:result] 104 | b3.use MessageNotCreated 105 | next 106 | end 107 | b3.use ProvisionerCleanup 108 | b3.use Call, IsRunning do |env3, b4| 109 | # If the VM is running, must power off 110 | b4.use action_halt if env3[:result] 111 | end 112 | b3.use DestroyVM 113 | end 114 | else 115 | b2.use MessageWillNotDestroy 116 | end 117 | end 118 | end 119 | end 120 | 121 | def self.action_provision 122 | Vagrant::Action::Builder.new.tap do |b| 123 | b.use ConfigValidate 124 | b.use Call, IsCreated do |env, b2| 125 | unless env[:result] 126 | b2.use MessageNotCreated 127 | next 128 | end 129 | b2.use Call, IsRunning do |env2, b3| 130 | unless env2[:result] 131 | b3.use MessageNotRunning 132 | next 133 | end 134 | b3.use Provision 135 | end 136 | end 137 | end 138 | end 139 | 140 | # This action is called to read the SSH info of the machine. The 141 | # resulting state is expected to be put into the `:machine_ssh_info` 142 | # key. 143 | def self.action_read_ssh_info 144 | Vagrant::Action::Builder.new.tap do |b| 145 | b.use ConnectAppCatalyst 146 | b.use ReadSSHInfo, 22 147 | end 148 | end 149 | 150 | # This action is called to read the state of the machine. The 151 | # resulting state is expected to be put into the `:machine_state_id` 152 | # key. 153 | def self.action_read_state 154 | Vagrant::Action::Builder.new.tap do |b| 155 | b.use ConfigValidate 156 | b.use ConnectAppCatalyst 157 | b.use ReadState 158 | end 159 | end 160 | 161 | def self.action_ssh 162 | Vagrant::Action::Builder.new.tap do |b| 163 | # b.use ConfigValidate 164 | b.use Call, IsCreated do |env, b2| 165 | unless env[:result] 166 | b2.use MessageNotCreated 167 | next 168 | end 169 | 170 | b2.use Call, IsRunning do |env2, b3| 171 | unless env2[:result] 172 | b3.use MessageNotRunning 173 | next 174 | end 175 | b3.use SSHExec 176 | end 177 | end 178 | end 179 | end 180 | 181 | def self.action_ssh_run 182 | Vagrant::Action::Builder.new.tap do |b| 183 | b.use ConfigValidate 184 | b.use Call, IsCreated do |env, b2| 185 | unless env[:result] 186 | b2.use MessageNotCreated 187 | next 188 | end 189 | 190 | b2.use SSHRun 191 | end 192 | end 193 | end 194 | 195 | def self.action_up 196 | Vagrant::Action::Builder.new.tap do |b| 197 | b.use ConnectAppCatalyst 198 | 199 | b.use Call, IsCreated do |env, b2| 200 | b2.use HandleBox unless env[:result] 201 | end 202 | 203 | b.use ConfigValidate 204 | 205 | b.use Call, IsCreated do |env, b2| 206 | unless env[:result] 207 | b2.use Import 208 | end 209 | end 210 | b.use action_start 211 | end 212 | end 213 | 214 | def self.action_connect 215 | Vagrant::Action::Builder.new.tap do |b| 216 | b.use ConnectAppCatalyst 217 | end 218 | end 219 | 220 | 221 | # The autoload farm 222 | action_root = Pathname.new(File.expand_path('../action', __FILE__)) 223 | autoload :Import, 224 | action_root.join('import') 225 | autoload :ConnectAppCatalyst, 226 | action_root.join('connect_appcatalyst') 227 | autoload :DestroyVM, 228 | action_root.join('destroy_vm') 229 | autoload :IsCreated, 230 | action_root.join('is_created') 231 | autoload :IsRunning, 232 | action_root.join('is_running') 233 | autoload :Suspend, 234 | action_root.join('suspend') 235 | autoload :Resume, 236 | action_root.join('resume') 237 | autoload :MessageAlreadyRunning, 238 | action_root.join('message_already_running') 239 | autoload :MessageNotRunning, 240 | action_root.join('message_not_running') 241 | autoload :MessageNotCreated, 242 | action_root.join('message_not_created') 243 | autoload :MessageNotSupported, 244 | action_root.join('message_not_supported') 245 | autoload :MessageWillNotDestroy, 246 | action_root.join('message_will_not_destroy') 247 | autoload :PowerOff, 248 | action_root.join('power_off') 249 | autoload :PowerOn, 250 | action_root.join('power_on') 251 | autoload :ReadSSHInfo, 252 | action_root.join('read_ssh_info') 253 | autoload :ReadState, 254 | action_root.join('read_state') 255 | end 256 | end 257 | end 258 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/connect_appcatalyst.rb: -------------------------------------------------------------------------------- 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 ConnectAppCatalyst 18 | def initialize(app, env) 19 | @app = app 20 | @logger = Log4r::Logger.new('vagrant_appcatalyst::action::connect_appcatalyst') 21 | end 22 | 23 | def call(env) 24 | config = env[:machine].provider_config 25 | 26 | @logger.info('Connecting to AppCatalyst...') 27 | 28 | @logger.debug("config.rest_port: #{config.rest_port}") unless config.rest_port.nil? 29 | 30 | if config.rest_port.nil? 31 | endpoint = 'http://localhost:8080' 32 | else 33 | endpoint = "http://localhost:#{config.rest_port}" 34 | end 35 | 36 | env[:appcatalyst_cnx] = Driver::Meta.new(endpoint) 37 | 38 | @logger.info('Logging into AppCatalyst...') 39 | 40 | @app.call env 41 | end 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/destroy_vm.rb: -------------------------------------------------------------------------------- 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 DestroyVM 18 | def initialize(app, env) 19 | @app = app 20 | @logger = Log4r::Logger.new('vagrant_appcatalyst::action::destroy_vm') 21 | end 22 | 23 | def call(env) 24 | env[:ui].info I18n.t("vagrant.actions.vm.destroy.destroying") 25 | env[:appcatalyst_cnx].delete_vm(env[:machine].id) 26 | env[:machine].id = nil 27 | 28 | @app.call(env) 29 | end 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/import.rb: -------------------------------------------------------------------------------- 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 'securerandom' 15 | 16 | module VagrantPlugins 17 | module AppCatalyst 18 | module Action 19 | class Import 20 | def initialize(app, _env) 21 | @app = app 22 | @logger = Log4r::Logger.new('vagrant_appcatalyst::action::import') 23 | end 24 | 25 | def call(env) 26 | env[:ui].info I18n.t('vagrant.actions.vm.import.importing', 27 | name: env[:machine].box.name) 28 | 29 | # Generate a random UUID for our box 30 | uuid = "vagrant-#{SecureRandom.uuid}" 31 | 32 | env[:ui].detail I18n.t('vagrant_appcatalyst.vm.cloning') 33 | 34 | env[:appcatalyst_cnx].clone_vm_in_directory( 35 | env[:machine].box.directory, 36 | "#{env[:machine].data_dir}/#{uuid}" 37 | ) 38 | 39 | vmx_file = Dir.glob( 40 | "#{env[:machine].data_dir}/#{uuid}/*.vmx" 41 | ).first 42 | 43 | env[:appcatalyst_cnx].set_vmx_value( 44 | vmx_file, 45 | 'memsize', 46 | env[:machine].provider_config.memory 47 | ) unless env[:machine].provider_config.memory.nil? 48 | 49 | env[:appcatalyst_cnx].set_vmx_value( 50 | vmx_file, 51 | 'numvcpus', 52 | env[:machine].provider_config.cpus 53 | ) unless env[:machine].provider_config.cpus.nil? 54 | 55 | # Make sure we use Virtual HW 11 56 | env[:appcatalyst_cnx].set_vmx_value(vmx_file, 'virtualHW.version', '11') 57 | 58 | # Make sure we use VGA only... 59 | env[:appcatalyst_cnx].set_vmx_value(vmx_file, 'svga.vgaOnly', 'true') 60 | 61 | # Reconfigure VM with additional parameters specified in the 62 | # Vagrantfile. 63 | unless env[:machine].provider_config.vmx.empty? 64 | @logger.debug( 65 | "Adding parameters to VMX: #{env[:machine].provider_config.vmx}" 66 | ) 67 | env[:machine].provider_config.vmx.each do |k, v| 68 | env[:appcatalyst_cnx].set_vmx_value(vmx_file, k, v) 69 | end 70 | end 71 | 72 | env[:appcatalyst_cnx].import_vm( 73 | uuid, 74 | "Vagrant: #{env[:machine].name}", 75 | vmx_file, 76 | 'vagrant' 77 | ) 78 | 79 | # If import has succeded, let's set machine id. 80 | env[:machine].id = uuid 81 | 82 | # If we got interrupted, then the import could have been 83 | # interrupted and its not a big deal. Just return out. 84 | return if env[:interrupted] 85 | 86 | # Flag as erroneous and return if import failed 87 | # TODO: raise correct error 88 | fail Vagrant::Errors::VMImportFailure unless env[:machine].id 89 | 90 | # Import completed successfully. Continue the chain 91 | @app.call(env) 92 | end 93 | 94 | def recover(env) 95 | if env[:machine].state.id != :not_created 96 | return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError) 97 | 98 | # If we're not supposed to destroy on error then just return 99 | return unless env[:destroy_on_error] 100 | 101 | # Interrupted, destroy the VM. We note that we don't want to 102 | # validate the configuration here, and we don't want to confirm 103 | # we want to destroy. 104 | destroy_env = env.clone 105 | destroy_env[:config_validate] = false 106 | destroy_env[:force_confirm_destroy] = true 107 | env[:action_runner].run(Action.action_destroy, destroy_env) 108 | end 109 | end 110 | end 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/is_created.rb: -------------------------------------------------------------------------------- 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 IsCreated 18 | def initialize(app, env) 19 | @app = app 20 | @logger = Log4r::Logger.new('vagrant_appcatalyst::action::is_created') 21 | end 22 | 23 | def call(env) 24 | # Set the result to be true if the machine is created. 25 | env[:result] = env[:machine].state.id != :not_created 26 | 27 | # Call the next if we have one (but we shouldn't, since this 28 | # middleware is built to run with the Call-type middlewares) 29 | @app.call(env) 30 | end 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/is_paused.rb: -------------------------------------------------------------------------------- 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 IsPaused 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | # Set the result to be true if the machine is suspended. 24 | env[:result] = env[:machine].state.id == :suspended 25 | 26 | # Call the next if we have one (but we shouldn't, since this 27 | # middleware is built to run with the Call-type middlewares) 28 | @app.call(env) 29 | end 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/is_running.rb: -------------------------------------------------------------------------------- 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 Action 16 | class IsRunning 17 | def initialize(app, env) 18 | @app = app 19 | end 20 | 21 | def call(env) 22 | # Set the result to be true if the machine is running. 23 | env[:result] = env[:machine].state.id == :running 24 | 25 | # Call the next if we have one (but we shouldn't, since this 26 | # middleware is built to run with the Call-type middlewares) 27 | @app.call(env) 28 | end 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/message_already_running.rb: -------------------------------------------------------------------------------- 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 MessageAlreadyRunning 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | env[:ui].info I18n.t("vagrant.commands.common.vm_already_running") 24 | @app.call(env) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/message_not_created.rb: -------------------------------------------------------------------------------- 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 MessageNotCreated 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | env[:ui].info I18n.t("vagrant.commands.common.vm_not_created") 24 | @app.call(env) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/message_not_running.rb: -------------------------------------------------------------------------------- 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 MessageNotRunning 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | env[:ui].info I18n.t("vagrant.commands.common.vm_not_running") 24 | @app.call(env) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/message_not_supported.rb: -------------------------------------------------------------------------------- 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 MessageNotSupported 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | env[:ui].error(I18n.t('vagrant_appcatalyst.errors.violations.operation_not_supported')) 24 | @app.call(env) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/message_will_not_destroy.rb: -------------------------------------------------------------------------------- 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 MessageWillNotDestroy 18 | def initialize(app, env) 19 | @app = app 20 | end 21 | 22 | def call(env) 23 | env[:ui].info I18n.t("vagrant.commands.destroy.will_not_destroy", 24 | name: env[:machine].name) 25 | @app.call(env) 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/power_off.rb: -------------------------------------------------------------------------------- 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 PowerOff 18 | def initialize(app, env) 19 | @app = app 20 | @logger = Log4r::Logger.new('vagrant_appcatalyst::action::poweroff') 21 | end 22 | 23 | def call(env) 24 | current_state = env[:machine].state.id 25 | if current_state == :running 26 | env[:ui].info(I18n.t("vagrant.actions.vm.halt.graceful")) 27 | begin 28 | env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'shutdown') 29 | rescue Errors::UnattendedCodeError 30 | env[:ui].info I18n.t("vagrant.actions.vm.halt.force") 31 | env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'off') 32 | end 33 | end 34 | 35 | @app.call(env) 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/power_on.rb: -------------------------------------------------------------------------------- 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 35 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/read_ssh_info.rb: -------------------------------------------------------------------------------- 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 57 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/read_state.rb: -------------------------------------------------------------------------------- 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 stopping") 48 | return :stopping 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 :suspending 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 :blocked 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 73 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/resume.rb: -------------------------------------------------------------------------------- 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 | current_state = env[:machine].state.id 25 | 26 | if current_state == :paused 27 | env[:ui].info I18n.t('vagrant.actions.vm.resume.unpausing') 28 | env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'unpause') 29 | elsif current_state == :suspended 30 | env[:ui].info I18n.t('vagrant.actions.vm.resume.resuming') 31 | env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'on') 32 | end 33 | @app.call(env) 34 | end 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/action/suspend.rb: -------------------------------------------------------------------------------- 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 | if env[:machine].state.id == :running 25 | env[:ui].info I18n.t('vagrant.actions.vm.suspend.suspending') 26 | env[:appcatalyst_cnx].set_vm_power(env[:machine].id, 'suspend') 27 | end 28 | 29 | @app.call(env) 30 | end 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/cap/mount_appcatalyst_shared_folder.rb: -------------------------------------------------------------------------------- 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 vmhgfs FUSE which is the preferred mount 38 | # style. 39 | mount_options = "-o allow_other,uid=#{mount_uid},gid=#{mount_gid}" 40 | mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options] 41 | mount_commands << "/usr/bin/vmhgfs-fuse #{mount_options} .host:/#{name} #{expanded_guest_path}" 42 | 43 | # second mount command fallsback to the kernel vmhgfs module and uses 44 | # getent to get the group. 45 | mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}" 46 | mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options] 47 | mount_commands << "mount -t vmhgfs #{mount_options} .host:/#{name} #{expanded_guest_path}" 48 | 49 | # Second mount command uses the old style `id -g` 50 | mount_options = "-o uid=#{mount_uid},gid=#{mount_gid_old}" 51 | mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options] 52 | mount_commands << "mount -t vmhgfs #{mount_options} .host:/#{name} #{expanded_guest_path}" 53 | 54 | # Create the guest path if it doesn't exist 55 | machine.communicate.sudo("mkdir -p #{expanded_guest_path}") 56 | 57 | # Get rid of the default /mnt/hgfs mount point 58 | machine.communicate.sudo('mountpoint -q /mnt/hgfs && umount /mnt/hgfs || true') 59 | 60 | # Attempt to mount the folder. We retry here a few times because 61 | # it can fail early on. 62 | attempts = 0 63 | loop do 64 | success = true 65 | 66 | stderr = "" 67 | mount_commands.each do |command| 68 | no_such_device = false 69 | stderr = "" 70 | status = machine.communicate.sudo(command, error_check: false) do |type, data| 71 | if type == :stderr 72 | no_such_device = true if data =~ /No such device/i 73 | stderr += data.to_s 74 | end 75 | end 76 | 77 | success = status == 0 && !no_such_device 78 | break if success 79 | end 80 | 81 | break if success 82 | 83 | attempts += 1 84 | if attempts > 10 85 | raise Vagrant::Errors::LinuxMountFailed, 86 | command: mount_commands.join("\n"), 87 | output: stderr 88 | end 89 | 90 | sleep(2*attempts) 91 | end 92 | 93 | # Emit an upstart event if we can 94 | if machine.communicate.test("test -x /sbin/initctl") 95 | machine.communicate.sudo( 96 | "/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}") 97 | end 98 | end 99 | 100 | def self.unmount_appcatalyst_shared_folder(machine, guestpath, options) 101 | result = machine.communicate.sudo( 102 | "umount #{guestpath}", error_check: false) 103 | if result == 0 104 | machine.communicate.sudo("rmdir #{guestpath}", error_check: false) 105 | end 106 | end 107 | end 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/cap/public_address.rb: -------------------------------------------------------------------------------- 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 32 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/config.rb: -------------------------------------------------------------------------------- 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 | # Shortcut to set memory in the VM 27 | # 28 | # @return [String] 29 | attr_accessor :memory 30 | 31 | # Shortcut to set cpus in the VM 32 | # 33 | # @return [String] 34 | attr_accessor :cpus 35 | 36 | # REST API daemon port, default 8080 37 | # 38 | # @return [String] 39 | attr_accessor :rest_port 40 | 41 | def initialize 42 | self.vmx = {} 43 | end 44 | 45 | def validate(machine) 46 | 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/driver/base.rb: -------------------------------------------------------------------------------- 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 132 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/driver/meta.rb: -------------------------------------------------------------------------------- 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 107 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/driver/version_1_0.rb: -------------------------------------------------------------------------------- 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 224 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/errors.rb: -------------------------------------------------------------------------------- 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 45 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/plugin.rb: -------------------------------------------------------------------------------- 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 112 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/provider.rb: -------------------------------------------------------------------------------- 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' 16 | 17 | module VagrantPlugins 18 | module AppCatalyst 19 | class Provider < Vagrant.plugin('2', :provider) 20 | def initialize(machine) 21 | @logger = Log4r::Logger.new("vagrant::provider::vmware_appcatalyst") 22 | @machine = machine 23 | end 24 | 25 | def action(name) 26 | action_method = "action_#{name}" 27 | return Action.send(action_method) if Action.respond_to?(action_method) 28 | nil 29 | end 30 | 31 | def ssh_info 32 | env = @machine.action('read_ssh_info') 33 | env[:machine_ssh_info] 34 | end 35 | 36 | def state 37 | env = @machine.action('read_state') 38 | 39 | state_id = env[:machine_state_id] 40 | 41 | # Translate into short/long descriptions 42 | short = state_id.to_s.gsub("_", " ") 43 | long = I18n.t("vagrant_appcatalyst.commands.status.#{state_id}") 44 | 45 | # If we're not created, then specify the special ID flag 46 | if state_id == :not_created 47 | state_id = Vagrant::MachineState::NOT_CREATED_ID 48 | end 49 | 50 | # Return the MachineState object 51 | Vagrant::MachineState.new(state_id, short, long) 52 | end 53 | 54 | def to_s 55 | id = @machine.id.nil? ? 'new' : @machine.id 56 | "AppCatalyst (#{id})" 57 | end 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/synced_folder.rb: -------------------------------------------------------------------------------- 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/util/platform" 15 | 16 | module VagrantPlugins 17 | module AppCatalyst 18 | class SyncedFolder < Vagrant.plugin("2", :synced_folder) 19 | def usable?(machine, raise_errors=false) 20 | return false if machine.provider_name != :vmware_appcatalyst 21 | 22 | machine.provider_config.functional_hgfs 23 | end 24 | 25 | def prepare(machine, folders, _opts) 26 | @machine = machine 27 | share_folders(machine, folders, false) 28 | end 29 | 30 | def enable(machine, folders, _opts) 31 | share_folders(machine, folders, true) 32 | 33 | folders = folders.sort_by do |id, data| 34 | if data[:guestpath] 35 | data[:guestpath].length 36 | else 37 | 10_000 38 | end 39 | end 40 | 41 | machine.ui.output(I18n.t('vagrant.actions.vm.share_folders.mounting')) 42 | folders.each do |id, data| 43 | if data[:guestpath] 44 | machine.ui.detail( 45 | I18n.t('vagrant.actions.vm.share_folders.mounting_entry', 46 | guestpath: data[:guestpath], 47 | hostpath: data[:hostpath])) 48 | data = data.dup 49 | 50 | ssh_info = machine.ssh_info 51 | data[:owner] ||= ssh_info[:username] 52 | data[:group] ||= ssh_info[:username] 53 | 54 | machine.guest.capability( 55 | :mount_appcatalyst_shared_folder, 56 | os_friendly_id(id), data[:guestpath], data) 57 | else 58 | machine.ui.detail( 59 | I18n.t('vagrant.actions.vm.share_folders.nomount_entry', 60 | hostpath: data[:hostpath])) 61 | end 62 | end 63 | end 64 | 65 | def disable(machine, folders, _opts) 66 | if machine.guest.capability?(:unmount_appcatalyst_shared_folder) 67 | folders.each do |_, data| 68 | machine.guest.capability( 69 | :unmount_appcatalyst_shared_folder, 70 | data[:guestpath], data) 71 | end 72 | end 73 | 74 | names = folders.map { |id, _| os_friendly_id(id) } 75 | env = @machine.action('connect') 76 | names.each do |name| 77 | env[:appcatalyst_cnx].delete_vm_shared_folder(env[:machine].id, name) 78 | end 79 | end 80 | 81 | def cleanup(machine, _) 82 | @machine = machine 83 | env = @machine.action('connect') 84 | 85 | if machine.id && machine.id != '' 86 | env[:appcatalyst_cnx].get_vm_shared_folders(env[:machine].id).each do |folder| 87 | env[:appcatalyst_cnx].delete_vm_shared_folder(env[:machine].id, folder) 88 | end 89 | end 90 | end 91 | 92 | protected 93 | 94 | def os_friendly_id(id) 95 | id.gsub(/[\/]/, '_').sub(/^_/, '') 96 | end 97 | 98 | def share_folders(_, folders, transient) 99 | env = @machine.action('connect') 100 | 101 | defs = [] 102 | folders.each do |id, data| 103 | hostpath = data[:hostpath] 104 | unless data[:hostpath_exact] 105 | hostpath = Vagrant::Util::Platform.cygwin_windows_path(hostpath) 106 | end 107 | 108 | if (!!data[:transient]) == transient 109 | defs << { 110 | name: os_friendly_id(id), 111 | hostpath: hostpath.to_s, 112 | transient: transient, 113 | } 114 | end 115 | end 116 | env[:appcatalyst_cnx].set_vm_shared_folders(env[:machine].id, 'true') 117 | defs.each do |folder| 118 | env[:appcatalyst_cnx].add_vm_shared_folder(env[:machine].id, folder[:name], folder[:hostpath], 4) 119 | end 120 | end 121 | end 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /lib/vagrant-vmware-appcatalyst/version.rb: -------------------------------------------------------------------------------- 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 | VERSION = '1.1.1' 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /locales/en.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015 VMware, Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | # use this file except in compliance with the License. You may obtain a copy of 5 | # the License at http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, without 9 | # warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the 10 | # License for the specific language governing permissions and limitations under 11 | # the License. 12 | en: 13 | vagrant_appcatalyst: 14 | commands: 15 | status: 16 | stopped: |- 17 | The VM is powered off. To restart the VM, simply run `vagrant up` 18 | stopping: |- 19 | The VM is stopping. 20 | not_created: |- 21 | The environment has not yet been created. Run `vagrant up` to 22 | create the environment. If a machine is not created, only the 23 | default provider will be shown. So if a provider is not listed, 24 | then the machine is not created for that environment. 25 | running: |- 26 | The VM is running. To stop this VM, you can run `vagrant halt` to 27 | shut it down forcefully, or you can run `vagrant suspend` to simply 28 | suspend the virtual machine. In either case, to restart it again, 29 | simply run `vagrant up`. 30 | suspending: |- 31 | The VM is currently saving its state. In a few moments this state 32 | should transition to "suspended." Please run `vagrant status` again 33 | in a few seconds. 34 | suspended: |- 35 | To resume this VM, simply run `vagrant resume` or `vagrant up`. 36 | output: |- 37 | Current machine states: 38 | 39 | %{states} 40 | 41 | %{message} 42 | blocked: |- 43 | The VM is "blocked" This is a very rare state which means that 44 | AppCatalyst is unable to start the VM as the VMX requires manual 45 | intervention. The only known solution to this problem is to destroy 46 | your machine, sorry. 47 | listing: |- 48 | This environment represents multiple VMs. The VMs are all listed 49 | above with their current state. For more information about a specific 50 | VM, run `vagrant status NAME`. 51 | vm: 52 | cloning: |- 53 | Cloning VM, this might take a while... 54 | errors: 55 | appcatalyst_old_version: |- 56 | This version of AppCatalyst is not supported. 57 | violations: 58 | poweron_not_allowed: |- 59 | Power on was canceled, make sure the VM you're trying to power on does not violate AppCatalyst constraints. 60 | operation_not_supported: |- 61 | Operation not supported by AppCatalyst. 62 | rest_errors: 63 | unattended_code_error: |- 64 | Unattended code received %{message} 65 | endpoint_unavailable: |- 66 | Can't connect to AppCatalyst, please verify that the daemon has 67 | been started. If you are unsure, please run the following: 68 | 69 | $ nohup /opt/vmware/appcatalyst/bin/appcatalyst-daemon 2>&1 >/dev/null & 70 | -------------------------------------------------------------------------------- /vagrant-vmware-appcatalyst.gemspec: -------------------------------------------------------------------------------- 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 | $LOAD_PATH.unshift File.expand_path('../lib', __FILE__) 15 | require 'vagrant-vmware-appcatalyst/version' 16 | 17 | Gem::Specification.new do |s| 18 | s.name = 'vagrant-vmware-appcatalyst' 19 | s.version = VagrantPlugins::AppCatalyst::VERSION 20 | s.platform = Gem::Platform::RUBY 21 | s.authors = ['Fabio Rapposelli'] 22 | s.email = ['fabio@vmware.com'] 23 | s.homepage = 'https://github.com/vmware/vagrant-vmware-appcatalyst' 24 | s.license = 'Apache License 2.0' 25 | s.summary = 'VMware AppCatalyst® provider' 26 | s.description = 'Enables Vagrant to manage machines with VMware AppCatalyst®.' 27 | 28 | s.add_runtime_dependency 'i18n', '~> 0.6' 29 | s.add_runtime_dependency 'log4r', '~> 1.1' 30 | s.add_runtime_dependency 'httpclient', '~> 2.6' 31 | 32 | s.add_development_dependency 'rspec-core', '~> 2.14' 33 | s.add_development_dependency 'rspec-expectations', '~> 2.14' 34 | s.add_development_dependency 'rspec-mocks', '~> 2.14' 35 | 36 | s.add_development_dependency 'bundler', '~> 1.3' 37 | s.add_development_dependency 'rake' 38 | 39 | s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) 40 | s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } 41 | s.test_files = s.files.grep(%r{^(test|spec|features)/}) 42 | s.require_path = 'lib' 43 | end 44 | --------------------------------------------------------------------------------