Module: Veewee::Provider::Core::BoxCommand

Included in:
Box, Kvm::Box, Parallels::Box, Vmfusion::Box
Defined in:
lib/veewee/provider/core/box/scp.rb,
lib/veewee/provider/core/box/ssh.rb,
lib/veewee/provider/core/box/vnc.rb,
lib/veewee/provider/core/box/copy.rb,
lib/veewee/provider/core/box/exec.rb,
lib/veewee/provider/core/box/halt.rb,
lib/veewee/provider/core/box/issh.rb,
lib/veewee/provider/core/box/sudo.rb,
lib/veewee/provider/core/box/build.rb,
lib/veewee/provider/core/box/wincp.rb,
lib/veewee/provider/core/box/winrm.rb,
lib/veewee/provider/core/box/floppy.rb,
lib/veewee/provider/core/box/poweroff.rb,
lib/veewee/provider/core/box/validate_tags.rb

Defined Under Namespace

Classes: Platform

Instance Method Summary collapse

Instance Method Details

#build(options = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/veewee/provider/core/box/build.rb', line 6

def build(options={})

  if definition.nil?
    raise Veewee::Error,"Could not find the definition. Make sure you are one level above the definitions directory when you execute the build command."
  end

  # Requires valid definition

  ui.info "Building Box #{name} with Definition #{definition.name}:"
  options.each do |name,value|
    ui.info "- #{name} : #{value}"
  end

  # Checking regexp of postinstall include/excludes
  validate_postinstall_regex(options)

  # Check the iso file we need to build the box
  definition.verify_iso(options)

  if self.exists?
    # check if --force option was given
    if options['force']==true
      self.destroy
      self.reload
    else
      ui.error("you need to provide --force because the box #{name} already exists",:prefix => false)
      raise Veewee::Error,"you need to provide --force because the box #{name} already exists"
    end
  end

  # By now the box should have been gone, just checking again
  if self.exists?
    ui.error("The box should have been deleted by now. Something went terribly wrong. Sorry",:prefix => false)
    raise Veewee::Error, "The box should have been deleted by now. Something went terribly wrong. Sorry"
  end

  self.create(options)

  # Check the GUI mode required
  env.logger.info "Provider asks the box to start: GUI enabled? #{!options['nogui']}"
  self.up(options)

  # Waiting for it to boot
  ui.info "Waiting #{definition.boot_wait.to_i} seconds for the machine to boot"
  sleep definition.boot_wait.to_i

  # Calculate an available kickstart port
  unless definition.kickstart_port.nil?
    guessed_port=guess_free_port(definition.kickstart_port.to_i,7199).to_s
    if guessed_port.to_s!=definition.kickstart_port
      ui.warn "Changing kickstart port from #{definition.kickstart_port} to #{guessed_port}"
      definition.kickstart_port=guessed_port.to_s
    end
  end

  # Let fill's in the variable we need
  boot_sequence=fill_sequence(definition.boot_cmd_sequence,{
    :ip =>host_ip_as_seen_by_guest,
    :port => definition.kickstart_port.to_s,
    :name => name
  })

  # Type the boot sequence
  Thread.new { self.console_type(boot_sequence) }

  self.handle_kickstart(options)

  # Wait for an ipaddress
  # This needs to be done after the kickstart:
  # As the dhcp request will likely occur just before the kickstart fetch
  until !self.ip_address.nil?
    env.logger.info "wait for Ip address"
    sleep 2
  end


  if ! definition.skip_iso_transfer then
    self.transfer_buildinfo(options)
  end

  # Filtering post install files based upon --postinstall-include and --postinstall--exclude
  definition.postinstall_files=filter_postinstall_files(options)

  self.handle_postinstall(options)

  ui.success "The box #{name} was built successfully!"
  ui.info "You can now login to the box with:"
  if (definition.winrm_user && definition.winrm_password)
    env.ui.info winrm_command_string
  else
    env.ui.info ssh_command_string
  end

  return self
end

#build_infoObject



167
168
169
# File 'lib/veewee/provider/core/box/build.rb', line 167

def build_info
  [ {:filename => ".veewee_version",:content => "#{Veewee::VERSION}"}]
end

#copy_to_box(localfile, remotefile, options = {}) ⇒ Object

Raises:



6
7
8
9
10
11
12
13
# File 'lib/veewee/provider/core/box/copy.rb', line 6

def copy_to_box(localfile,remotefile,options={})
  raise Veewee::Error,"Box is not running" unless self.running?
  if definition.winrm_user && definition.winrm_password # prefer winrm 
    self.wincp(localfile,remotefile,options)
  else
    self.scp(localfile,remotefile,options)
  end
end

#create_floppy(floppy_filename) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/veewee/provider/core/box/floppy.rb', line 5

def create_floppy(floppy_filename)
  # Todo Check for java
  # Todo check output of commands
  # Todo allow for .erb templates

  # Check for floppy
  unless definition.floppy_files.nil?
    require 'tmpdir'
    temp_dir=Dir.mktmpdir
    definition.floppy_files.each do |filename|
      full_filename=full_filename=File.join(definition.path,filename)
      FileUtils.cp("#{full_filename}","#{temp_dir}")
    end
    javacode_dir=File.expand_path(File.join(__FILE__,'..','..','..','..','..','java'))
    floppy_file=File.join(definition.path,floppy_filename)
    if File.exists?(floppy_file)
      env.logger.info "Removing previous floppy file"
      FileUtils.rm(floppy_file)
    end
    command="java -jar #{javacode_dir}/dir2floppy.jar \"#{temp_dir}\" \"#{floppy_file}\""
    shell_exec("#{command}")
  end
end

#create_wget_vbs_command {|bootstrap_bat.join(" && "), chunk_num += 1| ... } ⇒ Object

Yields:

  • (bootstrap_bat.join(" && "), chunk_num += 1)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/veewee/provider/core/box/wincp.rb', line 50

def create_wget_vbs_command(&block)
  bootstrap_bat = []
  chunk_num = 0
  wget_vbs.each_line do |line|
    # escape WIN BATCH special chars
    line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
    # windows commands are limited to 2047 characters
    if((bootstrap_bat + [line]).join(" && ").size > 2047 )
      yield bootstrap_bat.join(" && "), chunk_num += 1
      bootstrap_bat = []
    end
    bootstrap_bat << ">> #{wget_vbs_file} (echo.#{line.chomp.strip})"
  end
  yield bootstrap_bat.join(" && "), chunk_num += 1
  bootstrap_bat = []
end

#escape_and_echo(file_contents) ⇒ Object

escape WIN BATCH special chars and prefixes each line with an echo



113
114
115
# File 'lib/veewee/provider/core/box/wincp.rb', line 113

def escape_and_echo(file_contents)
  file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
end

#exec(command, options = {}) ⇒ Object

Raises:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/veewee/provider/core/box/exec.rb', line 16

def exec(command,options={})
  raise Veewee::Error,"Box is not running" unless self.running?
  if definition.winrm_user && definition.winrm_password
    begin
      new_options=winrm_options.merge(options)
      self.(self.ip_address,winrm_options.merge(options)) do
        result = self.winrm_execute(self.ip_address,command,new_options)
        return result
      end
    rescue RuntimeError => ex
      env.ui.error "Error executing command #{command} : #{ex}"
      raise Veewee::WinrmError, ex
    end
  else # definition.ssh_user && definition.ssh_password
    begin
      new_options=ssh_options.merge(options)
      self.(self.ip_address,new_options) do
        begin
          env.logger.info "About to execute remote command #{command} on box #{name} - #{self.ip_address} - #{new_options}"
          result=self.ssh_execute(self.ip_address,command,new_options)
          return result
        rescue RuntimeError => ex
          env.ui.error "Error executing command #{command} : #{ex}"
          raise Veewee::SshError, ex
        end
      end
    rescue Net::SSH::AuthenticationFailed => ex # may want to catch winrm auth fails as well
      env.ui.error "Authentication failure"
      raise Veewee::SshError, "Authentication failure\n"+ex
    end
  end


end

#fill_sequence(sequence, options) ⇒ Object

This will take a sequence and fill in the variables specified in the options f.i. options==> “name” will substitute “%IP%” -> “name”



157
158
159
160
161
162
163
164
165
# File 'lib/veewee/provider/core/box/build.rb', line 157

def fill_sequence(sequence,options)
  filled=sequence.dup
  options.each do |key,value|
    filled.each do |s|
      s.gsub!("%#{key.to_s.upcase}%",value)
    end
  end
  return filled
end

#filter_postinstall_files(options) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/veewee/provider/core/box/build.rb', line 126

def filter_postinstall_files(options)
  new_definition=definition.clone

  env.logger.info "Applying the postinstall excludes"
  unless options["postinstall_exclude"].nil?
    options["postinstall_exclude"].each do |p|
      env.logger.info "Exclude pattern #{p}"
      new_definition.postinstall_files.reject! { |f| f.match(p) }
    end
  end

  env.logger.info "Applying the postinstall includes"
  unless options["postinstall_include"].nil?
    options["postinstall_include"].each do |p|
      env.logger.info "Include pattern #{p}"
      new_definition.postinstall_files.collect! { |f| f.match(p) ? f.gsub(/^_/,""): f}
    end
  end

  env.logger.info "filtered postinstall files:"
  new_definition.postinstall_files.each do |p|
    env.logger.info "- "+p
  end

  return new_definition.postinstall_files
end

#halt(options = {}) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/veewee/provider/core/box/halt.rb', line 7

def halt(options={})
  if self.running?
    if options["force"]==true
      self.poweroff
    else
      if definition.winrm_user && definition.winrm_password # prefer winrm 
        self.exec("#{definition.shutdown_cmd}")
      else
        self.exec("echo '#{definition.shutdown_cmd}' > /tmp/shutdown.sh")
        self.exec("chmod +x /tmp/shutdown.sh")
        self.exec(sudo("/tmp/shutdown.sh"))
      end
    end
  else
    raise Veewee::Error,"Box is not running"
  end
end

#handle_kickstart(options) ⇒ Object

This function handles all the post-install scripts It requires a definition to find all the necessary information



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/veewee/provider/core/box/build.rb', line 173

def handle_kickstart(options)

  # Handling the kickstart by web
  kickstartfiles=definition.kickstart_file

  if kickstartfiles.nil? || kickstartfiles.length == 0
    env.ui.info "Skipping webserver as no kickstartfile was specified"
  else
    env.ui.info "Starting a webserver #{definition.kickstart_ip}:#{definition.kickstart_port}\n"
  end

  # Check if the kickstart is an array or a single string
  if kickstartfiles.is_a?(String)
    # Let's turn it into an array
    kickstartfiles=kickstartfiles.split
  end

  # For each kickstart file spinup a webserver and wait for the file to be fetched
  unless kickstartfiles.nil?
    kickstartfiles.each do |kickfile|
      wait_for_http_request(kickfile,{
        :port => definition.kickstart_port,
        :host => definition.kickstart_ip,
        :timeout => definition.kickstart_timeout,
        :web_dir => definition.path
      })
    end
  end
end

#handle_postinstall(options) ⇒ Object

This function handles all the post-install scripts It requires a box(to login to) and a definition(listing the postinstall files)



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/veewee/provider/core/box/build.rb', line 205

def handle_postinstall(options)

  # Transfer all postinstall files
  definition.postinstall_files.each do |postinstall_file|
    # Filenames of postinstall_files are relative to their definition
    filename=File.join(definition.path,postinstall_file)
    self.copy_to_box(filename,File.basename(filename))
    if not (definition.winrm_user && definition.winrm_password)
      self.exec("chmod +x \"#{File.basename(filename)}\"")
    end
  end

  # Prepare a pre_poinstall file if needed (not nil , or not empty)
  unless definition.pre_postinstall_file.to_s.empty?
    pre_filename=File.join(definition.path, definition.pre_postinstall_file)
    self.copy_to_box(filename,File.basename(pre_filename))
    if (definition.winrm_user && definition.winrm_password)
      # not implemented on windows yet
    else
      self.exec("chmod +x \"#{File.basename(pre_filename)}\"")
      # Inject the call to the real script by executing the first argument (it will be the postinstall script file name to be executed)
      self.exec("execute=\"\\n# We must execute the script passed as the first argument\\n\\$1\" && printf \"%b\\n\" \"$execute\" >> #{File.basename(pre_filename)}")
    end
  end

  # Now iterate over the postinstall files
  definition.postinstall_files.each do |postinstall_file|
    # Filenames of postinstall_files are relative to their definition
    filename=File.join(definition.path,postinstall_file)

    unless File.basename(postinstall_file).start_with?("_")

      unless definition.pre_postinstall_file.to_s.empty?
        raise 'not implemented on windows yet' if (definition.winrm_user && definition.winrm_password)
        # Filename of pre_postinstall_file are relative to their definition
        pre_filename=File.join(definition.path, definition.pre_postinstall_file)
        # Upload the pre postinstall script if not already transfered
        command = "./" + File.basename(pre_filename)
        command = sudo(command) + " ./"+File.basename(filename)
      else
        if (definition.winrm_user && definition.winrm_password)
          # no sudo on windows, batch files only please?
          self.exec(File.basename(filename))
        else
          self.exec(sudo("./"+File.basename(filename)))
        end
      end

      self.exec(command)

    else
      env.logger.info "Skipping postinstallfile #{postinstall_file}"
    end
  end
end

#issh(command = nil, options = {}) ⇒ Object



7
8
9
# File 'lib/veewee/provider/core/box/issh.rb', line 7

def issh(command=nil,options={})
  self.ssh(command,options.merge({:interactive => true}))
end

#poweroff(options = {}) ⇒ Object



6
7
# File 'lib/veewee/provider/core/box/poweroff.rb', line 6

def poweroff(options={})
end

#scp(localfile, remotefile, options = {}) ⇒ Object

Raises:



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/veewee/provider/core/box/scp.rb', line 7

def scp(localfile,remotefile,options={})
  raise Veewee::Error,"Box is not running" unless self.running?
  begin
    new_options=ssh_options.merge(options)
    self.(self.ip_address,new_options) do
      begin
        env.logger.info "About to transfer #{localfile} to #{remotefile} to the box #{name} - #{self.ip_address} - #{new_options.inspect}"
        self.ssh_transfer_file(self.ip_address,localfile,remotefile,new_options)
      rescue RuntimeError => ex
        ui.error("Error transfering file #{localfile} failed, possible not enough permissions to write? #{ex}",:prefix => false)
        raise Veewee::SshError,ex
      end
    end
  rescue Net::SSH::AuthenticationFailed => ex
    ui.error("Authentication failure",:prefix => false)
    raise Veewee::SshError,ex
  end

end

#send_vnc_keycode(vnc, keycode) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/veewee/provider/core/box/vnc.rb', line 37

def send_vnc_keycode(vnc,keycode)

  if keycode.is_a?(Symbol)
    vnc.key_press keycode
    sleep 1
  else
      vnc.type_string keycode,{:wait => 0.1}
  end

end

#ssh(command = nil, options = {}) ⇒ Object

Raises:



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/veewee/provider/core/box/ssh.rb', line 8

def ssh(command=nil,options={})

  raise Veewee::Error,"Box is not running" unless self.running?

  if (options[:interactive]==true)
    # Command line options
    extended_command="#{command}"
    host_ip=self.ip_address

    unless host_ip.nil? || host_ip==""
      ssh_command="ssh #{ssh_commandline_options(options)} #{host_ip} \"#{extended_command}\""

      fg_exec(ssh_command,options)

    else
      ui.error("Can't ssh into '#{@name} as we couldn't figure out it's ip-address",:prefix => false)
    end
  else
    ssh_options={:user => definition.ssh_user,:password => definition.ssh_password, :port => definition.ssh_host_port}
    ssh_execute(host_ip,command,ssh_options)
  end

end

#ssh_command_stringObject



7
8
9
# File 'lib/veewee/provider/core/box/exec.rb', line 7

def ssh_command_string
 "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p #{ssh_options[:port]} -l #{definition.ssh_user} #{self.ip_address}"
end

#string_to_vnccode(thestring) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/veewee/provider/core/box/vnc.rb', line 49

def string_to_vnccode(thestring)

  # http://code.google.com/p/ruby-vnc/source/browse/trunk/data/keys.yaml

  special=Hash.new
  # Specific veewee
  special['<Wait>'] = :wait

  # VNC Codes
  special['<Enter>'] = :return
  special['<Return>'] =  :return
  special['<Esc>'] = :escape

  # These still need some work!
  special['<Backspace>'] = :backspace
  special['<Spacebar>'] = ' '
  special['<Tab>'] = :tab
  # Hmm, what would the equivalent be here
  special['<KillX>'] = '1d 38 0e';

  special['<Up>'] = :up
  special['<Down>'] = :down
  special['<PageUp>'] = :page_up
  special['<PageDown>'] = :page_down
  special['<End>'] = :end
  special['<Insert>'] = :insert
  special['<Delete>'] = :delete
  special['<Left>'] = :left
  special['<Right>'] = :right
  special['<Home>'] = :home

  special['<F1>'] = :f1
  special['<F2>'] = :f2
  special['<F3>'] = :f3
  special['<F4>'] = :f4
  special['<F5>'] = :f5
  special['<F6>'] = :f6
  special['<F7>'] = :f7
  special['<F8>'] = :f8
  special['<F9>'] = :f9
  special['<F10>'] = :f10

  keycodes=Array.new
  thestring.gsub!(/ /,"<Spacebar>")

  until thestring.length == 0
    nospecial=true;
    special.keys.each { |key|
      if thestring.start_with?(key)
        #take thestring
        #check if it starts with a special key + pop special string
        keycodes<<special[key];
        thestring=thestring.slice(key.length,thestring.length-key.length)
        nospecial=false;
        break;
      end
    }
    if nospecial
      code = thestring.slice(0,1)
      keycodes << code
      #pop one
      thestring=thestring.slice(1,thestring.length-1)
    end
  end

  return keycodes
end

#sudo(scriptname) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/veewee/provider/core/box/sudo.rb', line 6

def sudo(scriptname)
  if definition.ssh_user=="root"
    return "#{scriptname}"
  else
    command=definition.sudo_cmd
    newcommand=command.gsub(/%p/,"#{definition.ssh_password}")
    newcommand.gsub!(/%u/,"#{definition.ssh_user}")
    newcommand.gsub!(/%f/,"#{scriptname}")
    return newcommand
  end
end

#transfer_buildinfo(options) ⇒ Object

Transfer information provide by the Provider to the box



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/veewee/provider/core/box/build.rb', line 264

def transfer_buildinfo(options)
  build_info.each do |info|
    begin
      infofile=Tempfile.open("#{info[:filename]}")
      # Force binary mode to prevent windows from putting CR-LF end line style
      # http://www.ruby-forum.com/topic/127453#568546
      infofile.binmode
      infofile.puts "#{info[:content]}"
      infofile.rewind
      infofile.close
      self.copy_to_box(infofile.path,info[:filename])
      infofile.delete
    rescue RuntimeError => ex
      ui.error("Error transfering file #{info[:filename]} failed, possible not enough permissions to write? #{ex}",:prefix => false)
      raise Veewee::Error,"Error transfering file #{info[:filename]} failed, possible not enough permissions to write? #{ex}"
    end
  end
end

#validate_postinstall_regex(options) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/veewee/provider/core/box/build.rb', line 102

def validate_postinstall_regex(options)
  env.logger.info "Checking the postinstall excludes"
  unless options["postinstall_exclude"].nil?
    options["postinstall_exclude"].each do |p|
      begin
        r=::Regexp.new(p)
      rescue ::RegexpError => ex
        raise Veewee::Error ,"\nError in postinstall exclude (ruby regexp) pattern: #{p}:\n- #{ex}"
      end
    end
  end

  env.logger.info "Checking the postinstall includes"
  unless options["postinstall_include"].nil?
    options["postinstall_include"].each do |p|
      begin
        r=Regexp.new(p)
      rescue RegexpError => ex
        raise Veewee::Error ,"\nError in postinstall include (ruby regexp) pattern: #{p}:\n- #{ex}"
      end
    end
  end
end

#validate_tags(tags, options) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/veewee/provider/core/box/validate_tags.rb', line 6

def validate_tags(tags,options)

  unless self.exists?
    ui.error "Error:: You tried to validate box '#{name}' but it does not exist"
    exit -1
  end

  unless self.running?
    ui.error "Error:: You tried to validate box '#{name}' but it is not running"
    exit -1
  end

  require 'cucumber'

  require 'cucumber/rspec/disable_option_parser'
  require 'cucumber/cli/main'

  # Passing ssh options via ENV varialbles to cucumber
  # VEEWEE_SSH_USER, VEEWEE_SSH_PASSWORD ,VEEWEE_SSH_PORT
  cucumber_vars=ssh_options
  cucumber_vars.each do |key,value|
    ENV['VEEWEE_'+key.to_s.upcase]=cucumber_vars[key].to_s
  end

  # Pass the name of the box
  ENV['VEEWEE_BOXNAME']=@name
  ENV['VEEWEE_PROVIDER']=@provider.name

  if definition.winrm_user && definition.winrm_password # prefer winrm 
    featurefile="veewee-windows.feature"
  else
    featurefile="veewee.feature"
  end

  feature_path=File.join(File.dirname(__FILE__),"..","..","..","..","..","validation",featurefile)

  features=Array.new
  features[0]=feature_path
  features << "--tags"
  features << tags.map {|t| "@#{t}"}.join(',')

  begin
    # The dup is to keep ARGV intact, so that tools like ruby-debug can respawn.
    failure = Cucumber::Cli::Main.execute(features.dup)
    Kernel.exit(failure ? 1 : 0)
  rescue SystemExit => e
    Kernel.exit(e.status)
  rescue Exception => e
    ui.error("#{e.message} (#{e.class})")
    ui.error(e.backtrace.join("\n"))
    Kernel.exit(1)
  end

end

#vnc_type(sequence, host, display = 20) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/veewee/provider/core/box/vnc.rb', line 12

def vnc_type(sequence,host,display=20)
  counter=0
  env.logger.info "Opening VNC #{host} on display #{display}"
  vnc=Net::VNC.open("#{host}:#{display}",{:wait => 0.001})
  sequence.each { |s|
    counter=counter+1

    ui.info "Typing:[#{counter}]: "+s

    keycodes=string_to_vnccode(s)

      keycodes.each do |keycode|
        if keycode==:wait
          sleep 1
        else
          send_vnc_keycode(vnc,keycode)
        end
      end
  }
  vnc.close
  ui.info "Done typing."
  ui.info ""

end

#wget_vbsObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/veewee/provider/core/box/wincp.rb', line 67

def wget_vbs
  wget_vbs = <<-WGET
url = WScript.Arguments.Named("url")
path = WScript.Arguments.Named("path")
Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
Set wshShell = CreateObject( "WScript.Shell" )
Set objUserVariables = wshShell.Environment("USER")

'http proxy is optional
'attempt to read from HTTP_PROXY env var first
On Error Resume Next

If NOT (objUserVariables("HTTP_PROXY") = "") Then
objXMLHTTP.setProxy 2, objUserVariables("HTTP_PROXY")

'fall back to named arg
ElseIf NOT (WScript.Arguments.Named("proxy") = "") Then
objXMLHTTP.setProxy 2, WScript.Arguments.Named("proxy")
End If

On Error Goto 0

objXMLHTTP.open "GET", url, false
objXMLHTTP.send()
If objXMLHTTP.Status = 200 Then
Set objADOStream = CreateObject("ADODB.Stream")
objADOStream.Open
objADOStream.Type = 1
objADOStream.Write objXMLHTTP.ResponseBody
objADOStream.Position = 0
Set objFSO = Createobject("Scripting.FileSystemObject")
If objFSO.Fileexists(path) Then objFSO.DeleteFile path
Set objFSO = Nothing
objADOStream.SaveToFile path
objADOStream.Close
Set objADOStream = Nothing
End if
Set objXMLHTTP = Nothing
WGET
  #escape_and_echo(win_wget)
  wget_vbs
end

#wget_vbs_fileObject



46
47
48
# File 'lib/veewee/provider/core/box/wincp.rb', line 46

def wget_vbs_file
  "%TEMP%\\\\wget.vbs"
end

#wincp(localfile, remotefile, options = {}) ⇒ Object

Raises:



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/veewee/provider/core/box/wincp.rb', line 7

def wincp(localfile,remotefile,options={})
  raise Veewee::Error,"Box is not running" unless self.running?

  if self.exec("cmd.exe /C dir #{wget_vbs_file} > %TEMP%\\null",{:exitcode=>"*"}).status != 0
    env.ui.warn "Creating wget.vbs"
    create_wget_vbs_command do |command_chunk, chunk_num|
      self.exec("cmd.exe /C echo \"Rendering '#{wget_vbs_file}' chunk #{chunk_num}\" && #{command_chunk}")
    end
  end

  
  # Calculate an available kickstart port which we will use for wincp
  definition.kickstart_port = "7000" if definition.kickstart_port.nil?
  guessed_port=guess_free_port(definition.kickstart_port.to_i,7199).to_s
  if guessed_port.to_s!=definition.kickstart_port
    env.ui.warn "Changing wincp port from #{definition.kickstart_port} to #{guessed_port}"
    definition.kickstart_port=guessed_port.to_s
  end

  env.ui.warn "Spinning up a wait_for_http_request on http://#{host_ip_as_seen_by_guest}:#{definition.kickstart_port}#{localfile}"
  webthread=allow_for_http_request(localfile,{
      :port => definition.kickstart_port,
      :host => definition.kickstart_ip,
      :timeout => definition.kickstart_timeout,
      :web_dir => '/'
    })
  
  begin
    self.(self.ip_address,winrm_options.merge(options)) do
      env.ui.info "Going to try and copy #{localfile} to #{remotefile.inspect}"
      self.exec("cmd.exe /C cscript %TEMP%\\wget.vbs /url:http://#{host_ip_as_seen_by_guest}:#{definition.kickstart_port}#{localfile} /path:#{remotefile}")
      # while true do
      #   sleep 0.1 # used to debug
      # end
    end
  end
end

#winrm(command = nil, options = {}) ⇒ Object

Raises:



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/veewee/provider/core/box/winrm.rb', line 8

def winrm(command=nil,options={})

  raise Veewee::Error,"Box is not running" unless self.running?
  winrm_options={:user => definition.winrm_user,:password => definition.winrm_password, :port => definition.winrm_host_port, :exitcode => '*'}

  if (command.nil?)
    env.ui.info "This is a simple interactive shell"
    env.ui.info "To exit interactive mode, use 'quit!'"

    while 1
      command = ui.ask("veewee>")
      case command.strip
      when 'quit!'
        env.ui.info 'Bye!'
        break
      else
        winrm_execute(self.ip_address,command,winrm_options.merge(options))
      end
    end
  else
    winrm_execute(self.ip_address,command,winrm_options.merge(options))
  end


end

#winrm_command_stringObject



11
12
13
14
# File 'lib/veewee/provider/core/box/exec.rb', line 11

def winrm_command_string
  "knife winrm -m #{self.ip_address} -P #{winrm_options[:port]} -x #{definition.winrm_user}" +
    " -P #{definition.winrm_password} COMMAND"
end