mcf-vmc-plugin 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.
- data/Rakefile +47 -0
- data/config/offline.conf +2 -0
- data/config/paths.yml +22 -0
- data/config/refresh_ip.rb +24 -0
- data/lib/mcf-vmc-plugin/errors.rb +4 -0
- data/lib/mcf-vmc-plugin/help.rb +4 -0
- data/lib/mcf-vmc-plugin/micro/micro.rb +56 -0
- data/lib/mcf-vmc-plugin/micro/switcher/base.rb +79 -0
- data/lib/mcf-vmc-plugin/micro/switcher/darwin.rb +21 -0
- data/lib/mcf-vmc-plugin/micro/switcher/dummy.rb +15 -0
- data/lib/mcf-vmc-plugin/micro/switcher/linux.rb +16 -0
- data/lib/mcf-vmc-plugin/micro/switcher/windows.rb +31 -0
- data/lib/mcf-vmc-plugin/micro/vmrun.rb +175 -0
- data/lib/mcf-vmc-plugin/plugin.rb +203 -0
- data/lib/mcf-vmc-plugin/version.rb +3 -0
- data/spec/plugin_spec.rb +68 -0
- data/spec/spec_helper.rb +11 -0
- metadata +142 -0
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
4
|
+
require "mcf-vmc-plugin/version"
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc "Run specs"
|
9
|
+
task :spec => ["bundler:install", "test:spec"]
|
10
|
+
|
11
|
+
desc "Run integration tests"
|
12
|
+
task :test => ["bundler:install", "test:integration"]
|
13
|
+
|
14
|
+
task :build do
|
15
|
+
sh "gem build mcf-vmc-plugin.gemspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :install => :build do
|
19
|
+
sh "gem install --local mcf-vmc-plugin-#{VMCMicro::VERSION}.gem"
|
20
|
+
end
|
21
|
+
|
22
|
+
task :uninstall do
|
23
|
+
sh "gem uninstall mcf-vmc-plugin"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :reinstall => [:uninstall, :install]
|
27
|
+
|
28
|
+
task :release => :build do
|
29
|
+
sh "gem push mcf-vmc-plugin-#{VMCMicro::VERSION}.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace "bundler" do
|
33
|
+
desc "Install gems"
|
34
|
+
task "install" do
|
35
|
+
sh("bundle install")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace "test" do
|
40
|
+
task "spec" do |t|
|
41
|
+
# nothing
|
42
|
+
end
|
43
|
+
|
44
|
+
task "integration" do |t|
|
45
|
+
sh("cd spec && bundle exec rake spec")
|
46
|
+
end
|
47
|
+
end
|
data/config/offline.conf
ADDED
data/config/paths.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
darwin:
|
2
|
+
vmrun:
|
3
|
+
- "/Applications/VMware Fusion.app/Contents/Library/"
|
4
|
+
- "/Applications/Fusion.app/Contents/Library/"
|
5
|
+
vmx:
|
6
|
+
- "~/Documents/Virtual Machines.localized/"
|
7
|
+
- "~/Documents/Virtual Machines/"
|
8
|
+
- "~/Desktop/"
|
9
|
+
|
10
|
+
linux:
|
11
|
+
vmrun:
|
12
|
+
- "/usr/bin/"
|
13
|
+
vmx:
|
14
|
+
- "~/"
|
15
|
+
|
16
|
+
windows:
|
17
|
+
vmrun:
|
18
|
+
- "c:\\Program Files (x86)\\"
|
19
|
+
- "c:\\Program Files\\"
|
20
|
+
vmx:
|
21
|
+
- "~\\Documents\\"
|
22
|
+
- "~\\Desktop\\"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/var/vcap/bosh/bin/ruby
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
A_ROOT_SERVER = '198.41.0.4'
|
5
|
+
|
6
|
+
begin
|
7
|
+
retries ||= 0
|
8
|
+
route ||= A_ROOT_SERVER
|
9
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
10
|
+
ip_address = UDPSocket.open do |s|
|
11
|
+
s.connect(route, 1); s.addr.last
|
12
|
+
end
|
13
|
+
rescue Errno::ENETUNREACH
|
14
|
+
# happens on boot when dhcp hasn't completed when we get here
|
15
|
+
sleep 3
|
16
|
+
retries += 1
|
17
|
+
retry if retries < 10
|
18
|
+
ensure
|
19
|
+
Socket.do_not_reverse_lookup = orig
|
20
|
+
end
|
21
|
+
|
22
|
+
File.open("/tmp/ip.txt", 'w') do |file|
|
23
|
+
file.write(ip_address)
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'find'
|
2
|
+
require "mcf-vmc-plugin/errors"
|
3
|
+
|
4
|
+
module VMCMicro
|
5
|
+
def config_file(file)
|
6
|
+
File.expand_path("../../../../config/#{file}", __FILE__)
|
7
|
+
end
|
8
|
+
|
9
|
+
def escape_path(path)
|
10
|
+
path = File.expand_path(path)
|
11
|
+
if RUBY_PLATFORM =~ /mingw|mswin32|cygwin/
|
12
|
+
if path.include?(' ')
|
13
|
+
'"' + path + '"'
|
14
|
+
else
|
15
|
+
path
|
16
|
+
end
|
17
|
+
else
|
18
|
+
path.gsub(' ', '\ ')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def locate_file(file, directory, search_paths)
|
23
|
+
search_paths.each do |path|
|
24
|
+
expanded_path = File.expand_path(path)
|
25
|
+
next unless File.exists?(expanded_path)
|
26
|
+
Find.find(expanded_path) do |current|
|
27
|
+
if File.directory?(current) && current.include?(directory)
|
28
|
+
full_path = File.join(current, file)
|
29
|
+
return escape_path(full_path) if File.exists?(full_path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_command(command, args=nil)
|
38
|
+
# TODO switch to using posix-spawn instead
|
39
|
+
result = %x{#{command} #{args} 2>&1}
|
40
|
+
if $?.exitstatus == 0
|
41
|
+
result.split(/\n/)
|
42
|
+
else
|
43
|
+
if block_given?
|
44
|
+
yield
|
45
|
+
else
|
46
|
+
raise VMCMicro::MCFError, "failed to execute #{command} #{args}:\n#{result}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module_function :config_file
|
52
|
+
module_function :escape_path
|
53
|
+
module_function :locate_file
|
54
|
+
module_function :run_command
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "mcf-vmc-plugin/errors"
|
2
|
+
|
3
|
+
module VMCMicro::Switcher
|
4
|
+
class Base
|
5
|
+
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
|
9
|
+
@vmrun = VMCMicro::VMrun.new(config)
|
10
|
+
end
|
11
|
+
|
12
|
+
#wrapper methods
|
13
|
+
def vmx
|
14
|
+
@vmrun.vmx
|
15
|
+
end
|
16
|
+
|
17
|
+
def domain
|
18
|
+
@vmrun.domain
|
19
|
+
end
|
20
|
+
|
21
|
+
def ip
|
22
|
+
@vmrun.ip
|
23
|
+
end
|
24
|
+
|
25
|
+
def running?
|
26
|
+
@vmrun.running?
|
27
|
+
end
|
28
|
+
|
29
|
+
def start!
|
30
|
+
@vmrun.start!
|
31
|
+
end
|
32
|
+
|
33
|
+
def ready?
|
34
|
+
@vmrun.ready?
|
35
|
+
end
|
36
|
+
|
37
|
+
def offline?
|
38
|
+
@vmrun.offline?
|
39
|
+
end
|
40
|
+
|
41
|
+
def nat?
|
42
|
+
@config['online_connection_type'] ||= @vmrun.connection_type
|
43
|
+
@config["online_connection_type"] == "nat"
|
44
|
+
end
|
45
|
+
|
46
|
+
def reset_to_nat!
|
47
|
+
@vmrun.connection_type = 'nat'
|
48
|
+
@vmrun.reset
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_host_dns!
|
52
|
+
@config['domain'] ||= @vmrun.domain
|
53
|
+
@config['ip'] ||= @vmrun.ip
|
54
|
+
set_nameserver(@config['domain'], @config['ip'])
|
55
|
+
end
|
56
|
+
|
57
|
+
def unset_host_dns!
|
58
|
+
@config['domain'] ||= @vmrun.domain
|
59
|
+
@config['ip'] ||= @vmrun.ip
|
60
|
+
unset_nameserver(@config['domain'], @config['ip'])
|
61
|
+
end
|
62
|
+
|
63
|
+
def offline!
|
64
|
+
if @vmrun.offline?
|
65
|
+
raise VMCMicro::MCFError, "Micro Cloud Foundry VM already in offline mode"
|
66
|
+
else
|
67
|
+
@vmrun.offline!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def online!
|
72
|
+
if @vmrun.offline?
|
73
|
+
@vmrun.online!
|
74
|
+
else
|
75
|
+
raise VMCMirco::MCFError, "Micro Cloud Foundry already in online mode"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "mcf-vmc-plugin/errors"
|
2
|
+
|
3
|
+
module VMCMicro::Switcher
|
4
|
+
|
5
|
+
class Darwin < Base
|
6
|
+
def adminrun(command)
|
7
|
+
VMCMicro.run_command("osascript", "-e 'do shell script \"#{command}\" with administrator privileges'")
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_nameserver(domain, ip)
|
11
|
+
File.open("/tmp/#{domain}", 'w') { |file| file.write("nameserver #{ip}") }
|
12
|
+
adminrun("mkdir -p /etc/resolver;mv /tmp/#{domain} /etc/resolver/")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unset_nameserver(domain, ip)
|
16
|
+
raise VMCMicro::MCFError, "domain missing" unless domain
|
17
|
+
adminrun("rm -f /etc/resolver/#{domain}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VMCMicro::Switcher
|
2
|
+
|
3
|
+
class Linux < Base
|
4
|
+
def set_nameserver(domain, ip)
|
5
|
+
VMCMicro.run_command("sudo", "sed -i'.backup' '1 i nameserver #{ip}' /etc/resolv.conf")
|
6
|
+
# lock resolv.conf so Network Manager doesn't clear out the file when offline
|
7
|
+
VMCMicro.run_command("sudo", "chattr +i /etc/resolv.conf")
|
8
|
+
end
|
9
|
+
|
10
|
+
def unset_nameserver(domain, ip)
|
11
|
+
VMCMicro.run_command("sudo", "chattr -i /etc/resolv.conf")
|
12
|
+
VMCMicro.run_command("sudo", "sed -i'.backup' '/#{ip}/d' /etc/resolv.conf")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module VMCMicro::Switcher
|
2
|
+
|
3
|
+
class Windows < Base
|
4
|
+
def version
|
5
|
+
VMCMicro.run_command("cmd", "/c ver").to_s.scan(/\d+\.\d+/).first.to_f
|
6
|
+
end
|
7
|
+
|
8
|
+
def adminrun(command, args=nil)
|
9
|
+
if version > 5.2
|
10
|
+
require 'win32ole'
|
11
|
+
shell = WIN32OLE.new("Shell.Application")
|
12
|
+
shell.ShellExecute(command, args, nil, "runas", 0)
|
13
|
+
else
|
14
|
+
# on older version this will try to run the command, and if you don't have
|
15
|
+
# admin privilges it will tell you so and exit
|
16
|
+
VMCMicro.run_command(command, args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# TODO better method to figure out the interface name is to get the NAT ip and find the
|
21
|
+
# interface with the correct subnet
|
22
|
+
def set_nameserver(domain, ip)
|
23
|
+
adminrun("netsh", "interface ip set dns \"VMware Network Adapter VMnet8\" static #{ip}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def unset_nameserver(domain, ip)
|
27
|
+
adminrun("netsh", "interface ip set dns \"VMware Network Adapter VMnet8\" static none")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require "mcf-vmc-plugin/errors"
|
2
|
+
|
3
|
+
module VMCMicro
|
4
|
+
class VMrun
|
5
|
+
attr_reader :vmx, :vmrun
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@platform = config[:platform]
|
9
|
+
@user = 'root' # must use root as we muck around with system settings
|
10
|
+
@password = config[:password]
|
11
|
+
@vmrun = config[:vmrun]
|
12
|
+
@vmx = config[:vmx]
|
13
|
+
|
14
|
+
# TODO honor TMPDIR
|
15
|
+
if @platform == :windows
|
16
|
+
@temp_dir = ENV['temp']
|
17
|
+
else
|
18
|
+
@temp_dir = '/tmp'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def vmx
|
23
|
+
@vmx
|
24
|
+
end
|
25
|
+
|
26
|
+
def connection_type
|
27
|
+
read_variable('ethernet0.connectionType')
|
28
|
+
end
|
29
|
+
|
30
|
+
def connection_type=(type)
|
31
|
+
write_variable("ethernet0.connectionType", type)
|
32
|
+
end
|
33
|
+
|
34
|
+
def nat?
|
35
|
+
connection_type == "nat"
|
36
|
+
end
|
37
|
+
|
38
|
+
def bridged?
|
39
|
+
connection_type == "bridged"
|
40
|
+
end
|
41
|
+
|
42
|
+
def domain
|
43
|
+
# switch to Dir.mktmpdir
|
44
|
+
state_config = VMCMicro.escape_path(File.join(@temp_dir, 'state.yml'))
|
45
|
+
run('CopyFileFromGuestToHost', "/var/vcap/bosh/state.yml #{state_config}")
|
46
|
+
bosh_config = YAML.load_file(state_config)
|
47
|
+
bosh_config['properties']['domain']
|
48
|
+
end
|
49
|
+
|
50
|
+
def ip
|
51
|
+
# switch to Dir.mktmpdir
|
52
|
+
path = VMCMicro.escape_path(VMCMicro.config_file('refresh_ip.rb'))
|
53
|
+
ip_file = VMCMicro.escape_path(File.join(@temp_dir, 'ip.txt'))
|
54
|
+
run('CopyFileFromHostToGuest', "#{path} /tmp/refresh_ip.rb")
|
55
|
+
run('runProgramInGuest', '/tmp/refresh_ip.rb')
|
56
|
+
run('CopyFileFromGuestToHost', "/tmp/ip.txt #{ip_file}")
|
57
|
+
File.open(ip_file, 'r') { |file| file.read }
|
58
|
+
end
|
59
|
+
|
60
|
+
def list
|
61
|
+
vms = run("list")
|
62
|
+
vms.delete_if { |line| line =~ /^Total/ }
|
63
|
+
vms.map { |line| VMCMicro.escape_path(File.expand_path(line)) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def offline?
|
67
|
+
command = "-gu #{@user} -gp #{@password} runProgramInGuest"
|
68
|
+
args = '/usr/bin/test -e /var/vcap/micro/offline'
|
69
|
+
# why not use run_command?
|
70
|
+
result = %x{#{@vmrun} #{command} #{@vmx} #{args}}
|
71
|
+
|
72
|
+
if result.include?('Guest program exited with non-zero exit code: 1')
|
73
|
+
return false
|
74
|
+
elsif $?.exitstatus == 0
|
75
|
+
return true
|
76
|
+
else
|
77
|
+
raise VMCMicro::MCFError, "failed to execute vmrun:\n#{result}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def offline!
|
82
|
+
path = VMCMicro.escape_path(VMCMicro.config_file('offline.conf'))
|
83
|
+
run('CopyFileFromHostToGuest', "#{path} /etc/dnsmasq.d/offline.conf")
|
84
|
+
run('runProgramInGuest', '/usr/bin/touch /var/vcap/micro/offline')
|
85
|
+
run('runProgramInGuest',
|
86
|
+
"/bin/sed -i -e 's/^[^#]/# &/g' /etc/dnsmasq.d/server || true")
|
87
|
+
restart_dnsmasq
|
88
|
+
end
|
89
|
+
|
90
|
+
def online!
|
91
|
+
run('runProgramInGuest', '/bin/rm -f /etc/dnsmasq.d/offline.conf')
|
92
|
+
run('runProgramInGuest', '/bin/rm -f /var/vcap/micro/offline')
|
93
|
+
run('runProgramInGuest',
|
94
|
+
"/bin/sed -i -e 's/^# //g' /etc/dnsmasq.d/server || true")
|
95
|
+
restart_dnsmasq
|
96
|
+
end
|
97
|
+
|
98
|
+
# check to see if the micro cloud has been configured
|
99
|
+
# uses default password to check
|
100
|
+
def ready?
|
101
|
+
command = "-gu root -gp 'ca$hc0w' runProgramInGuest"
|
102
|
+
args = '/usr/bin/test -e /var/vcap/micro/micro.json'
|
103
|
+
result = %x{#{@vmrun} #{command} #{@vmx} #{args}}
|
104
|
+
|
105
|
+
if result.include?('Invalid user name or password for the guest OS') || $?.exitstatus == 0
|
106
|
+
return true
|
107
|
+
elsif $?.exitstatus == 1
|
108
|
+
return false
|
109
|
+
else
|
110
|
+
raise VMCMicro::MCFError, "failed to execute vmrun:\n#{result}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def read_variable(var)
|
115
|
+
# TODO deal with non-ok return
|
116
|
+
run("readVariable", "runtimeConfig #{var}").first
|
117
|
+
end
|
118
|
+
|
119
|
+
def write_variable(var, value)
|
120
|
+
run('writeVariable', "runtimeConfig #{var} #{value}")
|
121
|
+
end
|
122
|
+
|
123
|
+
def reset
|
124
|
+
run('reset', 'soft')
|
125
|
+
end
|
126
|
+
|
127
|
+
def restart_dnsmasq
|
128
|
+
# restart command doesn't always work, start and stop seems to be more reliable
|
129
|
+
run('runProgramInGuest', '/etc/init.d/dnsmasq stop')
|
130
|
+
run('runProgramInGuest', '/etc/init.d/dnsmasq start')
|
131
|
+
end
|
132
|
+
|
133
|
+
def run(command, args=nil)
|
134
|
+
if command.include?('Guest')
|
135
|
+
command = "-gu #{@user} -gp #{@password} #{command}"
|
136
|
+
end
|
137
|
+
VMCMicro.run_command(@vmrun, "#{command} #{@vmx} #{args}")
|
138
|
+
end
|
139
|
+
|
140
|
+
def running?
|
141
|
+
vms = list
|
142
|
+
if @platform == :windows
|
143
|
+
vms.any? { |x|
|
144
|
+
x.downcase == @vmx.downcase
|
145
|
+
}
|
146
|
+
else
|
147
|
+
# Handle vmx being in a symlinked dir.
|
148
|
+
real_path = nil
|
149
|
+
begin
|
150
|
+
real_path = File.realpath(@vmx)
|
151
|
+
rescue
|
152
|
+
end
|
153
|
+
vms.include?(@vmx) || (real_path && vms.include?(real_path))
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def start!
|
158
|
+
run('start') unless running?
|
159
|
+
end
|
160
|
+
|
161
|
+
def stop!
|
162
|
+
run('stop') if running?
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.locate(platform)
|
166
|
+
paths = YAML.load_file(VMCMicro.config_file('paths.yml'))
|
167
|
+
vmrun_paths = paths[platform.to_s]['vmrun']
|
168
|
+
vmrun_exe = @platform == :windows ? 'vmrun.exe' : 'vmrun'
|
169
|
+
vmrun = VMCMicro.locate_file(vmrun_exe, "VMware", vmrun_paths)
|
170
|
+
err "Unable to locate vmrun, please supply --vmrun option" unless vmrun
|
171
|
+
vmrun
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "multi_json"
|
3
|
+
require "vmc/cli"
|
4
|
+
|
5
|
+
require "mcf-vmc-plugin/help"
|
6
|
+
require "mcf-vmc-plugin/micro/micro"
|
7
|
+
require "mcf-vmc-plugin/micro/vmrun"
|
8
|
+
require "mcf-vmc-plugin/micro/switcher/base"
|
9
|
+
require "mcf-vmc-plugin/micro/switcher/darwin"
|
10
|
+
require "mcf-vmc-plugin/micro/switcher/linux"
|
11
|
+
require "mcf-vmc-plugin/micro/switcher/windows"
|
12
|
+
|
13
|
+
module VMCMicro
|
14
|
+
class McfCommand < VMC::CLI
|
15
|
+
MICRO_FILE = '~/.vmc/micro.yml'
|
16
|
+
|
17
|
+
desc "Display Micro Cloud Foundry VM status"
|
18
|
+
group :mcf
|
19
|
+
input :vmx, :argument => :required,
|
20
|
+
:desc => "Path to micro.vmx"
|
21
|
+
input :password, :argument => :optional,
|
22
|
+
:desc => "Cleartext password for guest VM vcap user"
|
23
|
+
def micro_status
|
24
|
+
mode = runner.offline? ? 'offline' : 'online'
|
25
|
+
|
26
|
+
line "Micro Cloud Foundry VM currently in #{b(mode)} mode"
|
27
|
+
# should the VMX path be unescaped?
|
28
|
+
line "VMX Path: #{c(runner.vmx, :good)}"
|
29
|
+
line "Domain: #{c(runner.domain, :good)}"
|
30
|
+
line "IP Address: #{c(runner.ip, :good)}"
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Micro Cloud Foundry offline mode"
|
34
|
+
group :mcf
|
35
|
+
input :vmx, :argument => :required,
|
36
|
+
:desc => "Path to micro.vmx"
|
37
|
+
input :password, :argument => :optional,
|
38
|
+
:desc => "Cleartext password for guest VM vcap user"
|
39
|
+
def micro_offline
|
40
|
+
if !runner.nat?
|
41
|
+
if ask("Reconfigure MCF VM network to nat mode and reboot?", :default => true)
|
42
|
+
with_progress("Rebooting MCF VM") do
|
43
|
+
runner.reset_to_nat!
|
44
|
+
end
|
45
|
+
else
|
46
|
+
fail "Aborted"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
with_progress("Setting MCF VM to offline mode") do
|
51
|
+
runner.offline!
|
52
|
+
end
|
53
|
+
|
54
|
+
with_progress("Setting host DNS server") do
|
55
|
+
runner.set_host_dns!
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Micro Cloud Foundry online mode"
|
60
|
+
group :mcf
|
61
|
+
input :vmx, :argument => :required,
|
62
|
+
:desc => "Path to micro.vmx"
|
63
|
+
input :password, :argument => :optional,
|
64
|
+
:desc => "Cleartext password for guest VM vcap user"
|
65
|
+
def micro_online
|
66
|
+
runner
|
67
|
+
with_progress("Unsetting host DNS server") do
|
68
|
+
runner.unset_host_dns!
|
69
|
+
end
|
70
|
+
|
71
|
+
with_progress("Setting MCF VM to online mode") do
|
72
|
+
runner.online!
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def runner
|
77
|
+
return @runner if @runner
|
78
|
+
|
79
|
+
config = build_config
|
80
|
+
@runner = switcher(config)
|
81
|
+
check_vm_running
|
82
|
+
store_config(config)
|
83
|
+
|
84
|
+
@runner
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_vm_running
|
88
|
+
unless runner.running?
|
89
|
+
if ask("MCF VM is not running. Do you want to start it?", :default => true)
|
90
|
+
with_progress("Starting MCF VM") do
|
91
|
+
runner.start!
|
92
|
+
end
|
93
|
+
else
|
94
|
+
fail "MCF VM needs to be running."
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
unless runner.ready?
|
99
|
+
fail "MCF VM initial setup needs to be completed before using 'vmc micro'"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def switcher(config)
|
104
|
+
case McfCommand.platform
|
105
|
+
when :darwin
|
106
|
+
VMCMicro::Switcher::Darwin.new(config)
|
107
|
+
when :linux
|
108
|
+
VMCMicro::Switcher::Linux.new(config)
|
109
|
+
when :windows
|
110
|
+
VMCMicro::Switcher::Windows.new(config)
|
111
|
+
when :dummy # for testing only
|
112
|
+
VMCMicro::Switcher::Dummy.new(config)
|
113
|
+
else
|
114
|
+
fail "unsupported platform: #{McfCommand.platform}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the configuration needed to run the micro related subcommands.
|
119
|
+
# First loads saved config from file (if there is any), then overrides
|
120
|
+
# loaded values with command line arguments, and finally tries to guess
|
121
|
+
# in case neither was used:
|
122
|
+
# vmx location of micro.vmx file
|
123
|
+
# vmrun location of vmrun command
|
124
|
+
# password password for vcap user (in the guest vm)
|
125
|
+
# platform current platform
|
126
|
+
def build_config
|
127
|
+
conf = micro # returns {} if there isn't a saved config
|
128
|
+
|
129
|
+
override(conf, :vmx, true) do
|
130
|
+
locate_vmx(McfCommand.platform)
|
131
|
+
end
|
132
|
+
|
133
|
+
override(conf, :vmrun, true) do
|
134
|
+
VMCMicro::VMrun.locate(McfCommand.platform)
|
135
|
+
end
|
136
|
+
|
137
|
+
override(conf, :password) do
|
138
|
+
ask("Please enter your MCF VM password (vcap user) password", :echo => "*")
|
139
|
+
end
|
140
|
+
|
141
|
+
conf[:platform] = McfCommand.platform
|
142
|
+
|
143
|
+
conf
|
144
|
+
end
|
145
|
+
|
146
|
+
# Save the cleartext password if --save is supplied.
|
147
|
+
# Note: it is due to vix we have to use a cleartext password :(
|
148
|
+
# Only if --password is used and not --save is the password deleted from the
|
149
|
+
# config file before it is stored to disk.
|
150
|
+
def store_config(config)
|
151
|
+
if input[:save]
|
152
|
+
warn("cleartext password saved in: #{MICRO_FILE}")
|
153
|
+
end
|
154
|
+
|
155
|
+
store_micro(config)
|
156
|
+
end
|
157
|
+
|
158
|
+
# override with command line arguments and yield the block in case the option isn't set
|
159
|
+
def override(config, option, escape=false, &blk)
|
160
|
+
# override if given on the command line
|
161
|
+
if opt = input[option]
|
162
|
+
opt = VMCMicro.escape_path(opt) if escape
|
163
|
+
config[option] = opt
|
164
|
+
end
|
165
|
+
config[option] = yield unless config[option]
|
166
|
+
end
|
167
|
+
|
168
|
+
def locate_vmx(platform)
|
169
|
+
paths = YAML.load_file(VMCMicro.config_file('paths.yml'))
|
170
|
+
vmx_paths = paths[platform.to_s]['vmx']
|
171
|
+
vmx = VMCMicro.locate_file('micro.vmx', 'micro', vmx_paths)
|
172
|
+
fail "Unable to locate micro.vmx, please supply --vmx option" unless vmx
|
173
|
+
vmx
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.platform
|
177
|
+
case RUBY_PLATFORM
|
178
|
+
when /darwin/ # x86_64-darwin11.2.0
|
179
|
+
:darwin
|
180
|
+
when /linux/ # x86_64-linux
|
181
|
+
:linux
|
182
|
+
when /mingw|mswin32|cygwin/ # i386-mingw32
|
183
|
+
:windows
|
184
|
+
else
|
185
|
+
RUBY_PLATFORM
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def micro
|
190
|
+
micro_file = File.expand_path(MICRO_FILE)
|
191
|
+
return {} unless File.exists? micro_file
|
192
|
+
contents = File.read(micro_file).strip
|
193
|
+
MultiJson.load(contents)
|
194
|
+
end
|
195
|
+
|
196
|
+
def store_micro(micro)
|
197
|
+
micro_file = File.expand_path(MICRO_FILE)
|
198
|
+
File.open(micro_file, 'w') do |file|
|
199
|
+
file.write(MultiJson.dump(micro))
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
data/spec/plugin_spec.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mcf-vmc-plugin/plugin'
|
3
|
+
|
4
|
+
describe VMCMicro::McfCommand do
|
5
|
+
describe 'micro_status' do
|
6
|
+
shared_examples 'mcf common inputs' do
|
7
|
+
describe 'inputs' do
|
8
|
+
subject { command.inputs }
|
9
|
+
it { expect(subject[:vmx][:description]).to eq "Path to micro.vmx" }
|
10
|
+
it { expect(subject[:password][:description]).to eq "Cleartext password for guest VM vcap user" }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'arguments' do
|
14
|
+
subject { command.arguments }
|
15
|
+
|
16
|
+
it 'has the correct argument order' do
|
17
|
+
should eq([
|
18
|
+
{:type => :required, :value => nil, :name => :vmx},
|
19
|
+
{:type => :optional, :value => nil, :name => :password}
|
20
|
+
])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#metadata' do
|
26
|
+
let(:command) { Mothership.commands[:micro_status] }
|
27
|
+
|
28
|
+
include_examples 'mcf common inputs'
|
29
|
+
|
30
|
+
describe 'command' do
|
31
|
+
subject { command }
|
32
|
+
|
33
|
+
its(:description) { should eq "Display Micro Cloud Foundry VM status" }
|
34
|
+
it { expect(Mothership::Help.group(:mcf)).to include(subject) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#micro_offline' do
|
40
|
+
describe 'metadata' do
|
41
|
+
let(:command) { Mothership.commands[:micro_offline] }
|
42
|
+
|
43
|
+
include_examples 'mcf common inputs'
|
44
|
+
|
45
|
+
describe 'command' do
|
46
|
+
subject { command }
|
47
|
+
|
48
|
+
its(:description) { should eq "Micro Cloud Foundry offline mode" }
|
49
|
+
it { expect(Mothership::Help.group(:mcf)).to include(subject) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#micro_online' do
|
55
|
+
describe 'metadata' do
|
56
|
+
let(:command) { Mothership.commands[:micro_online] }
|
57
|
+
|
58
|
+
include_examples 'mcf common inputs'
|
59
|
+
|
60
|
+
describe 'command' do
|
61
|
+
subject { command }
|
62
|
+
|
63
|
+
its(:description) { should eq "Micro Cloud Foundry online mode" }
|
64
|
+
it { expect(Mothership::Help.group(:mcf)).to include(subject) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mcf-vmc-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Alex Suraci
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2013-02-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rake
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 25
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 9
|
32
|
+
version: "0.9"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 21
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 11
|
47
|
+
version: "2.11"
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: webmock
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 29
|
59
|
+
segments:
|
60
|
+
- 1
|
61
|
+
- 9
|
62
|
+
version: "1.9"
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: rr
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 15
|
74
|
+
segments:
|
75
|
+
- 1
|
76
|
+
- 0
|
77
|
+
version: "1.0"
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id004
|
80
|
+
description:
|
81
|
+
email:
|
82
|
+
- asuraci@vmware.com
|
83
|
+
executables: []
|
84
|
+
|
85
|
+
extensions: []
|
86
|
+
|
87
|
+
extra_rdoc_files: []
|
88
|
+
|
89
|
+
files:
|
90
|
+
- Rakefile
|
91
|
+
- lib/mcf-vmc-plugin/errors.rb
|
92
|
+
- lib/mcf-vmc-plugin/help.rb
|
93
|
+
- lib/mcf-vmc-plugin/micro/micro.rb
|
94
|
+
- lib/mcf-vmc-plugin/micro/switcher/base.rb
|
95
|
+
- lib/mcf-vmc-plugin/micro/switcher/darwin.rb
|
96
|
+
- lib/mcf-vmc-plugin/micro/switcher/dummy.rb
|
97
|
+
- lib/mcf-vmc-plugin/micro/switcher/linux.rb
|
98
|
+
- lib/mcf-vmc-plugin/micro/switcher/windows.rb
|
99
|
+
- lib/mcf-vmc-plugin/micro/vmrun.rb
|
100
|
+
- lib/mcf-vmc-plugin/plugin.rb
|
101
|
+
- lib/mcf-vmc-plugin/version.rb
|
102
|
+
- config/offline.conf
|
103
|
+
- config/paths.yml
|
104
|
+
- config/refresh_ip.rb
|
105
|
+
- spec/plugin_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
homepage: http://cloudfoundry.com/
|
108
|
+
licenses: []
|
109
|
+
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
hash: 3
|
130
|
+
segments:
|
131
|
+
- 0
|
132
|
+
version: "0"
|
133
|
+
requirements: []
|
134
|
+
|
135
|
+
rubyforge_project: mcf-vmc-plugin
|
136
|
+
rubygems_version: 1.8.24
|
137
|
+
signing_key:
|
138
|
+
specification_version: 3
|
139
|
+
summary: Provides a fake tunnel command that tells you to install the real plugin.
|
140
|
+
test_files:
|
141
|
+
- spec/plugin_spec.rb
|
142
|
+
- spec/spec_helper.rb
|