From 73ac4553bc60f89f800e207fab0ec54031ae9a29 Mon Sep 17 00:00:00 2001 From: Ohad Levy Date: Thu, 19 Jan 2012 15:41:23 +0200 Subject: [PATCH] first cut of cleaning up libvirt server class This patch tries not to change any functioanlity, rather just reoginize the code. --- lib/fog/libvirt/models/compute/server.rb | 187 +++++++++++------------ lib/fog/libvirt/models/compute/util.rb | 2 +- 2 files changed, 86 insertions(+), 103 deletions(-) diff --git a/lib/fog/libvirt/models/compute/server.rb b/lib/fog/libvirt/models/compute/server.rb index 1ba81e8d5..2bb7dd4a0 100644 --- a/lib/fog/libvirt/models/compute/server.rb +++ b/lib/fog/libvirt/models/compute/server.rb @@ -48,31 +48,10 @@ module Fog # @returns server/domain created def initialize(attributes={} ) - self.xml ||= nil unless attributes[:xml] - self.persistent ||=true unless attributes[:persistent] - self.cpus ||=1 unless attributes[:cpus] - self.memory_size ||=256 *1024 unless attributes[:memory_size] - self.name ||="fog-#{SecureRandom.random_number*10E14.to_i.round}" unless attributes[:name] - - self.os_type ||="hvm" unless attributes[:os_type] - self.arch ||="x86_64" unless attributes[:arch] - - self.domain_type ||="kvm" unless attributes[:domain_type] - - self.iso_file ||=nil unless attributes[:iso_file] - self.iso_dir ||="/var/lib/libvirt/images" unless attributes[:iso_dir] - - self.volume_format_type ||=nil unless attributes[:volume_format_type] - self.volume_capacity ||=nil unless attributes[:volume_capacity] - self.volume_allocation ||=nil unless attributes[:volume_allocation] - - self.volume_name ||=nil unless attributes[:volume_name] - self.volume_pool_name ||=nil unless attributes[:volume_pool_name] - self.volume_template_name ||=nil unless attributes[:volume_template_name] - - self.network_interface_type ||="nat" unless attributes[:network_interface_type] - self.network_nat_network ||="default" unless attributes[:network_nat_network] - self.network_bridge_name ||="br0" unless attributes[:network_bridge_name] + # setup all attributes. + defaults.merge(attributes).each do |k,v| + eval("self.#{k}= v") if self.respond_to?("#{k}=") + end super end @@ -83,65 +62,55 @@ module Fog validate_template_options - xml=xml_from_template if xml.nil? + xml ||= xml_from_template create_or_clone_volume - xml=xml_from_template + xml = xml_from_template # We either now have xml provided by the user or generated by the template begin - if !xml.nil? - domain=nil - if self.persistent - domain=connection.raw.define_domain_xml(xml) - else - domain=connection.raw.create_domain_xml(xml) - end - self.raw=domain + if xml + self.raw = self.persistent ? connection.raw.define_domain_xml(xml) : connection.raw.create_domain_xml(xml) end rescue raise Fog::Errors::Error.new("Error saving the server: #{$!}") end end + #TODO move all of this to the volume class def create_or_clone_volume - volume_options=Hash.new + volume_options = Hash.new - unless self.volume_name.nil? - volume_options[:name]=self.volume_name - else - extension = self.volume_format_type.nil? ? "img" : self.volume_format_type - volume_name = "#{self.name}.#{extension}" - volume_options[:name]=volume_name - end + volume_options[:name] = volume_name || default_volume_name # Check if a disk template was specified unless self.volume_template_name.nil? - template_volumes=connection.volumes.all(:name => self.volume_template_name) + template_volumes = connection.volumes.all(:name => self.volume_template_name) - raise Fog::Errors::Error.new("Template #{self.volume_template_name} not found") unless template_volumes.length==1 + raise Fog::Errors::Error.new("Template #{self.volume_template_name} not found") unless template_volumes.empty? - orig_volume=template_volumes.first - self.volume_format_type=orig_volume.format_type unless self.volume_format_type - volume=orig_volume.clone("#{volume_options[:name]}") + orig_volume = template_volumes.first + volume = orig_volume.clone("#{volume_options[:name]}") + # if we cloned it, it has the original volume type. + self.volume_format_type = orig_volume.format_type # This gets passed to the domain to know the path of the disk - self.volume_path=volume.path + self.volume_path = volume.path else # If no template volume was given, let's create our own volume - volume_options[:format_type]=self.volume_format_type unless self.volume_format_type.nil? - volume_options[:capacity]=self.volume_capacity unless self.volume_capacity.nil? - volume_options[:allocation]=self.volume_allocation unless self.volume_allocation.nil? + volume_options[:format_type] = self.volume_format_type if volume_format_type + volume_options[:capacity] = self.volume_capacity if volume_capacity + volume_options[:allocation] = self.volume_allocation if volume_allocation begin - volume=connection.volumes.create(volume_options) - self.volume_path=volume.path - self.volume_format_type=volume.format_type unless self.volume_format_type + volume = connection.volumes.create(volume_options) + self.volume_path = volume.path + self.volume_format_type ||= volume.format_type rescue raise Fog::Errors::Error.new("Error creating the volume : #{$!}") end @@ -158,27 +127,27 @@ module Fog def xml_from_template template_options={ - :cpus => self.cpus, - :memory_size => self.memory_size, - :domain_type => self.domain_type, - :name => self.name, - :iso_file => self.iso_file, - :iso_dir => self.iso_dir, - :os_type => self.os_type, - :arch => self.arch, - :volume_path => self.volume_path, - :volume_format_type => self.volume_format_type, - :network_interface_type => self.network_interface_type, - :network_nat_network => self.network_nat_network, - :network_bridge_name => self.network_bridge_name + :cpus => cpus, + :memory_size => memory_size, + :domain_type => domain_type, + :name => name, + :iso_file => iso_file, + :iso_dir => iso_dir, + :os_type => os_type, + :arch => arch, + :volume_path => volume_path, + :volume_format_type => volume_format_type, + :network_interface_type => network_interface_type, + :network_nat_network => network_nat_network, + :network_bridge_name => network_bridge_name } - vars = ErbBinding.new(template_options) - template_path=File.join(File.dirname(__FILE__),"templates","server.xml.erb") - template=File.open(template_path).readlines.join - erb = ERB.new(template) - vars_binding = vars.send(:get_binding) - result=erb.result(vars_binding) - return result + vars = ErbBinding.new(template_options) + template_path = File.join(File.dirname(__FILE__),"templates","server.xml.erb") + template = File.open(template_path).readlines.join + erb = ERB.new(template) + vars_binding = vars.send(:get_binding) + + erb.result(vars_binding) end def username @@ -202,16 +171,13 @@ module Fog # In fog a destroy means the remove of a machine def destroy(options={ :destroy_volumes => false}) requires :raw - if @raw.active? - @raw.destroy - end + poweroff unless stopped? + #TODO: add handling of failure @raw.undefine + if options[:destroy_volumes] - disk_path = document("domain/devices/disk/source", "file") # volumes.all filters do not handle nil keys well - (connection.volumes.all(:path => disk_path) rescue []).each do |vol| - vol.destroy - end + connection.volumes.all(:path => disk_path).each { |vol| vol.destroy} end end @@ -222,7 +188,7 @@ module Fog # Alias for poweroff def halt - poweroff + poweroff end # In libvirt a destroy means a hard power-off of the domain @@ -257,7 +223,10 @@ module Fog when 5 then "shutoff" when 6 then "crashed" end - return state + end + + def stopped? + state == "shutdown" end def ready? @@ -266,20 +235,15 @@ module Fog def stop requires :raw - @raw.shutdown end - #def xml_desc - #requires :raw - #raw.xml_desc - #end - # This retrieves the ip address of the mac address # It returns an array of public and private ip addresses # Currently only one ip address is returned, but in the future this could be multiple # if the server has multiple network interface # + #TODO: move this into the util class def addresses(options={}) mac=self.mac @@ -487,21 +451,20 @@ module Fog # Retrieves the mac address from parsing the XML of the domain def mac mac = document("domain/devices/interface/mac", "address") - return mac end def vnc_port - port = document("domain/devices/graphics[@type='vnc']", "port") - return port end + def disk_path + document("domain/devices/disk/source", "file") + rescue + [] + end private - - def raw - @raw - end + attr_reader :raw def raw=(new_raw) @raw = new_raw @@ -523,13 +486,33 @@ module Fog merge_attributes(raw_attributes) end - - # finds a value from xml - def document path, attribute=nil - xml = REXML::Document.new(self.xml) - attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute] + def randomized_name + "fog-#{SecureRandom.random_number*10E14.to_i.round}" end + def default_iso_dir + "/var/lib/libvirt/images" + end + + def default_volume_name + "#{name}.#{volume_format_type || 'img'}" + end + + def defaults + { + :persistent => true, + :cpus => 1, + :memory_size => 256 *1024, + :name => randomized_name, + :os_type => "hvm", + :arch => "x86_64", + :domain_type => "kvm", + :iso_dir => default_iso_dir , + :network_interface_type => "nat", + :network_nat_network => "default", + :network_bridge_name => "br0" + } + end end diff --git a/lib/fog/libvirt/models/compute/util.rb b/lib/fog/libvirt/models/compute/util.rb index 06ef19c11..5ba3d82b1 100644 --- a/lib/fog/libvirt/models/compute/util.rb +++ b/lib/fog/libvirt/models/compute/util.rb @@ -9,7 +9,7 @@ module Fog # finds a value from xml def document path, attribute=nil return nil if new? - xml = REXML::Document.new(@xml_desc) + xml = REXML::Document.new(self.xml) attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute] end