Module: Veewee::Provider::Vmfusion::BoxCommand

Included in:
Box
Defined in:
lib/veewee/provider/vmfusion/box/up.rb,
lib/veewee/provider/vmfusion/box/ssh.rb,
lib/veewee/provider/parallels/box/ssh.rb,
lib/veewee/provider/vmfusion/box/halt.rb,
lib/veewee/provider/vmfusion/box/winrm.rb,
lib/veewee/provider/vmfusion/box/build.rb,
lib/veewee/provider/vmfusion/box/export.rb,
lib/veewee/provider/vmfusion/box/create.rb,
lib/veewee/provider/vmfusion/box/destroy.rb,
lib/veewee/provider/vmfusion/box/poweroff.rb,
lib/veewee/provider/vmfusion/box/template.rb,
lib/veewee/provider/vmfusion/box/add_share.rb,
lib/veewee/provider/vmfusion/box/helper/ip.rb,
lib/veewee/provider/vmfusion/box/helper/vnc.rb,
lib/veewee/provider/vmfusion/box/helper/status.rb,
lib/veewee/provider/vmfusion/box/helper/buildinfo.rb,
lib/veewee/provider/vmfusion/box/validate_vmfusion.rb,
lib/veewee/provider/vmfusion/box/helper/console_type.rb

Defined Under Namespace

Classes: ErbBinding

Instance Method Summary collapse

Instance Method Details

#add_share(share_name, share_path) ⇒ Object

This function 'adds a share' the box based on the definition


6
7
8
# File 'lib/veewee/provider/vmfusion/box/add_share.rb', line 6

def add_share(share_name, share_path)
  shell_exec("#{(vmrun_cmd).shellescape} -T fusion addSharedFolder #{vmx_file_path.shellescape} '#{share_name}' #{::File.expand_path(share_path).shellescape}")
end

#add_share_from_defnObject


10
11
12
13
14
# File 'lib/veewee/provider/vmfusion/box/add_share.rb', line 10

def add_share_from_defn
  definition.add_shares.each do |share_name, share_path|
    add_share(share_name, share_path)
  end
end

#build(options) ⇒ Object


8
9
10
11
# File 'lib/veewee/provider/vmfusion/box/build.rb', line 8

def build(options)
  super(options)
  add_share_from_defn
end

#build_infoObject


6
7
8
9
10
# File 'lib/veewee/provider/vmfusion/box/helper/buildinfo.rb', line 6

def build_info
  info=super
  output=IO.popen("#{vmrun_cmd.shellescape}").readlines
  info << {:filename => ".vmfusion_version",:content => @provider.fusion_version }
end

#console_type(sequence, type_options = {}) ⇒ Object

Type on the console


7
8
9
10
11
12
13
# File 'lib/veewee/provider/vmfusion/box/helper/console_type.rb', line 7

def console_type(sequence,type_options={})
  if vnc_enabled?
    vnc_type(sequence,"127.0.0.1",vnc_display_port)
  else
    raise Veewee::Error, "VNC is not enabled"
  end
end

#create(options) ⇒ Object

When we create a new box We assume the box is not running


10
11
12
13
14
# File 'lib/veewee/provider/vmfusion/box/create.rb', line 10

def create(options)
  create_vm
  create_disk
  self.create_floppy("virtualfloppy.img")
end

#create_diskObject


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/veewee/provider/vmfusion/box/create.rb', line 17

def create_disk
  #Disk types:
  #    0                   : single growable virtual disk
  #    1                   : growable virtual disk split in 2GB files
  #    2                   : preallocated virtual disk
  #    3                   : preallocated virtual disk split in 2GB files
  #    4                   : preallocated ESX-type virtual disk
  #    5                   : compressed disk optimized for streaming
  #    6                   : thin provisioned virtual disk - ESX 3.x and above
  disk_type=1
  current_dir=FileUtils.pwd
  FileUtils.chdir(vm_path)
  env.ui.info "Creating disk"
  command="#{File.dirname(vmrun_cmd).shellescape}/vmware-vdiskmanager -c -s #{definition.disk_size}M -a lsilogic -t #{disk_type} #{name}.vmdk"
  shell_results=shell_exec("#{command}",{:mute => true})
  FileUtils.chdir(current_dir)
end

#create_vmObject


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/veewee/provider/vmfusion/box/create.rb', line 42

def create_vm
  fusion_definition=definition.dup

  fusion_definition.os_type_id=fusion_os_type(definition.os_type_id)
 
  FileUtils.mkdir_p(vm_path)
  current_dir=FileUtils.pwd
  FileUtils.chdir(vm_path)
       
  unless definition.vmdk_file.nil?
    src = "#{File.join(definition.path,definition.vmdk_file)}"
    FileUtils.cp(src, vm_path)
  end

  aFile = File.new(vmx_file_path, "w")
  aFile.write(vmx_template(fusion_definition))
  aFile.close
  FileUtils.chdir(current_dir)
end

#destroy(options = {}) ⇒ Object


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

def destroy(options={})
  unless raw.exists?
    raise Veewee::Error, "Error:: You tried to destroy a non-existing box '#{name}'"
  end

  raw.halt if raw.state=="running"
  ::Fission::VM.new(name).delete
  # remove it from memory
  @raw=nil
end

#exists?Boolean

Check if the box already exists

Returns:

  • (Boolean)

13
14
15
# File 'lib/veewee/provider/vmfusion/box/helper/status.rb', line 13

def exists?
  return raw.exists?
end

#export_vmfusion(options) ⇒ Object

This function 'exports' the box based on the definition


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
# File 'lib/veewee/provider/vmfusion/box/export.rb', line 8

def export_vmfusion(options)
  case options["export_type"]
  when "ova"
    debug="--X:logToConsole=true --X:logLevel=\"verbose\""
    debug=""
    flags="--compress=9"

    if File.exists?("#{name}.ova")
      if options["force"]
        env.logger.debug("#{name}.ova exists, but --force was provided")
        env.logger.debug("removing #{name}.ova first")
        FileUtils.rm("#{name}.ova")
        env.logger.debug("#{name}.ova removed")
      else
        raise Veewee::Error, "export file #{name}.ova already exists. Use --force option to overwrite."
      end
    end

    # before exporting the system needs to be shut down
    ensure_vm_stopped(options)

    # otherwise the debug log will show - The specified virtual disk needs repair
    env.ui.info "Exporting VM to #{options["export_type"]}"
    shell_exec("#{File.dirname(vmrun_cmd).shellescape}#{"/VMware OVF Tool/ovftool".shellescape} #{debug} #{flags} #{vmx_file_path.shellescape} #{name}.ova")
  when "vagrant"
    debug=""
    flags="-tt=OVF"

    ensure_vm_stopped(options)

    optimize_disk

    # get a temp dir
    Dir.mktmpdir do |tmpdir|
      env.ui.info "Exporting VM to #{options["export_type"]} box"
      FileUtils.cp_r(Dir["#{vm_path}/*"],tmpdir)

      # Inject a Vagrantfile unless one is provided
      if options['vagrantfile']
        FileUtils.cp(options['vagrantfile'], File.join(tmpdir, 'Vagrantfile'))
      else
        File.open(File.join(tmpdir, 'Vagrantfile'), 'w') {|f| f.write(template_vagrantfile()) }
      end
      #Inject a metadata.json file
      File.open(File.join(tmpdir, 'metadata.json'), 'w') {|f| f.write(template_metadatafile()) }

      # Tar it up into the destination
      pwd = Dir.pwd
      shell_exec("cd #{tmpdir} && tar -czf #{File.join(pwd, name)}.box *")
    end
  end



end

#fusion_os_type(type_id) ⇒ Object


35
36
37
38
39
40
# File 'lib/veewee/provider/vmfusion/box/create.rb', line 35

def fusion_os_type(type_id)
  env.logger.info "Translating #{type_id} into fusion type"
  fusiontype=env.ostypes[type_id][:fusion]
  env.logger.info "Found fusion type #{fusiontype}"
  return fusiontype
end

#guess_vnc_portObject

This tries to guess a port for the VNC Display


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/veewee/provider/vmfusion/box/helper/vnc.rb', line 18

def guess_vnc_port
  min_port=5920
  max_port=6000
  guessed_port=nil

  for port in (min_port..max_port)
    unless is_tcp_port_open?("127.0.0.1", port)
      guessed_port=port
      break
    end
  end

  if guessed_port.nil?
    env.ui.info "No free VNC port available: tried #{min_port}..#{max_port}"
    raise Veewee::Error, "No free VNC port available: tried #{min_port}..#{max_port}"
  else
    env.ui.info "Found VNC port #{guessed_port} available"
  end

  return guessed_port
end

#guest_iso_directoryObject


13
14
15
16
17
18
19
20
21
22
# File 'lib/veewee/provider/vmfusion/box/helper/buildinfo.rb', line 13

def guest_iso_directory
  # use vmware fusion 3.x as default path
  iso_images_dir="/Library/Application Support/VMware Fusion/isoimages"

  # if path doesn't exist check for vmware fusion >= 4.x path
  if( ! File.exists?(iso_images_dir) )
    iso_images_dir="/Applications/VMware Fusion.app/Contents/Library/isoimages"
  end
  return iso_images_dir
end

#guest_iso_pathObject

Determine the iso of the guest additions


25
26
27
28
29
30
31
32
# File 'lib/veewee/provider/vmfusion/box/helper/buildinfo.rb', line 25

def guest_iso_path
  # So we begin by transferring the ISO file of the vmware tools
  iso_image=File.join(guest_iso_directory, "linux.iso")
  iso_image=File.join(guest_iso_directory, "darwin.iso") if definition.os_type_id=~/^Darwin/
  iso_image=File.join(guest_iso_directory, "freebsd.iso") if definition.os_type_id=~/^Free/
  iso_image=File.join(guest_iso_directory, "windows.iso") if definition.os_type_id=~/^Win/
  return iso_image
end

#halt(options = {}) ⇒ Object


6
7
8
# File 'lib/veewee/provider/vmfusion/box/halt.rb', line 6

def halt(options={})
   super(options)
end

#host_ip_as_seen_by_guestObject


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/veewee/provider/vmfusion/box/helper/ip.rb', line 43

def host_ip_as_seen_by_guest

  # if File.exists?("/Library/Application Support/VMware Fusion/vmnet8/nat.conf")
  #   file = "/Library/Application Support/VMware Fusion/vmnet8/nat.conf"
  # end

  # if File.exists?("/Library/Preferences/VMware Fusion/vmnet8/nat.conf")
  #   file = "/Library/Preferences/VMware Fusion/vmnet8/nat.conf"
  # end
  # File.open(file).readlines.grep(/ip = /).first.split(" ")[2]

  # The above is not always correct
  # There seems also an entry for vmnet8 in the dhcpd.conf
  # /Library/Preferences/VMware Fusion/vmnet8/dhcpd.conf
  # host vmnet8 {
  #   fixed-address

  # The above is fancy but doesn't always agree, we need to do is ifconfig vmnet8
  # Ifconfig never lies
  shell_results = shell_exec("ifconfig vmnet8", { :mute => true})
  shell_results.stdout.split(/\n/).grep(/inet /)[0].strip.split(/ /)[1]
end

#ip_addressObject

Retrieve the ip address for a vm. This will only look for dynamically assigned ip address via vmware dhcp

Raises:


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/veewee/provider/vmfusion/box/helper/ip.rb', line 22

def ip_address
  # Does not work for now as the vmx path is not escape correctly by fission 0.4.0
  #return raw.network_info.data.first['ip_address']
  raise ::Fission::Error,"VM #{name} does not exist" unless self.exists?
  
  # Use alternate method to retrieve the IP address using vmrun readVariable
  
  ip_address = shell_exec("#{vmrun_cmd.shellescape} readVariable \"#{vmx_file_path}\" guestVar ip", { :mute => true}).stdout.strip
  return ip_address unless ip_address.empty?

  unless mac_address.nil?
    lease = Fission::Lease.find_by_mac_address(mac_address).data
    return lease.ip_address unless lease.nil?
    return nil
  else
    # No mac address was found for this machine so we can't calculate the ip-address
    return nil
  end
end

#mac_addressObject

Retrieve the first mac address for a vm This will only retrieve the first auto generate mac address

Raises:


8
9
10
11
12
13
14
15
16
17
18
# File 'lib/veewee/provider/vmfusion/box/helper/ip.rb', line 8

def mac_address
  raise ::Fission::Error,"VM #{name} does not exist" unless self.exists?

  line=File.new(vmx_file_path).grep(/^ethernet0.generatedAddress =/)
  if line.nil?
    #Fission.ui.output "Hmm, the vmx file #{vmx_path} does not contain a generated mac address "
    return nil
  end
  address=line.first.split("=")[1].strip.split(/\"/)[1]
  return address
end

#poweroff(options = {}) ⇒ Object


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

def poweroff(options={})
  raw.stop(:hard => true) unless raw.nil?
end

#running?Boolean

Check if box is running

Returns:

  • (Boolean)

7
8
9
10
# File 'lib/veewee/provider/vmfusion/box/helper/status.rb', line 7

def running?
  return false if raw.nil?
  return raw.running?
end

#ssh(command, options) ⇒ Object


6
7
8
# File 'lib/veewee/provider/vmfusion/box/ssh.rb', line 6

def ssh(command,options={})
  super(command,options)
end

#transfer_buildinfo(options) ⇒ Object

Transfer information provide by the provider to the box


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/veewee/provider/vmfusion/box/helper/buildinfo.rb', line 37

def transfer_buildinfo(options)
  super(options)

  # Initialize download_tools to true if null
  if definition.vmfusion[:vm_options]['download_tools'].nil?
    definition.vmfusion[:vm_options]['download_tools'] = true 
  end

  # When we get here, ssh is available and no postinstall scripts have been executed yet
  # So we begin by transferring the ISO file of the vmware tools
  if !(definition.winrm_user && definition.winrm_password) && definition.vmfusion[:vm_options]['download_tools']
    # with windows, we just use the mounted volume
    env.logger.info "About to transfer vmware tools iso buildinfo to the box #{name} - #{ip_address} - #{ssh_options}"
    iso_image=guest_iso_path
    if File.exists?(iso_image)
      self.copy_to_box(iso_image,File.basename(iso_image))
    else
      raise Veewee::Error, "We could not find the file #{iso_image}. In newer versions of Fusion, you might have to download the Guest Additions yourself. You can do this by first manually creating a vm and than 'installing the guest additions'"
    end
  end
end

#up(options = {}) ⇒ Object


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

def up(options={})
  gui_enabled=options[:nogui]==true ? false : true
  if gui_enabled
    raw.start unless raw.nil?
  else
    raw.start({:headless => true}) unless raw.nil?
  end
end

#validate_vmfusion(options) ⇒ Object


6
7
8
# File 'lib/veewee/provider/vmfusion/box/validate_vmfusion.rb', line 6

def validate_vmfusion(options)
  validate_tags( options['tags'],options)
end

#vmx_template(definition) ⇒ Object


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/vmfusion/box/template.rb', line 13

def vmx_template(definition)
  # We only want specific variables for ERB

  floppy_path=nil
  unless definition.floppy_files.nil?
    floppy_path=File.join(definition.path,'virtualfloppy.img')
  end
  
  # Property to support enabling hypervisor support in a VM
  enable_hypervisor_support = definition.vmfusion[:vm_options]['enable_hypervisor_support']
  
  # Depending on the fusion version, we need to update the virtualhw version
  fusion_version = @provider.fusion_version
  if fusion_version.start_with?('6.')
    virtualhw_version = 10
  elsif fusion_version.start_with?('5.')
    virtualhw_version = 9
  else
    virtualhw_version = 7
  end
  
  puts definition.vmdk_file
  vmdk_file = File.basename(definition.vmdk_file) unless definition.vmdk_file.nil?
  # Setup the variables for in the erb template
  data = {
    :cpu_count => definition.cpu_count, :memory_size => definition.memory_size,
    :controller_type => "lsilogic",
    :fusion_os_type => definition.os_type_id,
    :virtualhw_version => virtualhw_version,
    :floppyfile => floppy_path,
    :mac_addres => "auto generated",
    :iso_file => "#{File.join(env.config.veewee.iso_dir,definition.iso_file)}",
    :box_name => name,
    :vnc_port => guess_vnc_port,
    :fusion_version => fusion_version,
    :vmdk_file => vmdk_file,
    :enable_hypervisor_support => enable_hypervisor_support
  }

  vars = ErbBinding.new(data)
  template_path=File.join(File.dirname(__FILE__),"template.vmx.erb")
  template=File.open(template_path).readlines.join
  erb = ERB.new(template)
  vars_binding = vars.send(:get_binding)
  result=erb.result(vars_binding)
  return result
end

#vnc_display_portObject


40
41
42
# File 'lib/veewee/provider/vmfusion/box/helper/vnc.rb', line 40

def vnc_display_port
  self.vnc_port - 5900
end

#vnc_enabled?Boolean

Returns:

  • (Boolean)

44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/veewee/provider/vmfusion/box/helper/vnc.rb', line 44

def vnc_enabled?
   lines=File.readlines(vmx_file_path)
   matches=lines.grep(/^RemoteDisplay.vnc.enabled/)
   if matches.length==0
      return false
   else
      if matches.first.split("\"")[1].downcase == 'true'
        return true
      else
        return false
      end
   end
end

#vnc_portObject


6
7
8
9
10
11
12
13
14
15
# File 'lib/veewee/provider/vmfusion/box/helper/vnc.rb', line 6

def vnc_port
   lines=File.readlines(vmx_file_path)
   matches=lines.grep(/^RemoteDisplay.vnc.port/)
   if matches.length==0
      raise Veewee::Error,"No VNC port found, maybe it is not enabled?"
   else
      value=matches.first.split("\"")[1].to_i
      return value
   end
end

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


6
7
8
# File 'lib/veewee/provider/vmfusion/box/winrm.rb', line 6

def winrm(command,options = {})
  super(command,options)
end