Class: Vmit::VirtualMachine
- Inherits:
-
Object
- Object
- Vmit::VirtualMachine
- Defined in:
- lib/vmit/virtual_machine.rb
Constant Summary collapse
- VM_DEFAULTS =
{ :memory => '1G', }
- SWITCH =
'br0'
- DISK_INIT_DEFAULTS =
{:disk_size => '10G'}
- BINDIR =
File.join(File.dirname(__FILE__), '../../bin')
Instance Attribute Summary collapse
-
#work_dir ⇒ Object
Returns the value of attribute work_dir.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Accessor to current options.
-
#config ⇒ Hash
Config of the virtual machine This is all options plus the defaults.
- #config_file ⇒ Object
- #current_image ⇒ Object
- #disk_image_init!(opts = {}) ⇒ Object
-
#disk_image_shift!(opts = {}) ⇒ Object
Shifts an image, adding a new one using the previous newest one as backing file.
-
#disk_images ⇒ Array, <String>
Sorted list of snapshots.
-
#disk_rollback! ⇒ Object
Rolls back to the previous snapshot.
-
#disk_snapshot! ⇒ Object
Takes a disk snapshot.
-
#ifdown(device) ⇒ Object
Called by vmit-ifdown.
-
#ifup(device) ⇒ Object
Called by vmit-ifup.
-
#initialize(work_dir) ⇒ VirtualMachine
constructor
A new instance of VirtualMachine.
- #options ⇒ Object
-
#relevant_config ⇒ Hash
Config that differs from default and therefore relevant to be persisted in config.yml.
-
#run(runtime_opts) ⇒ Object
Starts the virtual machine.
-
#save_config! ⇒ Object
Saves the configuration in config.yml.
- #to_s ⇒ Object
Constructor Details
#initialize(work_dir) ⇒ VirtualMachine
Returns a new instance of VirtualMachine.
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 |
# File 'lib/vmit/virtual_machine.rb', line 49 def initialize(work_dir) @pidfile = PidFile.new(:piddir => work_dir, :pidfile => "vmit.pid") @work_dir = work_dir @opts = {} @opts.merge!(VM_DEFAULTS) if File.exist?(config_file) @opts.merge!(YAML::load(File.open(config_file))) end # By default the following keys are useful to be # generated if they don't exist and then use the # same in the future UNLESS they are # overriden with vmit run if not @opts.has_key?(:mac_address) @opts[:mac_address] = Vmit::Utils.random_mac_address end if not @opts.has_key?(:uuid) @opts[:uuid] = File.read("/proc/sys/kernel/random/uuid").strip end @network = if @opts.has_key?(:network) Network.create(@opts[:network]) else Vmit.logger.info 'No network selected. Using default.' Network.default end Vmit.logger.info "Network: #{@network}" end |
Instance Attribute Details
#work_dir ⇒ Object
Returns the value of attribute work_dir.
33 34 35 |
# File 'lib/vmit/virtual_machine.rb', line 33 def work_dir @work_dir end |
Instance Method Details
#[](key) ⇒ Object
Accessor to current options
41 42 43 |
# File 'lib/vmit/virtual_machine.rb', line 41 def [](key) @opts[key] end |
#config ⇒ Hash
Returns Config of the virtual machine This is all options plus the defaults.
155 156 157 |
# File 'lib/vmit/virtual_machine.rb', line 155 def config VM_DEFAULTS.merge(@opts) end |
#config_file ⇒ Object
45 46 47 |
# File 'lib/vmit/virtual_machine.rb', line 45 def config_file File.join(work_dir, 'config.yml') end |
#current_image ⇒ Object
143 144 145 146 147 |
# File 'lib/vmit/virtual_machine.rb', line 143 def current_image curr = disk_images.last raise "No hard disk image available" if curr.nil? curr end |
#disk_image_init!(opts = {}) ⇒ Object
93 94 95 |
# File 'lib/vmit/virtual_machine.rb', line 93 def disk_image_init!(opts={}) disk_image_shift!(opts) end |
#disk_image_shift!(opts = {}) ⇒ Object
Shifts an image, adding a new one using the previous newest one as backing file
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/vmit/virtual_machine.rb', line 104 def disk_image_shift!(opts={}) runtime_opts = DISK_INIT_DEFAULTS.merge(opts) file_name = File.join(work_dir, "sda-#{Time.now.to_i}.qcow2") images = disk_images file_name = 'base.qcow2' if images.size == 0 args = ['/usr/bin/qemu-img', 'create', '-f', "qcow2"] if not images.empty? args << '-b' args << images.last end args << file_name if images.empty? args << runtime_opts[:disk_size] end Vmit.logger.info "Shifted image. Current is '#{file_name}'." Cheetah.run(*args) end |
#disk_images ⇒ Array, <String>
Returns sorted list of snapshots.
82 83 84 85 86 |
# File 'lib/vmit/virtual_machine.rb', line 82 def disk_images Dir.glob(File.join(work_dir, '*.qcow2')).sort do |a,b| File.ctime(a) <=> File.ctime(b) end end |
#disk_rollback! ⇒ Object
Rolls back to the previous snapshot
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/vmit/virtual_machine.rb', line 129 def disk_rollback! images = disk_images return if images.empty? if images.size == 1 Vmit.logger.fatal "Only the base snapshot left!" return end Vmit.logger.info "Removing #{images.last}" FileUtils.rm(images.last) end |
#disk_snapshot! ⇒ Object
Takes a disk snapshot
89 90 91 |
# File 'lib/vmit/virtual_machine.rb', line 89 def disk_snapshot! disk_image_shift! end |
#ifdown(device) ⇒ Object
Called by vmit-ifdown
292 293 294 295 296 |
# File 'lib/vmit/virtual_machine.rb', line 292 def ifdown(device) Vmit.logger.info " Bringing down interface #{device}" Cheetah.run '/sbin/ifconfig', device, '0.0.0.0', 'down' @network.disconnect_interface(device) end |
#ifup(device) ⇒ Object
Called by vmit-ifup
285 286 287 288 289 |
# File 'lib/vmit/virtual_machine.rb', line 285 def ifup(device) Vmit.logger.info " Bringing interface #{device} up" Cheetah.run '/sbin/ifconfig', device, '0.0.0.0', 'up' @network.connect_interface(device) end |
#options ⇒ Object
149 150 151 |
# File 'lib/vmit/virtual_machine.rb', line 149 def @opts end |
#relevant_config ⇒ Hash
Returns config that differs from default and therefore relevant to be persisted in config.yml.
161 162 163 |
# File 'lib/vmit/virtual_machine.rb', line 161 def relevant_config config.diff(VM_DEFAULTS) end |
#run(runtime_opts) ⇒ Object
Starts the virtual machine
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 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 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/vmit/virtual_machine.rb', line 189 def run(runtime_opts) Vmit.logger.info "Starting VM..." # Don't overwrite @opts so that # run can be called various times opts = {} opts.merge!(@opts) opts.merge!(runtime_opts) config.each do |k,v| Vmit.logger.info " => #{k} : #{v}" end begin # HACK, will be replaced by a better config system use_virtio = ! File.exist?(File.join(work_dir, '.disable-virtio')) ifup = File.(File.join(BINDIR, 'vmit-ifup')) ifdown = File.(File.join(BINDIR, 'vmit-ifdown')) args = ['/usr/bin/qemu-kvm', '-boot', 'c', '-m', "#{opts[:memory]}", '-pidfile', File.join(work_dir, 'qemu.pid')] if use_virtio args << '-drive' args << "file=#{current_image},if=virtio" args << '-netdev' args << "type=tap,script=#{ifup},downscript=#{ifdown},id=vnet0" args << '-device' args << "virtio-net-pci,netdev=vnet0,mac=#{opts[:mac_address]}" else args << '-drive' args << "file=#{current_image}" args << '-net' args << "nic,macaddr=#{opts[:mac_address]}" args << '-net' args << "tap,script=#{ifup},downscript=#{ifdown}" end # advanced options, mostly to be used by plugins [:cdrom, :kernel, :initrd, :append].each do |key| if opts.has_key?(key) args << "-#{key}" args << case opts[key] # append is multple when Array then opts[key].join(' ') else opts[key] end end end if opts.has_key?(:floppy) if File.directory?(opts[:floppy]) args << '-fda' args << "fat:floppy:#{opts[:floppy]}" else Vmit.logger.warn "#{opts[:floppy]} : only directories supported" end end # options that translate to # -no-something if :something => false [:reboot].each do |key| if opts.has_key?(key) # default is true args << "-no-#{key}" if not opts[key] end end unless ENV['DISABLE_UUID'] args << '-uuid' args << "#{opts[:uuid]}" end DRb.start_service nil, self ENV['VMIT_SERVER'] = DRb.uri ENV['VMIT_SWITCH'] = SWITCH Vmit.logger.debug "Vmit server listening at #{DRb.uri}" @network.auto do begin Cheetah.run(*args) ensure FileUtils.rm_f File.join(work_dir, 'qemu.pid') end end rescue PidFile::DuplicateProcessError => e Vmit.logger.fatal "VM in '#{work_dir}'' is already running (#{e})" raise end end |
#save_config! ⇒ Object
Saves the configuration in config.yml
166 167 168 169 170 171 172 173 |
# File 'lib/vmit/virtual_machine.rb', line 166 def save_config! if not relevant_config.empty? Vmit.logger.info "Writing config.yml..." File.open(config_file, 'w') do |f| f.write(relevant_config.to_yaml) end end end |
#to_s ⇒ Object
175 176 177 |
# File 'lib/vmit/virtual_machine.rb', line 175 def to_s config.to_s end |