lib/vagrant-libvirt/driver.rb in vagrant-libvirt-0.9.0 vs lib/vagrant-libvirt/driver.rb in vagrant-libvirt-0.10.0
- old
+ new
@@ -30,21 +30,22 @@
# Get config options for Libvirt provider.
config = @machine.provider_config
uri = config.uri
- conn_attr = {}
- conn_attr[:provider] = 'libvirt'
- conn_attr[:libvirt_uri] = uri
- conn_attr[:libvirt_username] = config.username if config.username
- conn_attr[:libvirt_password] = config.password if config.password
-
# Setup command for retrieving IP address for newly created machine
# with some MAC address. Get it from dnsmasq leases table
ip_command = %q( awk "/$mac/ {print \$1}" /proc/net/arp )
- conn_attr[:libvirt_ip_command] = ip_command
+ conn_attr = {
+ provider: 'libvirt',
+ libvirt_uri: uri,
+ libvirt_ip_command: ip_command,
+ }
+ conn_attr[:libvirt_username] = config.username if config.username
+ conn_attr[:libvirt_password] = config.password if config.password
+
@logger.info("Connecting to Libvirt (#{uri}) ...")
begin
@connection = Fog::Compute.new(conn_attr)
rescue Fog::Errors::Error => e
raise Errors::FogLibvirtConnectionError,
@@ -59,24 +60,22 @@
# again.
return @system_connection if @system_connection
config = @machine.provider_config
- @system_connection = Libvirt::open_read_only(config.system_uri)
+ @system_connection = Libvirt.open_read_only(config.system_uri)
@system_connection
end
def get_domain(machine)
begin
domain = connection.servers.get(machine.id)
rescue Libvirt::RetrieveError => e
- if e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
- @logger.debug("machine #{machine.name} domain not found #{e}.")
- return nil
- else
- raise e
- end
+ raise e unless e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
+
+ @logger.debug("machine #{machine.name} domain not found #{e}.")
+ return nil
end
domain
end
@@ -97,36 +96,86 @@
get_domain_ipaddress(machine, domain)
end
def get_domain_ipaddress(machine, domain)
# attempt to get ip address from qemu agent
- if @machine.provider_config.qemu_use_agent == true
+ if machine.provider_config.qemu_use_agent == true
@logger.info('Get IP via qemu agent')
- return get_ipaddress_from_qemu_agent(domain, machine.id)
+ return get_ipaddress_from_qemu_agent(domain, machine.id, machine.config.vm.boot_timeout)
end
- if @machine.provider_config.qemu_use_session
- return get_ipaddress_from_system domain.mac
- end
+ return get_ipaddress_from_system domain.mac if machine.provider_config.qemu_use_session
# Get IP address from dhcp leases table
begin
ip_address = get_ipaddress_from_domain(domain)
rescue Fog::Errors::TimeoutError
- @logger.info('Timeout at waiting for an ip address for machine %s' % machine.name)
+ @logger.info("Timeout at waiting for an ip address for machine #{machine.name}")
raise
end
unless ip_address
- @logger.info('No arp table entry found for machine %s' % machine.name)
+ @logger.info("No arp table entry found for machine #{machine.name}")
return nil
end
ip_address
end
+ def restore_snapshot(machine, snapshot_name)
+ domain = get_libvirt_domain(machine)
+ snapshot = get_snapshot_if_exists(machine, snapshot_name)
+ begin
+ # 4 is VIR_DOMAIN_SNAPSHOT_REVERT_FORCE
+ # needed due to https://bugzilla.redhat.com/show_bug.cgi?id=1006886
+ domain.revert_to_snapshot(snapshot, 4)
+ rescue Fog::Errors::Error => e
+ raise Errors::SnapshotReversionError, error_message: e.message
+ end
+ end
+
+ def list_snapshots(machine)
+ get_libvirt_domain(machine).list_snapshots
+ rescue Fog::Errors::Error => e
+ raise Errors::SnapshotListError, error_message: e.message
+ end
+
+ def delete_snapshot(machine, snapshot_name)
+ get_snapshot_if_exists(machine, snapshot_name).delete
+ rescue Errors::SnapshotMissing => e
+ raise Errors::SnapshotDeletionError, error_message: e.message
+ end
+
+ def create_new_snapshot(machine, snapshot_name)
+ snapshot_desc = <<-EOF
+ <domainsnapshot>
+ <name>#{snapshot_name}</name>
+ <description>Snapshot for vagrant sandbox</description>
+ </domainsnapshot>
+ EOF
+ get_libvirt_domain(machine).snapshot_create_xml(snapshot_desc)
+ rescue Fog::Errors::Error => e
+ raise Errors::SnapshotCreationError, error_message: e.message
+ end
+
+ def create_snapshot(machine, snapshot_name)
+ begin
+ delete_snapshot(machine, snapshot_name)
+ rescue Errors::SnapshotDeletionError
+ end
+ create_new_snapshot(machine, snapshot_name)
+ end
+
+ # if we can get snapshot description without exception it exists
+ def get_snapshot_if_exists(machine, snapshot_name)
+ snapshot = get_libvirt_domain(machine).lookup_snapshot_by_name(snapshot_name)
+ return snapshot if snapshot.xml_desc
+ rescue Libvirt::RetrieveError => e
+ raise Errors::SnapshotMissing, error_message: e.message
+ end
+
def state(machine)
# may be other error states with initial retreival we can't handle
begin
domain = get_domain(machine)
rescue Libvirt::RetrieveError => e
@@ -147,75 +196,88 @@
@logger.debug("Machine #{machine.id} running but no IP address available: #{e}.")
return :inaccessible
end
end
- return state
+ state
end
private
def get_ipaddress_from_system(mac)
ip_address = nil
system_connection.list_all_networks.each do |net|
leases = net.dhcp_leases(mac, 0)
# Assume the lease expiring last is the current IP address
- ip_address = leases.sort_by { |lse| lse["expirytime"] }.last["ipaddr"] if !leases.empty?
+ ip_address = leases.max_by { |lse| lse['expirytime'] }['ipaddr'] unless leases.empty?
break if ip_address
end
ip_address
end
- def get_ipaddress_from_qemu_agent(domain, machine_id)
+ def get_ipaddress_from_qemu_agent(domain, machine_id, timeout)
ip_address = nil
addresses = nil
libvirt_domain = connection.client.lookup_domain_by_uuid(machine_id)
begin
- response = libvirt_domain.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout=10)
- @logger.debug("Got Response from qemu agent")
+ response = libvirt_domain.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout)
+ @logger.debug('Got Response from qemu agent')
@logger.debug(response)
addresses = JSON.parse(response)
- rescue => e
- @logger.debug("Unable to receive IP via qemu agent: [%s]" % e.message)
+ rescue StandardError => e
+ puts "Unable to receive IP via qemu agent: [#{e.message}]"
+ @logger.debug("Unable to receive IP via qemu agent: [#{e.message}]")
end
unless addresses.nil?
- addresses["return"].each{ |interface|
- if domain.mac.downcase == interface["hardware-address"].downcase
- @logger.debug("Found mathing interface: [%s]" % interface["name"])
- if interface.has_key?("ip-addresses")
- interface["ip-addresses"].each{ |ip|
- # returning ipv6 addresses might break windows guests because
- # winrm cant handle connection, winrm fails with "invalid uri"
- if ip["ip-address-type"] == "ipv4"
- ip_address = ip["ip-address"]
- @logger.debug("Return IP: [%s]" % ip_address)
- break
- end
- }
- end
+ addresses['return'].each do |interface|
+ next unless domain.mac.downcase == interface['hardware-address'].downcase
+
+ @logger.debug("Found matching interface: [#{interface['name']}]")
+ next unless interface.key?('ip-addresses')
+
+ interface['ip-addresses'].each do |ip|
+ # returning ipv6 addresses might break windows guests because
+ # winrm can't handle connection, winrm fails with "invalid uri"
+ next unless ip['ip-address-type'] == 'ipv4'
+
+ ip_address = ip['ip-address']
+ @logger.debug("Return IP: [#{ip_address}]")
+ break
end
- }
+ end
end
ip_address
end
def get_ipaddress_from_domain(domain)
ip_address = nil
domain.wait_for(2) do
- addresses.each_pair do |type, ip|
+ addresses.each_pair do |_type, ip|
# Multiple leases are separated with a newline, return only
# the most recent address
- ip_address = ip[0].split("\n").first if ip[0] != nil
+ ip_address = ip[0].split("\n").first unless ip[0].nil?
end
- ip_address != nil
+ !ip_address.nil?
end
ip_address
end
+ def get_libvirt_domain(machine)
+ begin
+ libvirt_domain = connection.client.lookup_domain_by_uuid(machine.id)
+ rescue Libvirt::RetrieveError => e
+ raise e unless e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
+
+ @logger.debug("machine #{machine.name} not found #{e}.")
+ return nil
+ end
+
+ libvirt_domain
+ end
end
end
end