Class: VagrantPlugins::ProviderKvm::Driver::Driver
- Inherits:
-
Object
- Object
- VagrantPlugins::ProviderKvm::Driver::Driver
- Includes:
- Util
- Defined in:
- lib/vagrant-kvm/driver/driver.rb
Defined Under Namespace
Classes: VMNotFound
Constant Summary collapse
- VM_STATE =
enum for states return by libvirt
[ :no_state, :running, :blocked, :paused, :shutdown, :shutoff, :crashed]
Instance Attribute Summary collapse
-
#uuid ⇒ Object
readonly
The UUID of the virtual machine we represent.
-
#version ⇒ Object
readonly
The QEMU version XXX sufficient or have to check kvm and libvirt versions?.
Instance Method Summary collapse
-
#create_network(config) ⇒ Object
Create network.
- #delete ⇒ Object
-
#halt ⇒ Object
Halts the virtual machine.
-
#import(xml, path) ⇒ String
Imports the VM.
-
#import_ovf(ovf, path) ⇒ String
Imports the VM from an OVF file.
-
#init_storage(base_path) ⇒ Object
Initialize or create storage pool.
-
#initialize(uuid = nil) ⇒ Driver
constructor
A new instance of Driver.
-
#read_network_interfaces ⇒ Hash
Returns a list of network interfaces of the VM.
- #read_state ⇒ Object
-
#read_version ⇒ Hash
Return the qemu version.
-
#resume ⇒ Object
Resumes the previously paused virtual machine.
- #set_mac_address(mac) ⇒ Object
-
#start ⇒ Object
Starts the virtual machine.
-
#suspend ⇒ Object
Suspend the virtual machine and saves its states.
-
#verify! ⇒ Object
Verifies that the driver is ready and the connection is open.
-
#vm_exists?(uuid) ⇒ Boolean
Checks if a VM with the given UUID exists.
Constructor Details
#initialize(uuid = nil) ⇒ Driver
Returns a new instance of Driver.
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 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 31 def initialize(uuid=nil) @logger = Log4r::Logger.new("vagrant::provider::kvm::driver") @uuid = uuid # This should be configurable @pool_name = "vagrant" @network_name = "vagrant" # Open a connection to the qemu driver begin @conn = Libvirt::open('qemu:///system') rescue Libvirt::Error => e if e.libvirt_code == 5 # can't connect to hypervisor raise Vagrant::Errors::KvmNoConnection else raise e end end @version = read_version if (@version[:maj] == 1 && @version[:min] < 2) || @version[:maj] < 1 raise Vagrant::Errors::KvmInvalidVersion end # Get storage pool if it exists begin @pool = @conn.lookup_storage_pool_by_name(@pool_name) @logger.info("Init storage pool #{@pool_name}") rescue Libvirt::RetrieveError # storage pool doesn't exist yet end if @uuid # Verify the VM exists, and if it doesn't, then don't worry # about it (mark the UUID as nil) raise VMNotFound if !vm_exists?(@uuid) end end |
Instance Attribute Details
#uuid ⇒ Object (readonly)
The UUID of the virtual machine we represent
25 26 27 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 25 def uuid @uuid end |
#version ⇒ Object (readonly)
The QEMU version XXX sufficient or have to check kvm and libvirt versions?
29 30 31 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 29 def version @version end |
Instance Method Details
#create_network(config) ⇒ Object
Create network
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 144 def create_network(config) begin # Get the network if it exists @network = @conn.lookup_network_by_name(@network_name) definition = Util::NetworkDefinition.new(@network_name, @network.xml_desc) @network.destroy if @network.active? @network.undefine rescue Libvirt::RetrieveError # Network doesn't exist, create with defaults definition = Util::NetworkDefinition.new(@network_name) end definition.configure(config) @network = @conn.define_network_xml(definition.as_xml) @logger.info("Creating network #{@network_name}") @network.create end |
#delete ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 69 def delete domain = @conn.lookup_domain_by_uuid(@uuid) definition = Util::VmDefinition.new(domain.xml_desc, 'libvirt') volume = @pool.lookup_volume_by_path(definition.disk) volume.delete # XXX remove pool if empty? @pool.refresh # remove any saved state domain.managed_save_remove if domain.has_managed_save? domain.undefine end |
#halt ⇒ Object
Halts the virtual machine
82 83 84 85 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 82 def halt domain = @conn.lookup_domain_by_uuid(@uuid) domain.destroy end |
#import(xml, path) ⇒ String
Imports the VM
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 92 def import(xml, path) @logger.info("Importing VM") # create vm definition from xml definition = File.open(xml) { |f| Util::VmDefinition.new(f.read) } # copy volume to storage pool box_disk = definition.disk new_disk = File.basename(box_disk, File.extname(box_disk)) + "-" + Time.now.to_i.to_s + ".img" @logger.info("Copying volume #{box_disk} to #{new_disk}") old_path = File.join(File.dirname(xml), box_disk) new_path = File.join(path, new_disk) # we use qemu-img convert to preserve image size system("qemu-img convert -p #{old_path} -O raw #{new_path}") @pool.refresh volume = @pool.lookup_volume_by_name(new_disk) definition.disk = volume.path # create vm @logger.info("Creating new VM") domain = @conn.define_domain_xml(definition.as_libvirt) domain.uuid end |
#import_ovf(ovf, path) ⇒ String
Imports the VM from an OVF file. XXX should be fusioned with import
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 121 def import_ovf(ovf, path) @logger.info("Importing OVF definition for VM") # create vm definition from ovf definition = File.open(ovf) { |f| Util::VmDefinition.new(f.read, 'ovf') } # copy volume to storage pool box_disk = definition.disk new_disk = File.basename(box_disk, File.extname(box_disk)) + "-" + Time.now.to_i.to_s + ".img" @logger.info("Converting volume #{box_disk} to #{new_disk}") old_path = File.join(File.dirname(ovf), box_disk) new_path = File.join(path, new_disk) system("qemu-img convert -p #{old_path} -O raw #{new_path}") @pool.refresh volume = @pool.lookup_volume_by_name(new_disk) definition.disk = volume.path # create vm @logger.info("Creating new VM") domain = @conn.define_domain_xml(definition.as_libvirt) domain.uuid end |
#init_storage(base_path) ⇒ Object
Initialize or create storage pool
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 163 def init_storage(base_path) begin # Get the storage pool if it exists @pool = @conn.lookup_storage_pool_by_name(@pool_name) @logger.info("Init storage pool #{@pool_name}") rescue Libvirt::RetrieveError # Storage pool doesn't exist so we create it # create dir if it doesn't exist # if we let libvirt create the dir it is owned by root pool_path = base_path.join("storage-pool") pool_path.mkpath unless Dir.exists?(pool_path) storage_pool_xml = <<-EOF <pool type="dir"> <name>#{@pool_name}</name> <target> <path>#{pool_path}</path> </target> </pool> EOF @pool = @conn.define_storage_pool_xml(storage_pool_xml) @pool.build @logger.info("Creating storage pool #{@pool_name} in #{pool_path}") end @pool.create unless @pool.active? @pool.refresh end |
#read_network_interfaces ⇒ Hash
Returns a list of network interfaces of the VM.
193 194 195 196 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 193 def read_network_interfaces domain = @conn.lookup_domain_by_uuid(@uuid) Util::VmDefinition.list_interfaces(domain.xml_desc) end |
#read_state ⇒ Object
198 199 200 201 202 203 204 205 206 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 198 def read_state domain = @conn.lookup_domain_by_uuid(@uuid) state, reason = domain.state # check if domain has been saved if VM_STATE[state] == :shutoff and domain.has_managed_save? return :saved end VM_STATE[state] end |
#read_version ⇒ Hash
Return the qemu version
211 212 213 214 215 216 217 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 211 def read_version # libvirt returns a number like 1002002 for version 1.2.2 # we return just the major.minor part like this 1002 maj = @conn.version / 1000000 min = (@conn.version - maj*1000000) / 1000 { :maj => maj, :min => min } end |
#resume ⇒ Object
Resumes the previously paused virtual machine.
220 221 222 223 224 225 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 220 def resume @logger.debug("Resuming paused VM...") domain = @conn.lookup_domain_by_uuid(@uuid) domain.resume true end |
#set_mac_address(mac) ⇒ Object
227 228 229 230 231 232 233 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 227 def set_mac_address(mac) domain = @conn.lookup_domain_by_uuid(@uuid) definition = Util::VmDefinition.new(domain.xml_desc, 'libvirt') definition.set_mac(mac) domain.undefine @conn.define_domain_xml(definition.as_libvirt) end |
#start ⇒ Object
Starts the virtual machine.
236 237 238 239 240 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 236 def start domain = @conn.lookup_domain_by_uuid(@uuid) domain.create true end |
#suspend ⇒ Object
Suspend the virtual machine and saves its states.
243 244 245 246 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 243 def suspend domain = @conn.lookup_domain_by_uuid(@uuid) domain.managed_save end |
#verify! ⇒ Object
Verifies that the driver is ready and the connection is open
This will raise a VagrantError if things are not ready.
251 252 253 254 255 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 251 def verify! if @conn.closed? raise Vagrant::Errors::KvmNoConnection end end |
#vm_exists?(uuid) ⇒ Boolean
Checks if a VM with the given UUID exists.
260 261 262 263 264 265 266 267 |
# File 'lib/vagrant-kvm/driver/driver.rb', line 260 def vm_exists?(uuid) begin @logger.info("Check if VM #{uuid} exists") @conn.lookup_domain_by_uuid(uuid) rescue Libvirt::RetrieveError false end end |