Module: Veewee::Provider::Parallels::BoxCommand

Included in:
Box
Defined in:
lib/veewee/provider/parallels/box/up.rb,
lib/veewee/provider/parallels/box/halt.rb,
lib/veewee/provider/parallels/box/build.rb,
lib/veewee/provider/parallels/box/create.rb,
lib/veewee/provider/parallels/box/destroy.rb,
lib/veewee/provider/parallels/box/poweroff.rb,
lib/veewee/provider/parallels/box/helper/ip.rb,
lib/veewee/provider/parallels/box/helper/status.rb,
lib/veewee/provider/parallels/box/helper/buildinfo.rb,
lib/veewee/provider/parallels/box/helper/ssh_options.rb,
lib/veewee/provider/parallels/box/validate_parallels.rb,
lib/veewee/provider/parallels/box/helper/console_type.rb

Instance Method Summary collapse

Instance Method Details

#build(options) ⇒ Object



6
7
8
# File 'lib/veewee/provider/parallels/box/build.rb', line 6

def build(options)
  super(options)
end

#build_infoObject



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

def build_info
  info=super
  command="prlctl --version"
  output=IO.popen("#{command}").readlines
  info << {:filename => ".parallels_version",:content => output[0].split(/ /)[2]}

end

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

Type on the console



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

def console_type(sequence,type_options={})
  #FIXME
  send_sequence(sequence)
end

#create(options) ⇒ Object

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



8
9
10
11
12
# File 'lib/veewee/provider/parallels/box/create.rb', line 8

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

#create_diskObject



15
16
# File 'lib/veewee/provider/parallels/box/create.rb', line 15

def create_disk
end

#create_vmObject



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
# File 'lib/veewee/provider/parallels/box/create.rb', line 25

def create_vm
  parallels_definition=definition.dup
  distribution=parallels_os_type(definition.os_type_id)

  # Create the vm
  command="prlctl create '#{self.name}' --distribution '#{distribution}'"
  shell_exec("#{command}")
  command="prlctl set '#{self.name}' --cpus #{definition.cpu_count} --memsize #{definition.memory_size}"
  shell_exec("#{command}")


  #NOTE: order is important: as this determines the boot order sequence
  #
  # Remove the network to disable pxe boot
  command="prlctl set '#{self.name}' --device-del net0"
  shell_exec("#{command}")

  # Remove default cdrom
  command ="prlctl set '#{self.name}' --device-del cdrom0"
  shell_exec("#{command}")
  #
  # Attach cdrom
  full_iso_file=File.join(env.config.veewee.iso_dir,definition.iso_file)
  ui.info "Mounting cdrom: #{full_iso_file}"
  command ="prlctl set '#{self.name}' --device-add cdrom --enable --image '#{full_iso_file}'"
  shell_exec("#{command}")

  #Enable the network again
  command="prlctl set '#{self.name}' --device-add net --enable --type shared"
  shell_exec("#{command}")



end

#destroy(options = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/veewee/provider/parallels/box/destroy.rb', line 6

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

  if self.running?
    self.poweroff
    sleep 2
  end

  command="prlctl delete '#{self.name}'"
  shell_exec("#{command}")

end

#exists?Boolean

Check if box is running

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
24
# File 'lib/veewee/provider/parallels/box/helper/status.rb', line 16

def exists?

  command="prlctl list --all "
  shell_results=shell_exec("#{command}",{:mute => true})
  exists=shell_results.stdout.split(/\n/).grep(/ #{name}$/).size!=0

  env.logger.info("Vm exists? #{exists}")
  return exists
end

#guest_iso_pathObject

Determine the iso of the guest additions



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/veewee/provider/parallels/box/helper/buildinfo.rb', line 15

def guest_iso_path
  # So we begin by transferring the ISO file of the vmware tools

  # Set default
  iso_image="/Library/Parallels/Tools/prl-tools-lin.iso"
  iso_image="/Library/Parallels/Tools/prl-tools-mac.iso" if definition.os_type_id=~/^Darwin/
  iso_image="/Library/Parallels/Tools/prl-tools-win.iso" if definition.os_type_id=~/^Win/
  iso_image="/Library/Parallels/Tools/prl-tools-other.iso" if definition.os_type_id=~/^Free/
  iso_image="/Library/Parallels/Tools/prl-tools-other.iso" if definition.os_type_id=~/^Solaris/
  return iso_image

end

#halt(options = {}) ⇒ Object

FIXME



7
8
9
# File 'lib/veewee/provider/parallels/box/halt.rb', line 7

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

#ip_addressObject

Get the IP address of the box



7
8
9
10
11
12
# File 'lib/veewee/provider/parallels/box/helper/ip.rb', line 7

def ip_address
  mac=mac_address
  command="grep #{mac} /Library/Preferences/Parallels/parallels_dhcp_leases|cut -d '=' -f 1"
  ip=shell_exec("#{command}").stdout.strip.downcase
  return ip
end

#mac_addressObject



14
15
16
17
18
# File 'lib/veewee/provider/parallels/box/helper/ip.rb', line 14

def mac_address
  command="prlctl list -i '#{self.name}'|grep 'net0 (' | cut -d '=' -f 3 | cut -d ' ' -f 1 "
  mac=shell_exec("#{command}").stdout.strip.downcase
  return mac
end

#parallels_os_type(type_id) ⇒ Object



18
19
20
21
22
23
# File 'lib/veewee/provider/parallels/box/create.rb', line 18

def parallels_os_type(type_id)
  env.logger.info "Translating #{type_id} into parallels type"
  parallelstype=env.ostypes[type_id][:parallels]
  env.logger.info "Found Parallels type #{parallelstype}"
  return parallelstype
end

#poweroff(options = {}) ⇒ Object



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

def poweroff(options={})
  command="prlctl stop '#{self.name}' --kill"
  shell_exec("#{command}")
end

#press_key(key) ⇒ Object

Returns array



42
43
44
# File 'lib/veewee/provider/parallels/box/helper/console_type.rb', line 42

def press_key(key)
	  return key
end

#running?Boolean

Returns:

  • (Boolean)


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

def running?
  command="prlctl list -i '#{self.name}'"
  shell_results=shell_exec("#{command}",{:mute => true})
  running=shell_results.stdout.split(/\n/).grep(/^State: running/).size!=0

  env.logger.info("Vm running? #{running}")
  return running
end

#send_sequence(sequence) ⇒ Object



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

def send_sequence(sequence)

  ui.info ""

  counter=0
  sequence.each { |s|
    counter=counter+1

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

	    # No need to send the state, we always PRESS then RELEASE.
	    # So we send the whole string at once and press/release every string item
    keystring=self.string_to_parallels_keycode_string(s)

	    send_string(keystring);
  }

  ui.info "Done typing."
  ui.info ""


end

#send_string(keystring) ⇒ Object



35
36
37
38
39
# File 'lib/veewee/provider/parallels/box/helper/console_type.rb', line 35

def send_string(keystring)
  python_script=File.join(File.dirname(__FILE__),'..','..','..','..','..','python','parallels_send_string.py')
  command="python #{python_script} '#{self.name}' '#{keystring}'"
  shell_results=shell_exec("#{command}")
end

#shift(sequence) ⇒ Object

Returns array



47
48
49
50
51
52
53
54
# File 'lib/veewee/provider/parallels/box/helper/console_type.rb', line 47

def shift(sequence)
  seq=Array.new
  seq << press_key('SHIFT_LEFT')
  sequence.each_char do |s|
    seq << s
  end
  return seq
end

#ssh_optionsObject

Translate the definition ssh options to ssh options that can be passed to Net::Ssh calls



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

def ssh_options
  ssh_options={
    :user => definition.ssh_user,
    :port => 22,
    :password => definition.ssh_password,
    :timeout => definition..to_i
  }
  return ssh_options
end

#string_to_parallels_keycode_string(thestring) ⇒ Object



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
116
117
118
119
120
121
122
123
124
125
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/veewee/provider/parallels/box/helper/console_type.rb', line 56

def string_to_parallels_keycode_string(thestring)


  # Setup one key presses
  k=Hash.new
  for key in 'A'..'Z'
    k[key] = shift(press_key(key))
  end

  for key in 'a'..'z'
    k[key] = press_key(key.upcase)
  end

  for key in '0'..'9'
    k[key] = press_key(key.upcase)
  end

  k['>'] = shift(press_key('GREATER'))
  k['.'] = press_key('GREATER')
  k['<'] = shift(press_key('LESS'))
  k[':'] = shift(press_key('COLON'))
  k[';'] = press_key('COLON')
  k['/'] = press_key('SLASH')
  k[' '] = press_key('SPACE')
  k['-'] = press_key('MINUS')
  k['\''] = press_key('QUOTE')
  k['{'] = press_key('CBRACE_LEFT')
  k['}'] = press_key('CBRACE_RIGHT')
  k['`'] = press_key('TILDA')
  k['~'] = shift(press_key('TILDA'))

  k['_'] = shift(press_key('MINUS'))
  k['?'] = shift(press_key('SLASH'))
  k['"'] = shift(press_key('QUOTE'))
  k[')'] = shift(press_key('0'))
  k['!'] = shift(press_key('1'))
  k['@'] = shift(press_key('2'))
  k['#'] = shift(press_key('3'))
  k['$'] = shift(press_key('4'))
  k['%'] = shift(press_key('5'))
  k['^'] = shift(press_key('6'))
  k['&'] = shift(press_key('7'))
  k['*'] = shift(press_key('8'))
  k['('] = shift(press_key('9'))
  k['|'] = shift(press_key('BACKSLASH'))
  k[','] = press_key('LESS')
  k['\\'] = press_key('BACKSLASH')
  k['+'] = shift(press_key('PLUS'))
  k['='] = press_key('PLUS')

  # Setup special keys
  special=Hash.new;
  special['<Enter>'] = [{ 'code' => 'ENTER', 'state' => 'press' }]
  special['<Backspace>'] = [{ 'code' => 'BACKSPACE', 'state' => 'press' }]
  special['<Spacebar>'] = [{ 'code' => 'SPACE', 'state' => 'press' }]
  special['<Return>'] = [{ 'code' => 'RETURN', 'state' => 'press' }]
  special['<Esc>'] = [{ 'code' => 'ESC', 'state' => 'press' }]
  special['<Tab>'] = [{ 'code' => 'TAB', 'state' => 'press' }]
  #FIXME
  special['<KillX>'] = '1d 38 0e';
  special['<Wait>'] = [{'code' => 'wait', 'state' => ''}];

  special['<Up>'] = [{ 'code' => 'UP', 'state' => 'press' }]
  special['<Down>'] = [{ 'code' => 'DOWN', 'state' => 'press' }]
  special['<PageUp'] = [{ 'code' => 'PAGE_UP', 'state' => 'press' }]
  special['<PageDown'] = [{ 'code' => 'PAGE_DOWN', 'state' => 'press' }]
  special['<End>'] = [{ 'code' => 'END', 'state' => 'press' }]
  special['<Insert>'] = [{ 'code' => 'INSERT', 'state' => 'press' }]
  special['<Delete>'] = [{ 'code' => 'DELETE', 'state' => 'press' }]
  special['<Left>'] = [{ 'code' => 'LEFT', 'state' => 'press' }]
  special['<Right>'] = [{ 'code' => 'RIGHT', 'state' => 'press' }]
  special['<Home>'] = [{ 'code' => 'HOME', 'state' => 'press' }]

  for i in 1..12 do
    special["<F#{i}>"] = press_key("F#{i}")
  end

  keycodes= ""

  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
        if key=="<Wait>"
          sleep 1
        else
          special[key].each do |c|
            keycodes.concat("#{c['code']} ")
          end
        end
        thestring=thestring.slice(key.length,thestring.length-key.length)
        nospecial=false;
        break;
      end
    }
    if nospecial
      code=k[thestring.slice(0,1)]
      if !code.nil?
        code=[code] if code.class==String
        code.each do |c|
		  if(c == 'SHIFT_LEFT')
          	keycodes.concat("#{c}\#")
		  else
          	keycodes.concat("#{c} ")
		  end
        end
      else
        ui.info "no scan code for #{thestring.slice(0,1)}"
      end
      #pop one
      thestring=thestring.slice(1,thestring.length-1)
    end
  end

  return keycodes
end

#transfer_buildinfo(options) ⇒ Object

Transfer information provide by the provider to the box



31
32
33
34
35
36
37
38
39
40
# File 'lib/veewee/provider/parallels/box/helper/buildinfo.rb', line 31

def transfer_buildinfo(options)
  super(options)

  # 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

  ui.info "About to transfer parallels tools iso buildinfo to the box #{name} - #{ip_address} - #{ssh_options}"
  iso_image=guest_iso_path
  self.copy_to_box(iso_image,File.basename(iso_image))
end

#up(options = {}) ⇒ Object



6
7
8
9
10
# File 'lib/veewee/provider/parallels/box/up.rb', line 6

def up(options={})
  gui_enabled=options[:nogui]==true ? false : true
  command="prlctl start '#{self.name}'"
  shell_exec("#{command}")
end

#validate_parallels(options) ⇒ Object



6
7
8
# File 'lib/veewee/provider/parallels/box/validate_parallels.rb', line 6

def validate_parallels(options)
  validate_tags([ 'parallels','puppet','chef'],options)
end