vagrant-vmpooler 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/.gitignore +21 -0
- data/Gemfile +15 -0
- data/LICENSE +15 -0
- data/README.md +143 -0
- data/Rakefile +22 -0
- data/example_box/Vagrantfile +22 -0
- data/example_box/dummy.box +0 -0
- data/example_box/metadata.json +3 -0
- data/example_box/readme.md +8 -0
- data/lib/vagrant-vmpooler.rb +53 -0
- data/lib/vagrant-vmpooler/action.rb +212 -0
- data/lib/vagrant-vmpooler/action/create_server.rb +103 -0
- data/lib/vagrant-vmpooler/action/delete_server.rb +50 -0
- data/lib/vagrant-vmpooler/action/hard_reboot_server.rb +24 -0
- data/lib/vagrant-vmpooler/action/is_created.rb +16 -0
- data/lib/vagrant-vmpooler/action/is_paused.rb +16 -0
- data/lib/vagrant-vmpooler/action/is_suspended.rb +16 -0
- data/lib/vagrant-vmpooler/action/message_already_created.rb +16 -0
- data/lib/vagrant-vmpooler/action/message_not_created.rb +16 -0
- data/lib/vagrant-vmpooler/action/message_server_running.rb +16 -0
- data/lib/vagrant-vmpooler/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-vmpooler/action/pause_server.rb +24 -0
- data/lib/vagrant-vmpooler/action/read_ssh_info.rb +56 -0
- data/lib/vagrant-vmpooler/action/read_state.rb +41 -0
- data/lib/vagrant-vmpooler/action/reboot_server.rb +24 -0
- data/lib/vagrant-vmpooler/action/resume_server.rb +25 -0
- data/lib/vagrant-vmpooler/action/setup_rsync.rb +40 -0
- data/lib/vagrant-vmpooler/action/suspend_server.rb +24 -0
- data/lib/vagrant-vmpooler/action/sync_folders.rb +104 -0
- data/lib/vagrant-vmpooler/action/take_snapshot.rb +35 -0
- data/lib/vagrant-vmpooler/action/wait_for_state.rb +38 -0
- data/lib/vagrant-vmpooler/config.rb +100 -0
- data/lib/vagrant-vmpooler/errors.rb +31 -0
- data/lib/vagrant-vmpooler/plugin.rb +30 -0
- data/lib/vagrant-vmpooler/provider.rb +55 -0
- data/lib/vagrant-vmpooler/version.rb +5 -0
- data/locales/en.yml +151 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/vagrant-vmpooler/config_spec.rb +44 -0
- data/vagrant-vmpooler.gemspec +23 -0
- metadata +45 -3
@@ -0,0 +1,25 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Vmpooler
|
5
|
+
module Action
|
6
|
+
# This starts a suspended server, if there is one.
|
7
|
+
class ResumeServer
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_vmpooler::action::resume_server")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
if env[:machine].id
|
15
|
+
env[:ui].info(I18n.t("vagrant_vmpooler.resuming_server"))
|
16
|
+
|
17
|
+
# raise "not implemented"
|
18
|
+
end
|
19
|
+
|
20
|
+
@app.call(env)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module VagrantPlugins
|
3
|
+
module Vmpooler
|
4
|
+
module Action
|
5
|
+
class SetupRsync
|
6
|
+
def initialize(app, env)
|
7
|
+
@app = app
|
8
|
+
@logger = Log4r::Logger.new("vagrant_vmpooler::action::setup_rsync")
|
9
|
+
end
|
10
|
+
|
11
|
+
def determine_packman(os_flavor)
|
12
|
+
if os_flavor =~ /centos|fedora|redhat/i
|
13
|
+
cmd_install_rsync = "yum install rsync.x86_64 -y"
|
14
|
+
elsif os_flavor =~ /debian|ubuntu/i
|
15
|
+
cmd_install_rsync = "apt-get install rsync -y"
|
16
|
+
else
|
17
|
+
cmd_install_rsync = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
cmd_install_rsync
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
ssh_info = env[:machine].ssh_info
|
25
|
+
os_flavor = env[:machine].provider_config.os
|
26
|
+
cmd_install_rsync = determine_packman(os_flavor)
|
27
|
+
|
28
|
+
if cmd_install_rsync
|
29
|
+
env[:ui].info(I18n.t("vagrant_vmpooler.install_rsync"))
|
30
|
+
env[:machine].communicate.execute(cmd_install_rsync, :error_check => true)
|
31
|
+
else
|
32
|
+
env[:ui].warn(I18n.t("vagrant_vmpooler.no_install_rsync"))
|
33
|
+
end
|
34
|
+
|
35
|
+
@app.call(env)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Vmpooler
|
5
|
+
module Action
|
6
|
+
# This deletes the running server, if there is one.
|
7
|
+
class SuspendServer
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_vmpooler::action::suspend_server")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
if env[:machine].id
|
15
|
+
env[:ui].info(I18n.t("vagrant_vmpooler.suspending_server"))
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
require "vagrant/util/subprocess"
|
4
|
+
require "vagrant/util/which"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module Vmpooler
|
8
|
+
module Action
|
9
|
+
# This middleware uses `rsync` to sync the folders over to the
|
10
|
+
# remote instance.
|
11
|
+
class SyncFolders
|
12
|
+
def initialize(app, env)
|
13
|
+
@app = app
|
14
|
+
@logger = Log4r::Logger.new("vagrant_vmpooler::action::sync_folders")
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
@app.call(env)
|
19
|
+
|
20
|
+
ssh_info = env[:machine].ssh_info
|
21
|
+
|
22
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
23
|
+
# ignore disabled shared folders
|
24
|
+
if data[:disabled]
|
25
|
+
@logger.info "Not syncing disabled folder: #{data[:hostpath]} => #{data[:guestpath]}"
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
unless Vagrant::Util::Which.which('rsync')
|
30
|
+
@logger.info "please install rsync locally first"
|
31
|
+
break
|
32
|
+
end
|
33
|
+
|
34
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
35
|
+
# rsync interprets paths with colons as remote locations.
|
36
|
+
# "cygdrive" path for cygwin on windows.
|
37
|
+
if Vagrant::Util::Platform.windows?
|
38
|
+
hostpath = Vagrant::Util::Subprocess.execute("cygpath", "-u", "-a", hostpath).stdout.chomp
|
39
|
+
end
|
40
|
+
guestpath = data[:guestpath]
|
41
|
+
|
42
|
+
# Make sure there is a trailing slash on the host path to
|
43
|
+
# avoid creating an additional directory with rsync
|
44
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
45
|
+
|
46
|
+
env[:ui].info(I18n.t("vagrant_vmpooler.rsync_folder",
|
47
|
+
:hostpath => hostpath,
|
48
|
+
:guestpath => guestpath))
|
49
|
+
|
50
|
+
# Create the guest path
|
51
|
+
# Use sudo only when it is necessary
|
52
|
+
cmd_mkdir = "mkdir -p '#{guestpath}'"
|
53
|
+
cmd_chown = "chown #{ssh_info[:username]} '#{guestpath}'"
|
54
|
+
if env[:machine].communicate.execute(cmd_mkdir, :error_check => false) != 0 then
|
55
|
+
env[:machine].communicate.sudo(cmd_mkdir)
|
56
|
+
end
|
57
|
+
if env[:machine].communicate.execute(cmd_chown, :error_check => false) != 0 then
|
58
|
+
env[:machine].communicate.sudo(cmd_chown)
|
59
|
+
end
|
60
|
+
|
61
|
+
#collect rsync excludes specified :rsync_excludes=>['path1',...] in synced_folder options
|
62
|
+
excludes = ['.vagrant/', 'Vagrantfile', *Array(data[:rsync_excludes])].uniq
|
63
|
+
|
64
|
+
# Rsync over to the guest path using the SSH info
|
65
|
+
if env[:machine].config.ssh.proxy_command
|
66
|
+
proxy_cmd = "-o ProxyCommand='#{env[:machine].config.ssh.proxy_command}'"
|
67
|
+
else
|
68
|
+
proxy_cmd = ''
|
69
|
+
end
|
70
|
+
|
71
|
+
# poor workaround for poor ipv6 handling of rsync
|
72
|
+
if ssh_info[:host].include? ':'
|
73
|
+
user_at_host = "[#{ssh_info[:username]}@#{ssh_info[:host]}]"
|
74
|
+
else
|
75
|
+
user_at_host = ssh_info[:username] + "@" + ssh_info[:host]
|
76
|
+
end
|
77
|
+
|
78
|
+
command = [
|
79
|
+
'rsync', '--verbose', '--archive', '-z', '--delete',
|
80
|
+
*excludes.map{|e|['--exclude', e]}.flatten,
|
81
|
+
'-e', "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no #{proxy_cmd} #{ssh_key_options(ssh_info)}",
|
82
|
+
hostpath,
|
83
|
+
user_at_host + ":" + guestpath]
|
84
|
+
|
85
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
86
|
+
if r.exit_code != 0
|
87
|
+
raise Errors::RsyncError,
|
88
|
+
:guestpath => guestpath,
|
89
|
+
:hostpath => hostpath,
|
90
|
+
:stderr => r.stderr
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def ssh_key_options(ssh_info)
|
98
|
+
# Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
|
99
|
+
Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Vmpooler
|
5
|
+
module Action
|
6
|
+
# This reboots a running server, if there is one.
|
7
|
+
class TakeSnapshot
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_vmpooler::action::take_snapshot")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
if env[:machine].id
|
15
|
+
env[:ui].info(I18n.t("vagrant_vmpooler.snapshoting_server"))
|
16
|
+
# make api call to snapshot server
|
17
|
+
provider_config = env[:machine].provider_config
|
18
|
+
|
19
|
+
token = provider_config.token
|
20
|
+
url = provider_config.url
|
21
|
+
verbose = provider_config.verbose
|
22
|
+
hostname = env[:machine].id
|
23
|
+
response = Pooler.snapshot(verbose, url, hostname, token)
|
24
|
+
if response['ok'] == false
|
25
|
+
env[:ui].info(I81n.t("vagrant_vmpooler.errors.failed_snapshot"))
|
26
|
+
env[:ui].info(response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Vmpooler
|
6
|
+
module Action
|
7
|
+
# This action will wait for a machine to reach a specific state or quit by timeout.
|
8
|
+
class WaitForState
|
9
|
+
def initialize(app, env, state, timeout)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmpooler::action::wait_for_state')
|
12
|
+
@state = Array.new(state).flatten
|
13
|
+
@timeout = timeout
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
env[:result] = true
|
18
|
+
state = env[:machine].state.id.to_sym
|
19
|
+
|
20
|
+
if @state.include?(state)
|
21
|
+
@logger.info("Machine already at status #{ state.to_s }")
|
22
|
+
else
|
23
|
+
@logger.info("Waiting for machine to reach state...")
|
24
|
+
begin
|
25
|
+
Timeout.timeout(@timeout) do
|
26
|
+
sleep 2 until @state.include?(env[:machine].state.id)
|
27
|
+
end
|
28
|
+
rescue Timeout::Error
|
29
|
+
env[:result] = false
|
30
|
+
end
|
31
|
+
|
32
|
+
@app.call(env)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Vmpooler
|
6
|
+
class Config < Vagrant.plugin("2", :config)
|
7
|
+
# The token used to obtain vms
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :token
|
11
|
+
|
12
|
+
# The url to your vmpooler installation
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :url
|
16
|
+
|
17
|
+
# Whether or not to run vmfloaty
|
18
|
+
# commands in verbose mode
|
19
|
+
#
|
20
|
+
# @return [Boolean]
|
21
|
+
attr_accessor :verbose
|
22
|
+
|
23
|
+
# The type of operatingsystem to
|
24
|
+
# get from the pooler
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
attr_accessor :os
|
28
|
+
|
29
|
+
# The password to use to log
|
30
|
+
# into the vmpooler machine
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
attr_accessor :password
|
34
|
+
|
35
|
+
# How long the vm should stay
|
36
|
+
# active for
|
37
|
+
#
|
38
|
+
# @return [Integer]
|
39
|
+
attr_accessor :ttl
|
40
|
+
|
41
|
+
# Increases default disk space by
|
42
|
+
# this size
|
43
|
+
#
|
44
|
+
# @return [Integer]
|
45
|
+
attr_accessor :disk
|
46
|
+
|
47
|
+
#attr_accessor :user
|
48
|
+
|
49
|
+
# ----------------
|
50
|
+
# Internal methods
|
51
|
+
# ----------------
|
52
|
+
|
53
|
+
def read_config
|
54
|
+
conf_file = {}
|
55
|
+
begin
|
56
|
+
conf_file = YAML.load_file("#{Dir.home}/.vmfloaty.yml")
|
57
|
+
rescue
|
58
|
+
# vagrant debug?
|
59
|
+
end
|
60
|
+
conf_file
|
61
|
+
end
|
62
|
+
|
63
|
+
def finalize!
|
64
|
+
conf_file = read_config
|
65
|
+
|
66
|
+
if conf_file['token']
|
67
|
+
@token = conf_file['token']
|
68
|
+
else
|
69
|
+
@token = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
if conf_file['url']
|
73
|
+
@url = conf_file['url']
|
74
|
+
else
|
75
|
+
@url = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
@verbose = false if @verbose == UNSET_VALUE
|
79
|
+
@os = nil if @os == UNSET_VALUE
|
80
|
+
@ttl = nil if @ttl == UNSET_VALUE
|
81
|
+
@disk = nil if @disk == UNSET_VALUE
|
82
|
+
@password = nil if @password == UNSET_VALUE
|
83
|
+
end
|
84
|
+
|
85
|
+
# ----------------
|
86
|
+
# Provider methods
|
87
|
+
# ----------------
|
88
|
+
|
89
|
+
def initialize(verbose=false)
|
90
|
+
@token = UNSET_VALUE
|
91
|
+
@url = UNSET_VALUE
|
92
|
+
@verbose = UNSET_VALUE
|
93
|
+
@os = UNSET_VALUE
|
94
|
+
@ttl = UNSET_VALUE
|
95
|
+
@disk = UNSET_VALUE
|
96
|
+
@password = UNSET_VALUE
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Vmpooler
|
5
|
+
module Errors
|
6
|
+
class VagrantVmpoolerErrors < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_vmpooler.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class NoURLError < VagrantVmpoolerErrors
|
11
|
+
error_key(:vmpooler_url_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoOSError < VagrantVmpoolerErrors
|
15
|
+
error_key(:no_os_error)
|
16
|
+
end
|
17
|
+
|
18
|
+
class FailedRequest < VagrantVmpoolerErrors
|
19
|
+
error_key(:bad_request)
|
20
|
+
end
|
21
|
+
|
22
|
+
class RsyncError < VagrantVmpoolerErrors
|
23
|
+
error_key(:rsync_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class RsyncError < VagrantVmpoolerErrors
|
27
|
+
error_key(:install_rsync_error)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The Vagrant vmpooler plugin must be run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module Vmpooler
|
9
|
+
class Plugin < Vagrant.plugin("2")
|
10
|
+
name "Vmpooler"
|
11
|
+
description <<-DESC
|
12
|
+
This plugin installs a provider that allows Vagrant to manage
|
13
|
+
machines in vmpooler.
|
14
|
+
DESC
|
15
|
+
|
16
|
+
config(:vmpooler, :provider) do
|
17
|
+
require_relative "config"
|
18
|
+
Config
|
19
|
+
end
|
20
|
+
|
21
|
+
provider(:vmpooler, parallel:true) do
|
22
|
+
Vmpooler.init_i18n
|
23
|
+
Vmpooler.init_logging
|
24
|
+
|
25
|
+
require_relative 'provider'
|
26
|
+
Provider
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
require "vagrant-vmpooler/action"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Vmpooler
|
7
|
+
class Provider < Vagrant.plugin("2", :provider)
|
8
|
+
def initialize(machine)
|
9
|
+
@machine = machine
|
10
|
+
end
|
11
|
+
|
12
|
+
def action(name)
|
13
|
+
# Attempt to get the action method from the Action class if it
|
14
|
+
# exists, otherwise return nil to show that we don't support the
|
15
|
+
# given action.
|
16
|
+
action_method = "action_#{name}"
|
17
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def ssh_info
|
22
|
+
# Run a custom action called "read_ssh_info" which does what it
|
23
|
+
# says and puts the resulting SSH info into the `:machine_ssh_info`
|
24
|
+
# key in the environment.
|
25
|
+
env = @machine.action("read_ssh_info")
|
26
|
+
env[:machine_ssh_info]
|
27
|
+
end
|
28
|
+
|
29
|
+
def state
|
30
|
+
# Run a custom action we define called "read_state" which does
|
31
|
+
# what it says. It puts the state in the `:machine_state_id`
|
32
|
+
# key in the environment.
|
33
|
+
env = @machine.action("read_state")
|
34
|
+
|
35
|
+
state_id = env[:machine_state_id]
|
36
|
+
|
37
|
+
# Get the short and long description
|
38
|
+
short = I18n.t("vagrant_vmpooler.states.short_#{state_id}")
|
39
|
+
long = I18n.t("vagrant_vmpooler.states.long_#{state_id}")
|
40
|
+
|
41
|
+
# Return the MachineState object
|
42
|
+
Vagrant::MachineState.new(state_id, short, long)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
id = "new"
|
47
|
+
if !@machine.id.nil?
|
48
|
+
id = @machine.id
|
49
|
+
end
|
50
|
+
|
51
|
+
"Vmpooler (#{id})"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|