diff --git a/lib/fog/compute/models/libvirt/interface.rb b/lib/fog/compute/models/libvirt/interface.rb index 260d35b15..770712f73 100644 --- a/lib/fog/compute/models/libvirt/interface.rb +++ b/lib/fog/compute/models/libvirt/interface.rb @@ -12,7 +12,7 @@ module Fog attribute :xml_desc def save - raise Fog::Errors::Error.new('Creating a new interface is not yet implemented. Contributions welcome!') + raise Fog::Errors::Error.new('Creating a new interface is not yet implemented. Contributions welcome!') end def destroy diff --git a/lib/fog/compute/models/libvirt/network.rb b/lib/fog/compute/models/libvirt/network.rb index cc0d7c5d0..97eccdd03 100644 --- a/lib/fog/compute/models/libvirt/network.rb +++ b/lib/fog/compute/models/libvirt/network.rb @@ -28,7 +28,7 @@ module Fog end def save - raise Fog::Errors::Error.new('Creating a new network is not yet implemented. Contributions welcome!') + raise Fog::Errors::Error.new('Creating a new network is not yet implemented. Contributions welcome!') end def destroy() diff --git a/lib/fog/compute/models/libvirt/pools.rb b/lib/fog/compute/models/libvirt/pools.rb index 9511ff84f..e8fc70737 100644 --- a/lib/fog/compute/models/libvirt/pools.rb +++ b/lib/fog/compute/models/libvirt/pools.rb @@ -50,7 +50,7 @@ module Fog def get_by_name(name) pool=connection.lookup_storage_pool_by_name(name) return pool -# new(:raw => pool) + # new(:raw => pool) end end #class diff --git a/lib/fog/compute/models/libvirt/server.rb b/lib/fog/compute/models/libvirt/server.rb index 521179965..4dbd1abf7 100644 --- a/lib/fog/compute/models/libvirt/server.rb +++ b/lib/fog/compute/models/libvirt/server.rb @@ -69,28 +69,28 @@ module Fog # Network options :interface_type => "nat", #or "bridge" - :nat_network_name => "default", - :bridge_name => "br0", + :nat_network_name => "default", + :bridge_name => "br0", - # Disk options - :disk_type => "raw", - :disk_size => 10, - :disk_size_unit => "G", - :disk_allocate => 1, - :disk_allocate_unit => "G", - :disk_extension => "img", - :disk_template_name => nil, - :poolname => nil, + # Disk options + :disk_type => "raw", + :disk_size => 10, + :disk_size_unit => "G", + :disk_allocate => 1, + :disk_allocate_unit => "G", + :disk_extension => "img", + :disk_template_name => nil, + :poolname => nil, - # DVD options - :iso_file => nil , - :iso_dir => "/var/lib/libvirt/images/" + # DVD options + :iso_file => nil , + :iso_dir => "/var/lib/libvirt/images/" } template_options2=template_defaults.merge(template_options) template_options={ - :disk_name => "#{template_options2[:name]}.#{template_options2[:disk_extension]}" + :disk_name => "#{template_options2[:name]}.#{template_options2[:disk_extension]}" }.merge(template_options2) validate_template_options(template_options) @@ -116,118 +116,118 @@ module Fog # This gets passed to the domain to know the path of the disk template_options[:disk_path]=volume.path - end - - xml=xml_from_template(template_options) - end - # We either now have xml provided by the user or generated by the template - if !xml.nil? - domain=nil - if create_persistent - domain=connection.define_domain_xml(xml) - else - domain=connection.create_domain_xml(xml) - end - self.raw=domain + xml=xml_from_template(template_options) + + end + + # We either now have xml provided by the user or generated by the template + if !xml.nil? + domain=nil + if create_persistent + domain=connection.define_domain_xml(xml) + else + domain=connection.create_domain_xml(xml) + end + self.raw=domain + end + end + + def validate_template_options(template_options) + #if template_options[:disk_template_name].nil? + # raise Fog::Errors::Error.new('In order to make the disk boot, we require a template volume we can clone') + #end + unless template_options[:interface_type].nil? + raise Fog::Errors::Error.new("#{template_options[:interface_type]} is not a supported interface type") unless ["nat", "bridge"].include?(template_options[:interface_type]) + end + + end + + def xml_from_template(template_options) + + # We only want specific variables for ERB + 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 + end + + def username + @username ||= 'root' + end + + def start + requires :raw + + unless @raw.active? + begin + @raw.create + true + rescue + false end end + end - def validate_template_options(template_options) - #if template_options[:disk_template_name].nil? - # raise Fog::Errors::Error.new('In order to make the disk boot, we require a template volume we can clone') - #end - unless template_options[:interface_type].nil? - raise Fog::Errors::Error.new("#{template_options[:interface_type]} is not a supported interface type") unless ["nat", "bridge"].include?(template_options[:interface_type]) - end + def destroy(options={ :destroy_volumes => false}) - end - - def xml_from_template(template_options) - - # We only want specific variables for ERB - 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 - end - - def username - @username ||= 'root' - end - - def start - requires :raw - - unless @raw.active? - begin - @raw.create - true - rescue - false - end - end - end - - def destroy(options={ :destroy_volumes => false}) - - #connection.volumes(name).destroy - requires :raw - if @raw.active? - @raw.destroy - end - @raw.undefine - end - - - def reboot - requires :raw - - @raw.reboot - end - - def halt - requires :raw - - @raw.halt - end - - def poweroff - requires :raw + #connection.volumes(name).destroy + requires :raw + if @raw.active? @raw.destroy end + @raw.undefine + end - def shutdown - requires :raw - @raw.shutdown - end + def reboot + requires :raw - def resume - requires :raw + @raw.reboot + end - @raw.resume - end + def halt + requires :raw - def suspend - requires :raw + @raw.halt + end - @raw.suspend - end + def poweroff + requires :raw + @raw.destroy + end - def state - state=case @raw.info.state - when 0 then :nostate - when 1 then :running - when 2 then :paused - when 3 then :shuttingdown - when 4 then :shutoff - when 5 then :crashed - end + def shutdown + requires :raw + + @raw.shutdown + end + + def resume + requires :raw + + @raw.resume + end + + def suspend + requires :raw + + @raw.suspend + end + + def state + state=case @raw.info.state + when 0 then :nostate + when 1 then :running + when 2 then :paused + when 3 then :shuttingdown + when 4 then :shutoff + when 5 then :crashed + end return state end @@ -236,218 +236,218 @@ module Fog end - def stop - requires :raw + def stop + requires :raw - @raw.shutdown - end + @raw.shutdown + end - def xml_desc - requires :raw - raw.xml_desc - end + def xml_desc + requires :raw + raw.xml_desc + end - ##Note this requires arpwatch to be running - ##and chmod o+x /var/lib/arpwatch + ##Note this requires arpwatch to be running + ##and chmod o+x /var/lib/arpwatch - def addresses - mac=self.mac - ipaddress=nil - if @connection.uri.ssh_enabled? - #command="arp -an|grep #{mac}|cut -d ' ' -f 2| cut -d '(' -f 2| cut -d ')' -f 1" - #command="grep #{mac} /var/log/daemon.log |sed -e 's/^.*address //'|cut -d ' ' -f 1" - # TODO: check if this files exists - # Check if it is readable - command="grep #{mac} /var/log/arpwatch.log |cut -d ':' -f 4-| cut -d ' ' -f 4" -# command="grep #{mac} /var/lib/arpwatch/arp.dat|cut -f 2|tail -1" + def addresses + mac=self.mac + ipaddress=nil + if @connection.uri.ssh_enabled? + #command="arp -an|grep #{mac}|cut -d ' ' -f 2| cut -d '(' -f 2| cut -d ')' -f 1" + #command="grep #{mac} /var/log/daemon.log |sed -e 's/^.*address //'|cut -d ' ' -f 1" + # TODO: check if this files exists + # Check if it is readable + command="grep #{mac} /var/log/arpwatch.log |cut -d ':' -f 4-| cut -d ' ' -f 4" + # command="grep #{mac} /var/lib/arpwatch/arp.dat|cut -f 2|tail -1" - # TODO: we need to take the time into account, when IP's are re-allocated, we might be executing - # On the wrong host + # TODO: we need to take the time into account, when IP's are re-allocated, we might be executing + # On the wrong host - # We can get the host, the - user=connection.uri.user #could be nil - host=connection.uri.host - keyfile=connection.uri.keyfile - port=connection.uri.port + # We can get the host, the + user=connection.uri.user #could be nil + host=connection.uri.host + keyfile=connection.uri.keyfile + port=connection.uri.port - options={} - options[:keys]=[ keyfile ] unless keyfile.nil? - options[:port]=port unless keyfile.nil? - options[:paranoid]=true if connection.uri.no_verify? + options={} + options[:keys]=[ keyfile ] unless keyfile.nil? + options[:port]=port unless keyfile.nil? + options[:paranoid]=true if connection.uri.no_verify? - result=Fog::SSH.new(host, user, options).run(command) - if result.first.status == 0 - ipaddress=result.first.stdout.strip - #TODO check for valid IP - #TODO check time validity - else - # We couldn't retrieve any IP information - return { :public => nil , :private => nil} - end + result=Fog::SSH.new(host, user, options).run(command) + if result.first.status == 0 + ipaddress=result.first.stdout.strip + #TODO check for valid IP + #TODO check time validity else - # TODO for locat execute - #No ssh just do it locally - #cat /var/log/daemon.log|grep "52:54:00:52:f6:22"| - # or local execute arp -an to get the ip (as a last resort) - + # We couldn't retrieve any IP information + return { :public => nil , :private => nil} end - return { :public => [ipaddress], :private => [ipaddress]} - end - - def private_ip_address - ip_address(:private) - end - - def public_ip_address - ip_address(:public) - end - - def ip_address(key) - ips=addresses[key] - unless ips.nil? - return ips.first - else - return nil - end - end - - def private_key_path - @private_key_path ||= Fog.credentials[:private_key_path] - @private_key_path &&= File.expand_path(@private_key_path) - end - - def private_key - @private_key ||= private_key_path && File.read(private_key_path) - end - - def public_key_path - @public_key_path ||= Fog.credentials[:public_key_path] - @public_key_path &&= File.expand_path(@public_key_path) - end - - def public_key - @public_key ||= public_key_path && File.read(public_key_path) - end - - def ssh(commands) - requires :public_ip_address, :username - - #requires :password, :private_key - ssh_options={} - ssh_options[:password] = password unless password.nil? - ssh_options[:key_data] = [private_key] if private_key - ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil? - - Fog::SSH.new(public_ip_address, @username, ssh_options).run(commands) + else + # TODO for locat execute + #No ssh just do it locally + #cat /var/log/daemon.log|grep "52:54:00:52:f6:22"| + # or local execute arp -an to get the ip (as a last resort) end + return { :public => [ipaddress], :private => [ipaddress]} + end + def private_ip_address + ip_address(:private) + end - def ssh_proxy - proxy=nil - if @connection.uri.ssh_enabled? - relay=connection.uri.host - user_string="" - user_string="-l #{connection.uri.user}" unless connection.uri.user.nil? - proxy = Net::SSH::Proxy::Command.new("ssh #{user_string} "+relay+" nc %h %p") - return proxy - else - return nil - # This is a direct connection, so we don't need a proxy to be set - end + def public_ip_address + ip_address(:public) + end + + def ip_address(key) + ips=addresses[key] + unless ips.nil? + return ips.first + else + return nil end + end - # Transfers a file - def scp(local_path, remote_path, upload_options = {}) - requires :public_ip_address, :username + def private_key_path + @private_key_path ||= Fog.credentials[:private_key_path] + @private_key_path &&= File.expand_path(@private_key_path) + end - scp_options = {} - scp_options[:password] = password unless self.password.nil? - scp_options[:key_data] = [private_key] if self.private_key - scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil? + def private_key + @private_key ||= private_key_path && File.read(private_key_path) + end - Fog::SCP.new(public_ip_address, username, scp_options).upload(local_path, remote_path, upload_options) - end + def public_key_path + @public_key_path ||= Fog.credentials[:public_key_path] + @public_key_path &&= File.expand_path(@public_key_path) + end + def public_key + @public_key ||= public_key_path && File.read(public_key_path) + end - # Sets up a new key - def setup(credentials = {}) - requires :public_key, :public_ip_address, :username - require 'multi_json' + def ssh(commands) + requires :public_ip_address, :username - credentials[:proxy]= ssh_proxy unless ssh_proxy.nil? - credentials[:password] = password unless self.password.nil? - credentails[:key_data] = [private_key] if self.private_key - - commands = [ - %{mkdir .ssh}, -# %{passwd -l #{username}}, #Not sure if we need this here -# %{echo "#{MultiJson.encode(attributes)}" >> ~/attributes.json} - ] - if public_key - commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys} - end - - # wait for domain to be ready - Timeout::timeout(360) do - begin - Timeout::timeout(8) do - Fog::SSH.new(public_ip_address, username, credentials.merge(:timeout => 4)).run('pwd') - end - rescue Errno::ECONNREFUSED - sleep(2) - retry - rescue Net::SSH::AuthenticationFailed, Timeout::Error - retry - end - end - Fog::SSH.new(public_ip_address, username, credentials).run(commands) - end - - 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 - - - private - - def raw - @raw - end - - def raw=(new_raw) - @raw = new_raw - - raw_attributes = { - :uuid => new_raw.uuid, - :name => new_raw.name, - :memory_size => new_raw.info.max_mem, - :cpus => new_raw.info.nr_virt_cpu, - :os_type => new_raw.os_type - } - - merge_attributes(raw_attributes) - end - - - # finds a value from xml - def document path, attribute=nil - xml = REXML::Document.new(xml_desc) - attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute] - end + #requires :password, :private_key + ssh_options={} + ssh_options[:password] = password unless password.nil? + ssh_options[:key_data] = [private_key] if private_key + ssh_options[:proxy]= ssh_proxy unless ssh_proxy.nil? + Fog::SSH.new(public_ip_address, @username, ssh_options).run(commands) end - end - end + def ssh_proxy + proxy=nil + if @connection.uri.ssh_enabled? + relay=connection.uri.host + user_string="" + user_string="-l #{connection.uri.user}" unless connection.uri.user.nil? + proxy = Net::SSH::Proxy::Command.new("ssh #{user_string} "+relay+" nc %h %p") + return proxy + else + return nil + # This is a direct connection, so we don't need a proxy to be set + end + end + + # Transfers a file + def scp(local_path, remote_path, upload_options = {}) + requires :public_ip_address, :username + + scp_options = {} + scp_options[:password] = password unless self.password.nil? + scp_options[:key_data] = [private_key] if self.private_key + scp_options[:proxy]= ssh_proxy unless self.ssh_proxy.nil? + + Fog::SCP.new(public_ip_address, username, scp_options).upload(local_path, remote_path, upload_options) + end + + + # Sets up a new key + def setup(credentials = {}) + requires :public_key, :public_ip_address, :username + require 'multi_json' + + credentials[:proxy]= ssh_proxy unless ssh_proxy.nil? + credentials[:password] = password unless self.password.nil? + credentails[:key_data] = [private_key] if self.private_key + + commands = [ + %{mkdir .ssh}, + # %{passwd -l #{username}}, #Not sure if we need this here + # %{echo "#{MultiJson.encode(attributes)}" >> ~/attributes.json} + ] + if public_key + commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys} + end + + # wait for domain to be ready + Timeout::timeout(360) do + begin + Timeout::timeout(8) do + Fog::SSH.new(public_ip_address, username, credentials.merge(:timeout => 4)).run('pwd') + end + rescue Errno::ECONNREFUSED + sleep(2) + retry + rescue Net::SSH::AuthenticationFailed, Timeout::Error + retry + end + end + Fog::SSH.new(public_ip_address, username, credentials).run(commands) + end + + 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 + + + private + + def raw + @raw + end + + def raw=(new_raw) + @raw = new_raw + + raw_attributes = { + :uuid => new_raw.uuid, + :name => new_raw.name, + :memory_size => new_raw.info.max_mem, + :cpus => new_raw.info.nr_virt_cpu, + :os_type => new_raw.os_type + } + + merge_attributes(raw_attributes) + end + + + # finds a value from xml + def document path, attribute=nil + xml = REXML::Document.new(xml_desc) + attribute.nil? ? xml.elements[path].text : xml.elements[path].attributes[attribute] + end + + + end + + end end + +end diff --git a/lib/fog/compute/models/libvirt/servers.rb b/lib/fog/compute/models/libvirt/servers.rb index be6857094..8062aeb3d 100644 --- a/lib/fog/compute/models/libvirt/servers.rb +++ b/lib/fog/compute/models/libvirt/servers.rb @@ -53,14 +53,14 @@ module Fog def get_by_uuid(uuid) server=connection.lookup_domain_by_uuid(uuid) return server -# new(:raw => machine) + # new(:raw => machine) end # Retrieve the server by name def get_by_name(name) server=connection.lookup_domain_by_name(name) return server -# new(:raw => machine) + # new(:raw => machine) end end #class diff --git a/lib/fog/compute/models/libvirt/uri.rb b/lib/fog/compute/models/libvirt/uri.rb index aa28479b6..6ef1f1565 100644 --- a/lib/fog/compute/models/libvirt/uri.rb +++ b/lib/fog/compute/models/libvirt/uri.rb @@ -82,14 +82,14 @@ module Fog end def no_verify? - no_verify=value("no_verify") - return false if no_verify.nil? + no_verify=value("no_verify") + return false if no_verify.nil? - if no_verify.to_s=="0" - return false - else - return true - end + if no_verify.to_s=="0" + return false + else + return true + end end def verify? diff --git a/lib/fog/compute/models/libvirt/volume.rb b/lib/fog/compute/models/libvirt/volume.rb index 24ff50ad9..c1e6506ab 100644 --- a/lib/fog/compute/models/libvirt/volume.rb +++ b/lib/fog/compute/models/libvirt/volume.rb @@ -19,7 +19,7 @@ module Fog attribute :xml attribute :template_options -# attribute :key + # attribute :key attribute :path attribute :name attribute :capacity @@ -43,7 +43,7 @@ module Fog if first_pool.nil? raise Fog::Errors::Error.new('We could not find a pool called "default" and there was no other pool defined') else - default_pool_name=first_pool.name + default_pool_name=first_pool.name end end @@ -54,8 +54,8 @@ module Fog # Takes a pool and either uses :xml or :template_options->xml to create the volume def save -# requires :xml -# requires :poolname + # requires :xml + # requires :poolname if poolname # :disk_type => "raw", @@ -100,80 +100,80 @@ module Fog end - def validate_template_options(template_options) - # Here we can validate the template_options - end + def validate_template_options(template_options) + # Here we can validate the template_options + end - def xml_from_template(template_options) + def xml_from_template(template_options) - # We only want specific variables for ERB + # We only want specific variables for ERB - # we can't use an option of name type - # This clashes with ruby 1.8 Erb.type which is equivalent of .class - new_template_options={:vol_type => template_options[:type]}.merge(template_options) + # we can't use an option of name type + # This clashes with ruby 1.8 Erb.type which is equivalent of .class + new_template_options={:vol_type => template_options[:type]}.merge(template_options) - vars = ErbBinding.new(template_options) - template_path=File.join(File.dirname(__FILE__),"templates","volume.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 - end + vars = ErbBinding.new(template_options) + template_path=File.join(File.dirname(__FILE__),"templates","volume.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 + end - # Destroy a volume - def destroy - requires :raw - raw.delete - true - end + # Destroy a volume + def destroy + requires :raw + raw.delete + true + end - # Wipes a volume , zeroes disk - def wipe - requires :raw - raw.wipe - true - end + # Wipes a volume , zeroes disk + def wipe + requires :raw + raw.wipe + true + end - # Clones this volume to the name provided - def clone(name) - pool=@raw.pool - xml = REXML::Document.new(xml_desc) - xml.root.elements['/volume/name'].text=name - xml.root.elements['/volume/key'].text=name - xml.delete_element('/volume/target/path') - pool.create_volume_xml_from(xml.to_s,@raw) - return connection.volumes.all(:name => name).first - end + # Clones this volume to the name provided + def clone(name) + pool=@raw.pool + xml = REXML::Document.new(xml_desc) + xml.root.elements['/volume/name'].text=name + xml.root.elements['/volume/key'].text=name + xml.delete_element('/volume/target/path') + pool.create_volume_xml_from(xml.to_s,@raw) + return connection.volumes.all(:name => name).first + end - def xml_desc - requires :raw - raw.xml_desc - end + def xml_desc + requires :raw + raw.xml_desc + end - private - def raw - @raw - end + private + def raw + @raw + end - def raw=(new_raw) - @raw = new_raw + def raw=(new_raw) + @raw = new_raw - raw_attributes = { - :key => new_raw.key, - :path => new_raw.path, - :name => new_raw.name, - :allocation => new_raw.info.allocation, - :capacity => new_raw.info.capacity, - :type => new_raw.info.type - } - - merge_attributes(raw_attributes) - end + raw_attributes = { + :key => new_raw.key, + :path => new_raw.path, + :name => new_raw.name, + :allocation => new_raw.info.allocation, + :capacity => new_raw.info.capacity, + :type => new_raw.info.type + } + merge_attributes(raw_attributes) end end - end + end end + +end