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

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/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