Class: Gogetit::GogetLibvirt

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/providers/libvirt.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

#get_gateway, #ping_available?, #recognize_env, #ssh_available?, #symbolize_keys

Constructor Details

#initialize(conf, maas, logger) ⇒ GogetLibvirt

Returns a new instance of GogetLibvirt.



13
14
15
16
17
18
# File 'lib/providers/libvirt.rb', line 13

def initialize(conf, maas, logger)
  @config = conf
  @conn = Libvirt::open(config[:libvirt][:url])
  @maas = maas
  @logger = logger
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



11
12
13
# File 'lib/providers/libvirt.rb', line 11

def config
  @config
end

#connObject (readonly)

Returns the value of attribute conn.



11
12
13
# File 'lib/providers/libvirt.rb', line 11

def conn
  @conn
end

#loggerObject (readonly)

Returns the value of attribute logger.



11
12
13
# File 'lib/providers/libvirt.rb', line 11

def logger
  @logger
end

#maasObject (readonly)

Returns the value of attribute maas.



11
12
13
# File 'lib/providers/libvirt.rb', line 11

def maas
  @maas
end

Instance Method Details

#add_nic(document, nic_conf) ⇒ Object



212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/providers/libvirt.rb', line 212

def add_nic(document, nic_conf)
  logger.info("Calling <#{__method__.to_s}>")
  template = File.read(config[:lib_dir] + "/template/nic.xml")
  doc = Oga.parse_xml(template)

  nic_conf.each do |nic|
    doc = Oga.parse_xml(template)
    doc.at_xpath('interface/source').attribute('network').value = nic[:network]
    doc.at_xpath('interface/source').attribute('portgroup').value = nic[:portgroup]
    document.at_xpath('domain/devices').children << doc.at_xpath('interface')
  end

  document
end

#create(name, conf_file = nil) ⇒ Object

subject.create(name: ‘test01’)



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/providers/libvirt.rb', line 46

def create(name, conf_file = nil)
  logger.info("Calling <#{__method__.to_s}>")
  if maas.domain_name_exists?(name) or domain_exists?(name)
    puts "Domain #{name} already exists! Please check both on MAAS and libvirt."
    return false
  end

  conf_file ||= config[:default_provider_conf_file]
  domain = symbolize_keys(YAML.load_file(conf_file))
  domain[:name] = name
  domain[:uuid] = SecureRandom.uuid

  dom = conn.define_domain_xml(define_domain(domain))
  maas.refresh_pods

  system_id = maas.get_system_id(domain[:name])
  maas.wait_until_state(system_id, 'Ready')
  logger.info("Calling to deploy...")
  maas.conn.request(:post, ['machines', system_id], {'op' => 'deploy'})
  maas.wait_until_state(system_id, 'Deployed')
  logger.info("#{domain[:name]} has been created.")
  true
end

#create_volume(pool_name, volume_doc) ⇒ Object



205
206
207
208
209
210
# File 'lib/providers/libvirt.rb', line 205

def create_volume(pool_name, volume_doc)
  logger.info("Calling <#{__method__.to_s}> to create volume in #{pool_name} pool.")
  pool = conn.lookup_storage_pool_by_name(pool_name)
  pool.create_volume_xml(volume_doc)
  pool.refresh
end

#define_domain(domain) ⇒ Object



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
# File 'lib/providers/libvirt.rb', line 105

def define_domain(domain)
  logger.info("Calling <#{__method__.to_s}>")
  template = File.read(config[:lib_dir] + '/template/domain.xml')
  doc = Oga.parse_xml(template)

  name = domain[:name]
  doc.at_xpath('domain/name').inner_text = name
  uuid = domain[:uuid]
  doc.at_xpath('domain/uuid').inner_text = uuid
  vcpu = domain[:vcpu].to_s
  doc.at_xpath('domain/vcpu').inner_text = vcpu
  memory = domain[:memory].to_s
  doc.at_xpath('domain/memory').inner_text = memory
  doc.at_xpath('domain/currentMemory').inner_text = memory

  doc = define_volumes(doc, domain)
  doc = add_nic(doc, domain[:nic])

  #print_xml(doc)
  #volumes.each do |v|
  #  print_xml(v)
  #end

  return Oga::XML::Generator.new(doc).to_xml
end

#define_volumes(document, domain) ⇒ Object



156
157
158
159
160
161
162
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/providers/libvirt.rb', line 156

def define_volumes(document, domain)
  logger.info("Calling <#{__method__.to_s}>")
  disk_template = File.read(config[:lib_dir] + '/template/disk.xml')
  disk_doc = Oga.parse_xml(disk_template)
  volume_template = File.read(config[:lib_dir] + '/template/volume.xml')
  volume_doc = Oga.parse_xml(volume_template)

  defined_volumes = []

  # For root volume
  pool_path = get_pool_path(domain[:disk][:root][:pool])
  volume_name = "#{domain[:name]}_root_sda.qcow2"
  volume_file = pool_path + "/" + volume_name
  disk_doc.at_xpath('disk/source').attribute('file').value = volume_file
  document.at_xpath('domain/devices').children << disk_doc.at_xpath('disk')

  volume_doc.at_xpath('volume/name').inner_text = volume_name
  volume_doc.at_xpath('volume/target/path').inner_text = volume_file
  volume_doc.at_xpath('volume/capacity').inner_text = domain[:disk][:root][:capacity].to_s

  create_volume(domain[:disk][:root][:pool], Oga::XML::Generator.new(volume_doc).to_xml)
  defined_volumes << volume_doc

  # For data(secondary) volumes
  if domain[:disk][:data] != [] and domain[:disk][:data] != nil
    disk_index = 98
    domain[:disk][:data].each do |v|
      pool_path = get_pool_path(v[:pool])
      volume_index = "sd" + disk_index.chr
      volume_name = "#{domain[:name]}_data_#{volume_index}.qcow2"
      volume_file = pool_path + "/" + volume_name
      disk_doc = Oga.parse_xml(disk_template)
      disk_doc.at_xpath('disk/source').attribute('file').value = volume_file
      disk_doc.at_xpath('disk/target').attribute('dev').value = volume_index
      document.at_xpath('domain/devices').children << disk_doc.at_xpath('disk')

      volume_doc = Oga.parse_xml(volume_template)
      volume_doc.at_xpath('volume/name').inner_text = volume_name
      volume_doc.at_xpath('volume/target/path').inner_text = volume_file
      volume_doc.at_xpath('volume/capacity').inner_text = v[:capacity].to_s
      create_volume(v[:pool], Oga::XML::Generator.new(volume_doc).to_xml)
      defined_volumes << volume_doc
      disk_index += 1
    end
  end

  return document
end

#destroy(name) ⇒ Object



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
# File 'lib/providers/libvirt.rb', line 70

def destroy(name)
  logger.info("Calling <#{__method__.to_s}>")
  system_id = maas.get_system_id(name)
  if maas.machine_exists?(name)
    if maas.get_machine_state(system_id) == 'Deployed'
      logger.info("Calling to release...")
      maas.conn.request(:post, ['machines', system_id], {'op' => 'release'})
      maas.wait_until_state(system_id, 'Ready')
    end
    maas.conn.request(:delete, ['machines', system_id])
  end

  pools = []
  conn.list_storage_pools.each do |name|
    pools << self.conn.lookup_storage_pool_by_name(name)
  end

  dom = conn.lookup_domain_by_name(name)
  dom.destroy if dom.active?
  Oga.parse_xml(dom.xml_desc).xpath('domain/devices/disk/source').each do |d|
    pool_path = d.attribute('file').value.split('/')[0..2].join('/')
    pools.each do |p|
      if Oga.parse_xml(p.xml_desc).at_xpath('pool/target/path').inner_text == pool_path
        logger.info("Deleting volume in #{p.name} pool.")
        p.lookup_volume_by_name(d.attribute('file').value.split('/')[3]).delete
      end
    end
  end
  dom.undefine

  maas.refresh_pods
  logger.info("#{name} has been destroyed.")
  true
end

#domain_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
35
# File 'lib/providers/libvirt.rb', line 29

def domain_exists?(name)
  logger.info("Calling <#{__method__.to_s}>")
  get_domain_list.each do |d|
    return true if d == name
  end
  false
end

#get_domain_listObject



20
21
22
23
24
25
26
27
# File 'lib/providers/libvirt.rb', line 20

def get_domain_list
  logger.info("Calling <#{__method__.to_s}>")
  domains = []
  conn.list_all_domains.each do |d|
    domains << d.name
  end
  domains
end

#get_mac_addr(domain_name) ⇒ Object



37
38
39
40
41
42
43
# File 'lib/providers/libvirt.rb', line 37

def get_mac_addr(domain_name)
  logger.info("Calling <#{__method__.to_s}>")
   Oga.parse_xml(conn.lookup_domain_by_name(domain_name).xml_desc)
    .at_xpath('domain/devices/interface[1]/mac')
    .attribute('address')
    .value
end

#get_pool_path(pool) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/providers/libvirt.rb', line 139

def get_pool_path(pool)
  logger.info("Calling <#{__method__.to_s}>")
  path = nil
  conn.list_all_storage_pools.each do |p|
    if p.name == pool
      pool_doc = Oga.parse_xml(p.xml_desc)
      path = pool_doc.at_xpath('pool/target/path').inner_text
    end
  end

  if path
    return path
  else
    raise 'No such pool found.'
  end
end


131
132
133
134
135
136
137
# File 'lib/providers/libvirt.rb', line 131

def print_xml(doc)
  logger.info("Calling <#{__method__.to_s}>")
  output = REXML::Document.new(Oga::XML::Generator.new(doc).to_xml)
  formatter = REXML::Formatters::Pretty.new
  formatter.compact = true
  formatter.write(output, $stdout)
end