vagrant-haipa 0.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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.vscode/launch.json +29 -0
  4. data/Gemfile +20 -0
  5. data/LICENSE +373 -0
  6. data/README.md +111 -0
  7. data/Rakefile +24 -0
  8. data/box/haipa.box +0 -0
  9. data/box/metadata.json +3 -0
  10. data/lib/vagrant-haipa.rb +20 -0
  11. data/lib/vagrant-haipa/actions.rb +209 -0
  12. data/lib/vagrant-haipa/actions/check_state.rb +19 -0
  13. data/lib/vagrant-haipa/actions/connect_haipa.rb +24 -0
  14. data/lib/vagrant-haipa/actions/create_machine.rb +56 -0
  15. data/lib/vagrant-haipa/actions/delete_machine.rb +31 -0
  16. data/lib/vagrant-haipa/actions/is_created.rb +18 -0
  17. data/lib/vagrant-haipa/actions/is_stopped.rb +18 -0
  18. data/lib/vagrant-haipa/actions/message_already_created.rb +16 -0
  19. data/lib/vagrant-haipa/actions/message_not_created.rb +16 -0
  20. data/lib/vagrant-haipa/actions/message_will_not_destroy.rb +16 -0
  21. data/lib/vagrant-haipa/actions/modify_provision_path.rb +38 -0
  22. data/lib/vagrant-haipa/actions/set_name.rb +53 -0
  23. data/lib/vagrant-haipa/actions/shut_down.rb +33 -0
  24. data/lib/vagrant-haipa/actions/start_machine.rb +34 -0
  25. data/lib/vagrant-haipa/actions/stop_machine.rb +33 -0
  26. data/lib/vagrant-haipa/actions/wait_for_ip_address.rb +32 -0
  27. data/lib/vagrant-haipa/config.rb +54 -0
  28. data/lib/vagrant-haipa/errors.rb +41 -0
  29. data/lib/vagrant-haipa/helpers/client.rb +111 -0
  30. data/lib/vagrant-haipa/helpers/result.rb +40 -0
  31. data/lib/vagrant-haipa/plugin.rb +22 -0
  32. data/lib/vagrant-haipa/provider.rb +118 -0
  33. data/lib/vagrant-haipa/version.rb +5 -0
  34. data/locales/en.yml +95 -0
  35. data/test/Vagrantfile +43 -0
  36. data/test/cookbooks/test/recipes/default.rb +1 -0
  37. data/test/scripts/provision.sh +3 -0
  38. data/test/test.sh +13 -0
  39. data/test/test_id_rsa +27 -0
  40. data/test/test_id_rsa.pub +1 -0
  41. data/vagrant +27 -0
  42. data/vagrant-haipa.gemspec +21 -0
  43. metadata +132 -0
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ Haipa Vagrant Provider
2
+ =================================
3
+
4
+
5
+ `vagrant-haipa` is a Vagrant provider plugin that supports the management of Hyper-V virtual machines with [Haipa](http://www.haipa.io).
6
+
7
+ Features include:
8
+ - Create and destroy Haipa Machines
9
+ - Power on and off Haipa Machines
10
+
11
+
12
+ Install
13
+ -------
14
+ Install the provider plugin using the Vagrant command-line interface:
15
+
16
+ `vagrant plugin install vagrant-haipa`
17
+
18
+
19
+ Configure
20
+ ---------
21
+ Once the provider has been installed, you will need to configure your project to use it. See the following example for a basic `Vagrantfile` implementation:
22
+
23
+ ```ruby
24
+ config.vm.define :ubuntu do |ubuntu|
25
+ ubuntu.vm.provider :haipa do |provider|
26
+ provider.vm_config = {
27
+ 'Memory' => {
28
+ 'Startup' => 2048
29
+ },
30
+ 'Disks' => [
31
+ {
32
+ "Template" => 'c:\hyperv-templates\ubuntu-xenial.vhdx',
33
+ "Size" => 20
34
+ }
35
+ ],
36
+ 'NetworkAdapters' => [
37
+ {
38
+ "Name" => "eth0",
39
+ "SwitchName" => "Default Switch",
40
+ }
41
+ ]
42
+ }
43
+ end
44
+ end
45
+ end
46
+ ```
47
+
48
+
49
+ **Supported Configuration Attributes**
50
+
51
+ The following attributes are available to further configure the provider:
52
+ - `provider.vm_config`
53
+ * A Hash with the Haipa vm configuration
54
+ - `provider.provision`
55
+ * A Hash with the Haipa provision configuration
56
+
57
+ Run
58
+ ---
59
+ After creating your project's `Vagrantfile` with the required configuration
60
+ attributes described above, you may create a new Machine with the following
61
+ command:
62
+
63
+ $ vagrant up --provider=haipa
64
+
65
+ This command will create a new machine, setup your SSH key for authentication,
66
+ create a new user account, and run the provisioners you have configured.
67
+
68
+ **Supported Commands**
69
+
70
+ The provider supports the following Vagrant sub-commands:
71
+ - `vagrant destroy` - Destroys the machine instance.
72
+ - `vagrant ssh` - Logs into the machine instance using the configured user account.
73
+ - `vagrant halt` - Powers off the machine instance.
74
+ - `vagrant provision` - Runs the configured provisioners and rsyncs any specified `config.vm.synced_folder`.
75
+ - `vagrant status` - Outputs the status (active, off, not created) for the machine instance.
76
+
77
+
78
+ Troubleshooting
79
+ ---------------
80
+ Before submitting a GitHub issue, please ensure both Vagrant and vagrant-haipa are fully up-to-date.
81
+ * For the latest Vagrant version, please visit the [Vagrant](https://www.vagrantup.com/) website
82
+ * To update Vagrant plugins, run the following command: `vagrant plugin update`
83
+
84
+
85
+ Contribute
86
+ ----------
87
+ To contribute, fork then clone the repository, and then the following:
88
+
89
+ **Developing**
90
+
91
+ 1. Install [Bundler](http://bundler.io/)
92
+ 2. Currently the Bundler version is locked to 1.7.9, please install this version.
93
+ * `sudo gem install bundler -v '1.7.9'`
94
+ 3. Then install vagrant-haipa dependencies:
95
+ * `bundle _1.7.9_ install`
96
+ 4. Do your development and run a few commands, one to get started would be:
97
+ * `bundle _1.7.9_ exec vagrant haipa-list images`
98
+ 5. You can then run a test:
99
+ * `bundle _1.7.9_ exec rake test`
100
+ 6. Once you are satisfied with your changes, please submit a pull request.
101
+
102
+ **Testing**
103
+
104
+ 1. Build and package your newly developed code:
105
+ * `rake gem:build`
106
+ 2. Then install the packaged plugin:
107
+ * `vagrant plugin install pkg/vagrant-haipa-*.gem`
108
+ 3. Once you're done testing, roll-back to the latest released version:
109
+ * `vagrant plugin uninstall vagrant-haipa`
110
+ * `vagrant plugin install vagrant-haipa`
111
+ 4. Once you're satisfied developing and testing your new code, please submit a pull request for review.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+
5
+ namespace :gem do
6
+ Bundler::GemHelper.install_tasks
7
+ end
8
+
9
+ task :test do
10
+ result = sh 'bash test/test.sh'
11
+
12
+ if result
13
+ puts 'Success!'
14
+ else
15
+ puts 'Failure!'
16
+ exit 1
17
+ end
18
+ end
19
+
20
+ def env
21
+ ['DO_CLIENT_ID', 'DO_API_KEY', 'VAGRANT_LOG'].inject('') do |acc, key|
22
+ acc += "#{key}=#{ENV[key] || 'error'} "
23
+ end
24
+ end
data/box/haipa.box ADDED
Binary file
data/box/metadata.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "haipa"
3
+ }
@@ -0,0 +1,20 @@
1
+ require 'vagrant-haipa/version'
2
+ require 'vagrant-haipa/plugin'
3
+ require 'vagrant-haipa/errors'
4
+
5
+ module VagrantPlugins
6
+ module Haipa
7
+ def self.source_root
8
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
9
+ end
10
+
11
+ def self.public_key(private_key_path)
12
+ File.read("#{private_key_path}.pub")
13
+ rescue
14
+ raise Errors::PublicKeyError, :path => "#{private_key_path}.pub"
15
+ end
16
+
17
+ I18n.load_path << File.expand_path('locales/en.yml', source_root)
18
+ I18n.reload!
19
+ end
20
+ end
@@ -0,0 +1,209 @@
1
+ module VagrantPlugins
2
+ module Haipa
3
+ module Actions
4
+ include Vagrant::Action::Builtin
5
+
6
+ # This action is called to halt the remote machine.
7
+ def self.action_halt
8
+ Vagrant::Action::Builder.new.tap do |b|
9
+ b.use ConfigValidate
10
+ b.use Call, IsCreated do |env, b2|
11
+ unless env[:result]
12
+ b2.use MessageNotCreated
13
+ next
14
+ end
15
+
16
+ b2.use ConnectHaipa
17
+ b2.use StopMachine
18
+ end
19
+ end
20
+ end
21
+
22
+ # This action is called to terminate the remote machine.
23
+ def self.action_destroy
24
+ Vagrant::Action::Builder.new.tap do |b|
25
+ b.use Call, DestroyConfirm do |env, b2|
26
+ if env[:result]
27
+ b2.use ConfigValidate
28
+ b2.use Call, IsCreated do |env2, b3|
29
+ unless env2[:result]
30
+ b3.use MessageNotCreated
31
+ next
32
+ end
33
+
34
+ b3.use ConnectHaipa
35
+ b3.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
36
+ b3.use DeleteMachine
37
+ end
38
+ else
39
+ b2.use MessageWillNotDestroy
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # This action is called when `vagrant provision` is called.
46
+ def self.action_provision
47
+ Vagrant::Action::Builder.new.tap do |b|
48
+ b.use ConfigValidate
49
+ b.use Call, IsCreated do |env, b2|
50
+ unless env[:result]
51
+ b2.use MessageNotCreated
52
+ next
53
+ end
54
+
55
+ b2.use Provision
56
+ b2.use SyncedFolderCleanup
57
+ b2.use SyncedFolders
58
+ end
59
+ end
60
+ end
61
+
62
+ # This action is called to read the SSH info of the machine. The
63
+ # resulting state is expected to be put into the `:machine_ssh_info`
64
+ # key.
65
+ def self.action_read_ssh_info
66
+ Vagrant::Action::Builder.new.tap do |b|
67
+ b.use ConfigValidate
68
+ b.use ConnectHaipa
69
+ b.use ReadSSHInfo
70
+ end
71
+ end
72
+
73
+ # This action is called to read the state of the machine. The
74
+ # resulting state is expected to be put into the `:machine_state_id`
75
+ # key.
76
+ def self.action_read_state
77
+ Vagrant::Action::Builder.new.tap do |b|
78
+ b.use ConfigValidate
79
+ b.use ConnectHaipa
80
+ b.use ReadState
81
+ end
82
+ end
83
+
84
+ # This action is called to SSH into the machine.
85
+ def self.action_ssh
86
+ Vagrant::Action::Builder.new.tap do |b|
87
+ b.use ConfigValidate
88
+ b.use Call, IsCreated do |env, b2|
89
+ unless env[:result]
90
+ b2.use MessageNotCreated
91
+ next
92
+ end
93
+
94
+ b2.use SSHExec
95
+ end
96
+ end
97
+ end
98
+
99
+ def self.action_ssh_run
100
+ Vagrant::Action::Builder.new.tap do |b|
101
+ b.use ConfigValidate
102
+ b.use Call, IsCreated do |env, b2|
103
+ unless env[:result]
104
+ b2.use MessageNotCreated
105
+ next
106
+ end
107
+
108
+ b2.use SSHRun
109
+ end
110
+ end
111
+ end
112
+
113
+ def self.action_ssh_ip
114
+ Vagrant::Action::Builder.new.tap do |b|
115
+ b.use Call, ConfigValidate do |env, b2|
116
+ b2.use WaitForIpAddress
117
+ end
118
+ end
119
+ end
120
+
121
+ def self.action_start
122
+ Vagrant::Action::Builder.new.tap do |b|
123
+ b.use Call, IsState, :running do |env1, b1|
124
+ if env1[:result]
125
+ b1.use action_provision
126
+ next
127
+ end
128
+
129
+ b1.use Call, IsState, :paused do |env2, b2|
130
+ if env2[:result]
131
+ b2.use action_resume
132
+ next
133
+ end
134
+
135
+ b2.use Provision
136
+ b2.use StartMachine
137
+ b2.use WaitForCommunicator, [:running]
138
+ b2.use SyncedFolderCleanup
139
+ b2.use SyncedFolders
140
+ b2.use SetHostname
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ # This action is called to bring the box up from nothing.
147
+ def self.action_up
148
+ Vagrant::Action::Builder.new.tap do |b|
149
+ # b.use HandleBox
150
+ b.use ConfigValidate
151
+ # b.use BoxCheckOutdated
152
+ b.use ConnectHaipa
153
+ b.use Call, IsCreated do |env1, b1|
154
+ if env1[:result]
155
+ b1.use Call, IsStopped do |env2, b2|
156
+ if env2[:result]
157
+ b2.use action_start
158
+ else
159
+ b2.use MessageAlreadyCreated
160
+ end
161
+ end
162
+ else
163
+ b1.use SetName
164
+ b1.use CreateMachine
165
+ b1.use action_start
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ def self.action_reload
172
+ Vagrant::Action::Builder.new.tap do |b|
173
+ b.use ConfigValidate
174
+ b.use ConnectHaipa
175
+ b.use Call, IsCreated do |env, b2|
176
+ unless env[:result]
177
+ b2.use MessageNotCreated
178
+ next
179
+ end
180
+
181
+ b2.use action_halt
182
+ b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
183
+ if env2[:result]
184
+ b3.use action_up
185
+ else
186
+ # TODO we couldn't reach :stopped, what now?
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ # The autoload farm
194
+ action_root = Pathname.new(File.expand_path('../actions', __FILE__))
195
+ autoload :ConnectHaipa, action_root.join('connect_haipa')
196
+ autoload :IsCreated, action_root.join('is_created')
197
+ autoload :IsStopped, action_root.join('is_stopped')
198
+ autoload :MessageAlreadyCreated, action_root.join('message_already_created')
199
+ autoload :MessageNotCreated, action_root.join('message_not_created')
200
+ autoload :MessageWillNotDestroy, action_root.join('message_will_not_destroy')
201
+ autoload :CreateMachine, action_root.join('create_machine')
202
+ autoload :DeleteMachine, action_root.join('delete_machine')
203
+ autoload :StartMachine, action_root.join('start_machine')
204
+ autoload :StopMachine, action_root.join('stop_machine')
205
+ autoload :WaitForIpAddress, action_root.join('wait_for_ip_address')
206
+ autoload :SetName, action_root.join('set_name')
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module Haipa
3
+ module Actions
4
+ class CheckState
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::haipa::check_state')
9
+ end
10
+
11
+ def call(env)
12
+ env[:machine_state] = @machine.state.id
13
+ @logger.info "Machine state is '#{@machine.state.id}'"
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'vagrant-haipa'
2
+
3
+ module VagrantPlugins
4
+ module Haipa
5
+ module Actions
6
+ class ConnectHaipa
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::haipa::ConnectHaipa')
14
+ end
15
+
16
+ def call(env)
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,56 @@
1
+ require 'vagrant-haipa/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Haipa
5
+ module Actions
6
+ class CreateMachine
7
+ include Helpers::Client
8
+ include Vagrant::Util::Retryable
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @machine = env[:machine]
13
+ @client = client
14
+ @logger = Log4r::Logger.new('vagrant::haipa::create_machine')
15
+ end
16
+
17
+ def call(env)
18
+ ssh_key_id = [env[:ssh_key_id]]
19
+
20
+ # submit new machine request
21
+ result = @client.post('/odata/Machines', {
22
+
23
+ 'Name' => env[:generated_name],
24
+ 'VM' => @machine.provider_config.vm_config,
25
+ "Provisioning" => @machine.provider_config.provision
26
+ })
27
+
28
+ # wait for request to complete
29
+ env[:ui].info I18n.t('vagrant_haipa.info.creating')
30
+ @client.wait_for_event(env, result['Id'])
31
+
32
+ # assign the machine id for reference in other commands
33
+ operation_result = @client.request("odata/Operations(#{result['Id']})")
34
+ @machine.id = operation_result['MachineGuid'].to_s
35
+
36
+ @app.call(env)
37
+ end
38
+
39
+ # Both the recover and terminate are stolen almost verbatim from
40
+ # the Vagrant AWS provider up action
41
+ def recover(env)
42
+ return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
43
+ terminate(env) if @machine.state.id != :not_created
44
+ end
45
+
46
+ def terminate(env)
47
+ destroy_env = env.dup
48
+ destroy_env.delete(:interrupted)
49
+ destroy_env[:config_validate] = false
50
+ destroy_env[:force_confirm_destroy] = true
51
+ env[:action_runner].run(Actions.action_destroy, destroy_env)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end