vmc 0.3.16.beta.3 → 0.3.16.beta.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -75,6 +75,15 @@ MIT license, please see the LICENSE file. All rights reserved._
75
75
  runtimes Display the supported runtimes of the target system
76
76
  frameworks Display the recognized frameworks of the target system
77
77
 
78
+ Micro Cloud Foundry
79
+ micro status Display Micro Cloud Foundry VM status
80
+ mciro offline Configure Micro Cloud Foundry VM for offline mode
81
+ micro online Configure Micro Cloud Foundry VM for online mode
82
+ [--vmx file] Path to micro.vmx
83
+ [--vmrun executable] Path to vmrun executable
84
+ [--password cleartext] Cleartext password for guest VM vcap user
85
+ [--save] Save cleartext password in ~/.vmc_micro
86
+
78
87
  Misc
79
88
  aliases List aliases
80
89
  alias <alias[=]command> Create an alias for a command
@@ -0,0 +1,2 @@
1
+ no-resolv
2
+ log-queries
@@ -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,20 @@
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 {|s| s.connect(route, 1); s.addr.last }
11
+ rescue Errno::ENETUNREACH
12
+ # happens on boot when dhcp hasn't completed when we get here
13
+ sleep 3
14
+ retries += 1
15
+ retry if retries < 10
16
+ ensure
17
+ Socket.do_not_reverse_lookup = orig
18
+ end
19
+
20
+ File.open("/tmp/ip.txt", 'w') { |file| file.write(ip_address) }
@@ -193,7 +193,7 @@ module VMC::Cli::Command
193
193
  instance = @options[:instance] || '0'
194
194
  content = client.app_files(appname, path, instance)
195
195
  display content
196
- rescue VMC::Client::TargetError
196
+ rescue VMC::Client::NotFound, VMC::Client::TargetError
197
197
  err 'No such file or directory'
198
198
  end
199
199
 
@@ -675,10 +675,6 @@ module VMC::Cli::Command
675
675
  end
676
676
  end
677
677
 
678
- def log_file_paths
679
- %w[logs/stderr.log logs/stdout.log logs/startup.log]
680
- end
681
-
682
678
  def grab_all_logs(appname)
683
679
  instances_info_envelope = client.app_instances(appname)
684
680
  return if instances_info_envelope.is_a?(Array)
@@ -689,15 +685,23 @@ module VMC::Cli::Command
689
685
  end
690
686
 
691
687
  def grab_logs(appname, instance)
692
- log_file_paths.each do |path|
688
+ files_under(appname, instance, "/logs").each do |path|
693
689
  begin
694
690
  content = client.app_files(appname, path, instance)
695
691
  display_logfile(path, content, instance)
696
- rescue VMC::Client::TargetError
692
+ rescue VMC::Client::NotFound, VMC::Client::TargetError
697
693
  end
698
694
  end
699
695
  end
700
696
 
697
+ def files_under(appname, instance, path)
698
+ client.app_files(appname, path, instance).split("\n").collect do |l|
699
+ "#{path}/#{l.split[0]}"
700
+ end
701
+ rescue VMC::Client::NotFound, VMC::Client::TargetError
702
+ []
703
+ end
704
+
701
705
  def grab_crash_logs(appname, instance, was_staged=false)
702
706
  # stage crash info
703
707
  crashes(appname, false) unless was_staged
@@ -706,16 +710,11 @@ module VMC::Cli::Command
706
710
  map = VMC::Cli::Config.instances
707
711
  instance = map[instance] if map[instance]
708
712
 
709
- %w{
710
- /logs/err.log /logs/staging.log /logs/migration.log
711
- /app/logs/stderr.log /app/logs/stdout.log /app/logs/startup.log
712
- /app/logs/migration.log
713
- }.each do |path|
714
- begin
715
- content = client.app_files(appname, path, instance)
716
- display_logfile(path, content, instance)
717
- rescue VMC::Client::TargetError
718
- end
713
+ (files_under(appname, instance, "/logs") +
714
+ files_under(appname, instance, "/app/logs") +
715
+ files_under(appname, instance, "/app/log")).each do |path|
716
+ content = client.app_files(appname, path, instance)
717
+ display_logfile(path, content, instance)
719
718
  end
720
719
  end
721
720
 
@@ -732,7 +731,7 @@ module VMC::Cli::Command
732
731
  display tail.join("\n") if new_lines > 0
733
732
  end
734
733
  since + new_lines
735
- rescue VMC::Client::TargetError
734
+ rescue VMC::Client::NotFound, VMC::Client::TargetError
736
735
  0
737
736
  end
738
737
 
@@ -1064,7 +1063,7 @@ module VMC::Cli::Command
1064
1063
  entry[:index],
1065
1064
  "====> [#{entry[:index]}: #{path}] <====\n".bold
1066
1065
  )
1067
- rescue VMC::Client::TargetError
1066
+ rescue VMC::Client::NotFound, VMC::Client::TargetError
1068
1067
  end
1069
1068
  end
1070
1069
  end
@@ -0,0 +1,115 @@
1
+ module VMC::Cli::Command
2
+ class Micro < Base
3
+
4
+ def initialize(args)
5
+ super(args)
6
+ end
7
+
8
+ def offline(mode)
9
+ command('offline')
10
+ end
11
+
12
+ def online(mode)
13
+ command('online')
14
+ end
15
+
16
+ def status(mode)
17
+ command('status')
18
+ end
19
+
20
+ def command(cmd)
21
+ config = build_config
22
+ switcher(config).send(cmd)
23
+ store_config(config)
24
+ end
25
+
26
+ def switcher(config)
27
+ case Micro.platform
28
+ when :darwin
29
+ switcher = VMC::Micro::Switcher::Darwin.new(config)
30
+ when :linux
31
+ switcher = VMC::Micro::Switcher::Linux.new(config)
32
+ when :windows
33
+ switcher = VMC::Micro::Switcher::Windows.new(config)
34
+ when :dummy # for testing only
35
+ switcher = VMC::Micro::Switcher::Dummy.new(config)
36
+ else
37
+ err "unsupported platform: #{Micro.platform}"
38
+ end
39
+ end
40
+
41
+ # Returns the configuration needed to run the micro related subcommands.
42
+ # First loads saved config from file (if there is any), then overrides
43
+ # loaded values with command line arguments, and finally tries to guess
44
+ # in case neither was used:
45
+ # vmx location of micro.vmx file
46
+ # vmrun location of vmrun command
47
+ # password password for vcap user (in the guest vm)
48
+ # platform current platform
49
+ def build_config
50
+ conf = VMC::Cli::Config.micro # returns {} if there isn't a saved config
51
+
52
+ override(conf, 'vmx', true) do
53
+ locate_vmx(Micro.platform)
54
+ end
55
+
56
+ override(conf, 'vmrun', true) do
57
+ VMC::Micro::VMrun.locate(Micro.platform)
58
+ end
59
+
60
+ override(conf, 'password') do
61
+ @password = ask("Please enter your Micro Cloud Foundry VM password (vcap user) password", :echo => "*")
62
+ end
63
+
64
+ conf['platform'] = Micro.platform
65
+
66
+ conf
67
+ end
68
+
69
+ # Save the cleartext password if --save is supplied.
70
+ # Note: it is due to vix we have to use a cleartext password :(
71
+ # Only if --password is used and not --save is the password deleted from the
72
+ # config file before it is stored to disk.
73
+ def store_config(config)
74
+ if @options[:save]
75
+ warn("cleartext password saved in: #{VMC::Cli::Config::MICRO_FILE}")
76
+ elsif @options[:password] || @password
77
+ config.delete('password')
78
+ end
79
+
80
+ VMC::Cli::Config.store_micro(config)
81
+ end
82
+
83
+ # override with command line arguments and yield the block in case the option isn't set
84
+ def override(config, option, escape=false, &blk)
85
+ # override if given on the command line
86
+ if opt = @options[option.to_sym]
87
+ opt = VMC::Micro.escape_path(opt) if escape
88
+ config[option] = opt
89
+ end
90
+ config[option] = yield unless config[option]
91
+ end
92
+
93
+ def locate_vmx(platform)
94
+ paths = YAML.load_file(VMC::Micro.config_file('paths.yml'))
95
+ vmx_paths = paths[platform.to_s]['vmx']
96
+ vmx = VMC::Micro.locate_file('micro.vmx', 'micro', vmx_paths)
97
+ err "Unable to locate micro.vmx, please supply --vmx option" unless vmx
98
+ vmx
99
+ end
100
+
101
+ def self.platform
102
+ case RUBY_PLATFORM
103
+ when /darwin/ # x86_64-darwin11.2.0
104
+ :darwin
105
+ when /linux/ # x86_64-linux
106
+ :linux
107
+ when /mingw|mswin32|cygwin/ # i386-mingw32
108
+ :windows
109
+ else
110
+ RUBY_PLATFORM
111
+ end
112
+ end
113
+
114
+ end
115
+ end
data/lib/cli/config.rb CHANGED
@@ -14,6 +14,7 @@ module VMC::Cli
14
14
  INSTANCES_FILE = '~/.vmc_instances'
15
15
  ALIASES_FILE = '~/.vmc_aliases'
16
16
  CLIENTS_FILE = '~/.vmc_clients'
17
+ MICRO_FILE = '~/.vmc_micro'
17
18
 
18
19
  STOCK_CLIENTS = File.expand_path("../../../config/clients.yml", __FILE__)
19
20
 
@@ -102,6 +103,18 @@ module VMC::Cli
102
103
  File.open(aliases_file, 'wb') {|f| f.write(aliases.to_yaml)}
103
104
  end
104
105
 
106
+ def micro
107
+ micro_file = File.expand_path(MICRO_FILE)
108
+ return {} unless File.exists? micro_file
109
+ contents = lock_and_read(micro_file).strip
110
+ JSON.parse(contents)
111
+ end
112
+
113
+ def store_micro(micro)
114
+ micro_file = File.expand_path(MICRO_FILE)
115
+ lock_and_write(micro_file, micro.to_json)
116
+ end
117
+
105
118
  def deep_merge(a, b)
106
119
  merge = proc do |_, old, new|
107
120
  if new.is_a?(Hash) and old.is_a?(Hash)
@@ -17,6 +17,7 @@ module VMC::Cli
17
17
  'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}],
18
18
  'WSGI' => ['wsgi', { :mem => '64M', :description => 'Python WSGI Application'}],
19
19
  'Django' => ['django', { :mem => '128M', :description => 'Python Django Application'}],
20
+ 'Rack' => ['rack', { :mem => '128M', :description => 'Rack Application'}]
20
21
  }
21
22
 
22
23
  class << self
@@ -35,13 +36,16 @@ module VMC::Cli
35
36
  end
36
37
  end
37
38
 
38
- def detect(path)
39
+ def detect(path, available_frameworks)
39
40
  Dir.chdir(path) do
40
-
41
41
  # Rails
42
42
  if File.exist?('config/environment.rb')
43
43
  return Framework.lookup('Rails')
44
44
 
45
+ # Rack
46
+ elsif File.exist?('config.ru') && available_frameworks.include?(["rack"])
47
+ return Framework.lookup('Rack')
48
+
45
49
  # Java
46
50
  elsif Dir.glob('*.war').first || File.exist?('WEB-INF/web.xml')
47
51
  war_file = Dir.glob('*.war').first
@@ -165,7 +165,7 @@ module VMC::Cli::ManifestHelper
165
165
 
166
166
  # Detect the appropriate framework.
167
167
  def detect_framework(prompt_ok = true)
168
- framework = VMC::Cli::Framework.detect(@application)
168
+ framework = VMC::Cli::Framework.detect(@application, frameworks_info)
169
169
  framework_correct = ask("Detected a #{framework}, is this correct?", :default => true) if prompt_ok && framework
170
170
  if prompt_ok && (framework.nil? || !framework_correct)
171
171
  display "#{"[WARNING]".yellow} Can't determine the Application Type." unless framework
data/lib/cli/runner.rb CHANGED
@@ -59,6 +59,11 @@ class VMC::Cli::Runner
59
59
 
60
60
  opts.on('-q', '--quiet') { @options[:quiet] = true }
61
61
 
62
+ # micro cloud options
63
+ opts.on('--vmx FILE') { |file| @options[:vmx] = file }
64
+ opts.on('--vmrun FILE') { |file| @options[:vmrun] = file }
65
+ opts.on('--save') { @options[:save] = true }
66
+
62
67
  # Don't use builtin zip
63
68
  opts.on('--no-zip') { @options[:nozip] = true }
64
69
  opts.on('--nozip') { @options[:nozip] = true }
@@ -380,6 +385,12 @@ class VMC::Cli::Runner
380
385
  usage('vmc rails-console <appname>')
381
386
  set_cmd(:apps, :console, 1)
382
387
 
388
+ when 'micro'
389
+ usage('vmc micro <online|offline|status> [--password password] [--save] [--vmx file] [--vmrun executable]')
390
+ if %w[online offline status].include?(@args[0])
391
+ set_cmd(:micro, @args[0].to_sym, 1)
392
+ end
393
+
383
394
  when 'help'
384
395
  display_help if @args.size == 0
385
396
  @help_only = true
data/lib/cli/usage.rb CHANGED
@@ -91,6 +91,15 @@ Currently available vmc commands are:
91
91
  runtimes Display the supported runtimes of the target system
92
92
  frameworks Display the recognized frameworks of the target system
93
93
 
94
+ Micro Cloud Foundry
95
+ micro status Display Micro Cloud Foundry VM status
96
+ micro offline Configure Micro Cloud Foundry VM for offline mode
97
+ micro online Configure Micro Cloud Foundry VM for online mode
98
+ [--vmx file] Path to micro.vmx
99
+ [--vmrun executable] Path to vmrun executable
100
+ [--password cleartext] Cleartext password for guest VM vcap user
101
+ [--save] Save cleartext password in ~/.vmc_micro
102
+
94
103
  Misc
95
104
  aliases List aliases
96
105
  alias <alias[=]command> Create an alias for a command
data/lib/cli/version.rb CHANGED
@@ -2,6 +2,6 @@ module VMC
2
2
  module Cli
3
3
  # This version number is used as the RubyGem release version.
4
4
  # The internal VMC version number is VMC::VERSION.
5
- VERSION = '0.3.16.beta.3'
5
+ VERSION = '0.3.16.beta.5'
6
6
  end
7
7
  end
data/lib/cli.rb CHANGED
@@ -4,6 +4,18 @@ WINDOWS = !!(RUBY_PLATFORM =~ /mingw|mswin32|cygwin/)
4
4
 
5
5
  module VMC
6
6
  autoload :Client, "#{ROOT}/vmc/client"
7
+ autoload :Micro, "#{ROOT}/vmc/micro"
8
+
9
+ module Micro
10
+ module Switcher
11
+ autoload :Base, "#{ROOT}/vmc/micro/switcher/base"
12
+ autoload :Darwin, "#{ROOT}/vmc/micro/switcher/darwin"
13
+ autoload :Dummy, "#{ROOT}/vmc/micro/switcher/dummy"
14
+ autoload :Linux, "#{ROOT}/vmc/micro/switcher/linux"
15
+ autoload :Windows, "#{ROOT}/vmc/micro/switcher/windows"
16
+ end
17
+ autoload :VMrun, "#{ROOT}/vmc/micro/vmrun"
18
+ end
7
19
 
8
20
  module Cli
9
21
  autoload :Config, "#{ROOT}/cli/config"
@@ -13,12 +25,13 @@ module VMC
13
25
  autoload :ServicesHelper, "#{ROOT}/cli/services_helper"
14
26
  autoload :TunnelHelper, "#{ROOT}/cli/tunnel_helper"
15
27
  autoload :ManifestHelper, "#{ROOT}/cli/manifest_helper"
16
- autoload :ConsoleHelper, "#{ROOT}/cli/console_helper"
28
+ autoload :ConsoleHelper, "#{ROOT}/cli/console_helper"
17
29
 
18
30
  module Command
19
31
  autoload :Base, "#{ROOT}/cli/commands/base"
20
32
  autoload :Admin, "#{ROOT}/cli/commands/admin"
21
33
  autoload :Apps, "#{ROOT}/cli/commands/apps"
34
+ autoload :Micro, "#{ROOT}/cli/commands/micro"
22
35
  autoload :Misc, "#{ROOT}/cli/commands/misc"
23
36
  autoload :Services, "#{ROOT}/cli/commands/services"
24
37
  autoload :User, "#{ROOT}/cli/commands/user"
@@ -0,0 +1,97 @@
1
+ require 'interact'
2
+
3
+ module VMC::Micro::Switcher
4
+ class Base
5
+ include Interactive
6
+
7
+ def initialize(config)
8
+ @config = config
9
+
10
+ @vmrun = VMC::Micro::VMrun.new(config)
11
+ unless @vmrun.running?
12
+ if ask("Micro Cloud Foundry VM is not running. Do you want to start it?", :choices => ['y', 'n']) == 'y'
13
+ display "Starting Micro Cloud Foundry VM: ", false
14
+ @vmrun.start
15
+ say "done".green
16
+ else
17
+ err "Micro Cloud Foundry VM needs to be running."
18
+ end
19
+ end
20
+
21
+ err "Micro Cloud Foundry VM initial setup needs to be completed before using 'vmc micro'" unless @vmrun.ready?
22
+ end
23
+
24
+ def offline
25
+ unless @vmrun.offline?
26
+ # save online connection type so we can restore it later
27
+ @config['online_connection_type'] = @vmrun.connection_type
28
+
29
+ if (@config['online_connection_type'] != 'nat')
30
+ if ask("Reconfigure Micro Cloud Foundry VM network to nat mode and reboot?", :choices => ['y', 'n']) == 'y'
31
+ display "Rebooting Micro Cloud Foundry VM: ", false
32
+ @vmrun.connection_type = 'nat'
33
+ @vmrun.reset
34
+ say "done".green
35
+ else
36
+ err "Aborted"
37
+ end
38
+ end
39
+
40
+ display "Setting Micro Cloud Foundry VM to offline mode: ", false
41
+ @vmrun.offline!
42
+ say "done".green
43
+ display "Setting host DNS server: ", false
44
+
45
+ @config['domain'] = @vmrun.domain
46
+ @config['ip'] = @vmrun.ip
47
+ set_nameserver(@config['domain'], @config['ip'])
48
+ say "done".green
49
+ else
50
+ say "Micro Cloud Foundry VM already in offline mode".yellow
51
+ end
52
+ end
53
+
54
+ def online
55
+ if @vmrun.offline?
56
+ current_connection_type = @vmrun.connection_type
57
+ @config['online_connection_type'] ||= current_connection_type
58
+
59
+ if (@config['online_connection_type'] != current_connection_type)
60
+ # TODO handle missing connection type in saved config
61
+ question = "Reconfigure Micro Cloud Foundry VM network to #{@config['online_connection_type']} mode and reboot?"
62
+ if ask(question, :choices => ['y', 'n']) == 'y'
63
+ display "Rebooting Micro Cloud Foundry VM: ", false
64
+ @vmrun.connection_type = @config['online_connection_type']
65
+ @vmrun.reset
66
+ say "done".green
67
+ else
68
+ err "Aborted"
69
+ end
70
+ end
71
+
72
+ display "Unsetting host DNS server: ", false
73
+ # TODO handle missing domain and ip in saved config (look at the VM)
74
+ @config['domain'] ||= @vmrun.domain
75
+ @config['ip'] ||= @vmrun.ip
76
+ unset_nameserver(@config['domain'], @config['ip'])
77
+ say "done".green
78
+
79
+ display "Setting Micro Cloud Foundry VM to online mode: ", false
80
+ @vmrun.online!
81
+ say "done".green
82
+ else
83
+ say "Micro Cloud Foundry already in online mode".yellow
84
+ end
85
+ end
86
+
87
+ def status
88
+ mode = @vmrun.offline? ? 'offline' : 'online'
89
+ say "Micro Cloud Foundry VM currently in #{mode.green} mode"
90
+ # should the VMX path be unescaped?
91
+ say "VMX Path: #{@vmrun.vmx}"
92
+ say "Domain: #{@vmrun.domain.green}"
93
+ say "IP Address: #{@vmrun.ip.green}"
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,19 @@
1
+ module VMC::Micro::Switcher
2
+
3
+ class Darwin < Base
4
+ def adminrun(command)
5
+ VMC::Micro.run_command("osascript", "-e 'do shell script \"#{command}\" with administrator privileges'")
6
+ end
7
+
8
+ def set_nameserver(domain, ip)
9
+ File.open("/tmp/#{domain}", 'w') { |file| file.write("nameserver #{ip}") }
10
+ adminrun("mkdir -p /etc/resolver;mv /tmp/#{domain} /etc/resolver/")
11
+ end
12
+
13
+ def unset_nameserver(domain, ip)
14
+ err "domain missing" unless domain
15
+ adminrun("rm -f /etc/resolver/#{domain}")
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,15 @@
1
+ # only used for testing
2
+ module VMC::Micro::Switcher
3
+
4
+ class Dummy < Base
5
+ def adminrun(command)
6
+ end
7
+
8
+ def set_nameserver(domain, ip)
9
+ end
10
+
11
+ def unset_nameserver(domain, ip)
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,16 @@
1
+ module VMC::Micro::Switcher
2
+
3
+ class Linux < Base
4
+ def set_nameserver(domain, ip)
5
+ VMC::Micro.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
+ VMC::Micro.run_command("sudo", "chattr +i /etc/resolv.conf")
8
+ end
9
+
10
+ def unset_nameserver(domain, ip)
11
+ VMC::Micro.run_command("sudo", "chattr -i /etc/resolv.conf")
12
+ VMC::Micro.run_command("sudo", "sed -i'.backup' '/#{ip}/d' /etc/resolv.conf")
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,31 @@
1
+ module VMC::Micro::Switcher
2
+
3
+ class Windows < Base
4
+ def version?
5
+ VMC::Micro.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
+ VMC::Micro.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,158 @@
1
+ module VMC::Micro
2
+ class VMrun
3
+ attr_reader :vmx, :vmrun
4
+
5
+ def initialize(config)
6
+ @platform = config['platform']
7
+ @user = 'root' # must use root as we muck around with system settings
8
+ @password = config['password']
9
+ @vmrun = config['vmrun']
10
+ @vmx = config['vmx']
11
+
12
+ # TODO honor TMPDIR
13
+ if @platform == :windows
14
+ @temp_dir = ENV['temp']
15
+ else
16
+ @temp_dir = '/tmp'
17
+ end
18
+ end
19
+
20
+ def connection_type
21
+ read_variable('ethernet0.connectionType')
22
+ end
23
+
24
+ def connection_type=(type)
25
+ write_variable("ethernet0.connectionType", type)
26
+ end
27
+
28
+ def nat?
29
+ connection_type == "nat"
30
+ end
31
+
32
+ def bridged?
33
+ connection_type == "bridged"
34
+ end
35
+
36
+ def domain
37
+ # switch to Dir.mktmpdir
38
+ state_config = VMC::Micro.escape_path(File.join(@temp_dir, 'state.yml'))
39
+ run('CopyFileFromGuestToHost', "/var/vcap/bosh/state.yml #{state_config}")
40
+ bosh_config = YAML.load_file(state_config)
41
+ bosh_config['properties']['domain']
42
+ end
43
+
44
+ def ip
45
+ # switch to Dir.mktmpdir
46
+ path = VMC::Micro.escape_path(VMC::Micro.config_file('refresh_ip.rb'))
47
+ ip_file = VMC::Micro.escape_path(File.join(@temp_dir, 'ip.txt'))
48
+ run('CopyFileFromHostToGuest', "#{path} /tmp/refresh_ip.rb")
49
+ run('runProgramInGuest', '/tmp/refresh_ip.rb')
50
+ run('CopyFileFromGuestToHost', "/tmp/ip.txt #{ip_file}")
51
+ File.open(ip_file, 'r') { |file| file.read }
52
+ end
53
+
54
+ def list
55
+ vms = run("list")
56
+ vms.delete_if { |line| line =~ /^Total/ }
57
+ vms.map { |line| VMC::Micro.escape_path(File.expand_path(line)) }
58
+ end
59
+
60
+ def offline?
61
+ command = "-gu #{@user} -gp #{@password} runProgramInGuest"
62
+ args = '/usr/bin/test -e /var/vcap/micro/offline'
63
+ # why not use run_command?
64
+ result = %x{#{@vmrun} #{command} #{@vmx} #{args}}
65
+
66
+ if result.include?('Guest program exited with non-zero exit code: 1')
67
+ return false
68
+ elsif $?.exitstatus == 0
69
+ return true
70
+ else
71
+ raise "failed to execute vmrun:\n#{result}"
72
+ end
73
+ end
74
+
75
+ def offline!
76
+ path = VMC::Micro.escape_path(VMC::Micro.config_file('offline.conf'))
77
+ run('CopyFileFromHostToGuest', "#{path} /etc/dnsmasq.d/offline.conf")
78
+ run('runProgramInGuest', '/usr/bin/touch /var/vcap/micro/offline')
79
+ restart_dnsmasq
80
+ end
81
+
82
+ def online!
83
+ run('runProgramInGuest', '/bin/rm -f /etc/dnsmasq.d/offline.conf')
84
+ run('runProgramInGuest', '/bin/rm -f /var/vcap/micro/offline')
85
+ restart_dnsmasq
86
+ end
87
+
88
+ # check to see if the micro cloud has been configured
89
+ # uses default password to check
90
+ def ready?
91
+ command = "-gu root -gp 'ca$hc0w' runProgramInGuest"
92
+ args = '/usr/bin/test -e /var/vcap/micro/micro.json'
93
+ result = %x{#{@vmrun} #{command} #{@vmx} #{args}}
94
+
95
+ if result.include?('Invalid user name or password for the guest OS') || $?.exitstatus == 0
96
+ return true
97
+ elsif $?.exitstatus == 1
98
+ return false
99
+ else
100
+ raise "failed to execute vmrun:\n#{result}"
101
+ end
102
+ end
103
+
104
+ def read_variable(var)
105
+ # TODO deal with non-ok return
106
+ run("readVariable", "runtimeConfig #{var}").first
107
+ end
108
+
109
+ def write_variable(var, value)
110
+ run('writeVariable', "runtimeConfig #{var} #{value}")
111
+ end
112
+
113
+ def reset
114
+ run('reset', 'soft')
115
+ end
116
+
117
+ def restart_dnsmasq
118
+ # restart command doesn't always work, start and stop seems to be more reliable
119
+ run('runProgramInGuest', '/etc/init.d/dnsmasq stop')
120
+ run('runProgramInGuest', '/etc/init.d/dnsmasq start')
121
+ end
122
+
123
+ def run(command, args=nil)
124
+ if command.include?('Guest')
125
+ command = "-gu #{@user} -gp #{@password} #{command}"
126
+ end
127
+ VMC::Micro.run_command(@vmrun, "#{command} #{@vmx} #{args}")
128
+ end
129
+
130
+ def running?
131
+ vms = list
132
+ if @platform == :windows
133
+ vms.map! { |x| x.downcase }
134
+ vms.include?(@vmx.downcase)
135
+ else
136
+ vms.include?(@vmx)
137
+ end
138
+ end
139
+
140
+ def start
141
+ run('start') unless running?
142
+ end
143
+
144
+ def stop
145
+ run('stop') if running?
146
+ end
147
+
148
+ def self.locate(platform)
149
+ paths = YAML.load_file(VMC::Micro.config_file('paths.yml'))
150
+ vmrun_paths = paths[platform.to_s]['vmrun']
151
+ vmrun_exe = @platform == :windows ? 'vmrun.exe' : 'vmrun'
152
+ vmrun = VMC::Micro.locate_file(vmrun_exe, "VMware", vmrun_paths)
153
+ err "Unable to locate vmrun, please supply --vmrun option" unless vmrun
154
+ vmrun
155
+ end
156
+ end
157
+
158
+ end
data/lib/vmc/micro.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'find'
2
+
3
+ module VMC::Micro
4
+ def config_file(file)
5
+ File.join(File.dirname(__FILE__), '..', '..', 'config', 'micro', file)
6
+ end
7
+
8
+ def escape_path(path)
9
+ path = File.expand_path(path)
10
+ if RUBY_PLATFORM =~ /mingw|mswin32|cygwin/
11
+ if path.include?(' ')
12
+ return '"' + path + '"'
13
+ else
14
+ return path
15
+ end
16
+ else
17
+ return path.gsub(' ', '\ ')
18
+ end
19
+ end
20
+
21
+ def locate_file(file, directory, search_paths)
22
+ search_paths.each do |path|
23
+ expanded_path = File.expand_path(path)
24
+ if File.exists?(expanded_path)
25
+ Find.find(expanded_path) do |current|
26
+ if File.directory?(current) && current.include?(directory)
27
+ full_path = File.join(current, file)
28
+ return self.escape_path(full_path) if File.exists?(full_path)
29
+ end
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
+ unless $?.exitstatus == 0
41
+ if block_given?
42
+ yield
43
+ else
44
+ raise "failed to execute #{command} #{args}:\n#{result}"
45
+ end
46
+ else
47
+ result.split(/\n/)
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
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: vmc
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 7
5
- version: 0.3.16.beta.3
5
+ version: 0.3.16.beta.5
6
6
  platform: ruby
7
7
  authors:
8
8
  - VMware
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-02-07 00:00:00 -08:00
13
+ date: 2012-03-02 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -143,10 +143,14 @@ files:
143
143
  - README.md
144
144
  - Rakefile
145
145
  - config/clients.yml
146
+ - config/micro/offline.conf
147
+ - config/micro/paths.yml
148
+ - config/micro/refresh_ip.rb
146
149
  - lib/cli/commands/admin.rb
147
150
  - lib/cli/commands/apps.rb
148
151
  - lib/cli/commands/base.rb
149
152
  - lib/cli/commands/manifest.rb
153
+ - lib/cli/commands/micro.rb
150
154
  - lib/cli/commands/misc.rb
151
155
  - lib/cli/commands/services.rb
152
156
  - lib/cli/commands/user.rb
@@ -165,6 +169,13 @@ files:
165
169
  - lib/cli.rb
166
170
  - lib/vmc/client.rb
167
171
  - lib/vmc/const.rb
172
+ - lib/vmc/micro/switcher/base.rb
173
+ - lib/vmc/micro/switcher/darwin.rb
174
+ - lib/vmc/micro/switcher/dummy.rb
175
+ - lib/vmc/micro/switcher/linux.rb
176
+ - lib/vmc/micro/switcher/windows.rb
177
+ - lib/vmc/micro/vmrun.rb
178
+ - lib/vmc/micro.rb
168
179
  - lib/vmc.rb
169
180
  - caldecott_helper/Gemfile
170
181
  - caldecott_helper/Gemfile.lock