Class: VagrantPlugins::ProviderLibvirt::Action::ResolveDiskSettings

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-libvirt/action/resolve_disk_settings.rb

Instance Method Summary collapse

Constructor Details

#initialize(app, _env) ⇒ ResolveDiskSettings

Returns a new instance of ResolveDiskSettings.



14
15
16
17
# File 'lib/vagrant-libvirt/action/resolve_disk_settings.rb', line 14

def initialize(app, _env)
  @logger = Log4r::Logger.new('vagrant_libvirt::action::resolve_disk_devices')
  @app = app
end

Instance Method Details

#call(env) ⇒ Object



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
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
# File 'lib/vagrant-libvirt/action/resolve_disk_settings.rb', line 19

def call(env)
  # Get config.
  config = env[:machine].provider_config

  domain_name = env[:domain_name] # only set on create
  disk_bus = config.disk_bus
  disk_device = config.disk_device
  disk_address_type = config.disk_address_type
  domain_volume_cache = config.volume_cache || 'default'

  # Storage
  storage_pool_name = config.storage_pool_name
  snapshot_pool_name = config.snapshot_pool_name
  domain_volumes = []
  disks = config.disks.dup

  resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new(disk_device[0..1])

  # Get path to domain image from the storage pool selected if we have a box.
  if env[:machine].config.vm.box
    pool_name = if snapshot_pool_name == storage_pool_name
                  storage_pool_name
                else
                  snapshot_pool_name
                end

    if env[:box_volumes].nil?
      # domain must be already created, need to read domain volumes from domain XML
      libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
        env[:machine].id
      )
      domain_xml = libvirt_domain.xml_desc(1)
      xml_descr = REXML::Document.new(domain_xml)
      domain_name = xml_descr.elements['domain'].elements['name'].text
      disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
      have_aliases = !REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first.nil?
      env[:ui].warn(I18n.t('vagrant_libvirt.domain_xml.obsolete_method')) unless have_aliases

      if have_aliases
        REXML::XPath.match(disks_xml,
                           './alias[contains(@name, "ua-box-volume-")]').each_with_index do |alias_xml, idx|
          domain_volumes.push(volume_from_xml(alias_xml.parent, domain_name, idx))
        end
      else
        # fallback to try and infer which boxes are box images, as they are listed first
        # as soon as there is no match, can exit
        disks_xml.each_with_index do |box_disk_xml, idx|
          diskname = box_disk_xml.elements['source'].attributes['file'].rpartition('/').last

          break if volume_name(domain_name, idx) != diskname

          domain_volumes.push(volume_from_xml(box_disk_xml, domain_name, idx))
        end
      end
    else

      @logger.debug "Search for volumes in pool: #{pool_name}"
      env[:box_volumes].each_index do |index|
        domain_volume = env[:machine].provider.driver.connection.volumes.all(
          name: volume_name(domain_name, index)
        ).find { |x| x.pool_name == pool_name }
        raise Errors::NoDomainVolume if domain_volume.nil?

        domain_volumes.push(
          {
            name: volume_name(domain_name, index),
            device: env[:box_volumes][index][:device],
            cache: domain_volume_cache,
            bus: disk_bus,
            address_type: disk_address_type,
            absolute_path: domain_volume.path,
            virtual_size: env[:box_volumes][index][:virtual_size],
            pool: pool_name,
          }
        )
      end
    end

    resolver.resolve!(domain_volumes)

    # If we have a box, take the path from the domain volume and set our storage_prefix.
    # If not, we dump the storage pool xml to get its defined path.
    # the default storage prefix is typically: /var/lib/libvirt/images/
    storage_prefix = "#{File.dirname(domain_volumes[0][:absolute_path])}/" # steal
  else
    if domain_name.nil?
      # Ensure domain name is set for subsequent steps if restarting a machine without a box
      libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
        env[:machine].id
      )
      domain_xml = libvirt_domain.xml_desc(1)
      xml_descr = REXML::Document.new(domain_xml)
      domain_name = xml_descr.elements['domain'].elements['name'].text
    end

    storage_prefix = get_disk_storage_prefix(env[:machine], storage_pool_name)
  end

  resolver.resolve!(disks)

  disks.each do |disk|
    disk[:path] ||= disk_name(domain_name, disk)

    # On volume creation, the <path> element inside <target>
    # is oddly ignored; instead the path is taken from the
    # <name> element:
    # http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
    disk[:name] = disk[:path]

    disk[:absolute_path] = storage_prefix + disk[:path]

    if disk[:pool].nil?
      disk[:pool] = storage_pool_name
    else
      @logger.debug "Overriding pool name with: #{disk[:pool]}"
      disk_storage_prefix = get_disk_storage_prefix(env[:machine], disk[:pool])
      disk[:absolute_path] = disk_storage_prefix + disk[:path]
      @logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
    end
  end

  env[:domain_volumes] = domain_volumes
  env[:disks] = disks

  @app.call(env)
end