Parent

Included Modules

Files

Class/Module Index [+]

Quicksearch

Fog::Compute::Libvirt::Server

Attributes

iso_dir[RW]

The following attributes are only needed when creating a new vm

iso_file[RW]

The following attributes are only needed when creating a new vm

network_bridge_name[RW]
network_interface_type[RW]
network_nat_network[RW]
password[RW]
private_key[W]
private_key_path[W]
public_key[W]
public_key_path[W]
username[W]
volume_allocation[RW]
volume_capacity[RW]
volume_format_type[RW]
volume_name[RW]
volume_path[RW]
volume_pool_name[RW]
volume_template_name[RW]

Public Class Methods

new(attributes={} ) click to toggle source

Can be created by passing in :xml => "<xml to create domain/server>" or by providing :template_options => {

             :name => "", :cpus => 1, :memory_size => 256 , :volume_template
:}

@returns server/domain created

# File lib/fog/libvirt/models/compute/server.rb, line 49
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]

  super
end

Public Instance Methods

addresses(options={}) click to toggle source

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

# File lib/fog/libvirt/models/compute/server.rb, line 283
def addresses(options={})
  mac=self.mac

  # Aug 24 17:34:41 juno arpwatch: new station 10.247.4.137 52:54:00:88:5a:0a eth0.4
  # Aug 24 17:37:19 juno arpwatch: changed ethernet address 10.247.4.137 52:54:00:27:33:00 (52:54:00:88:5a:0a) eth0.4
  # Check if another ip_command string was provided
  ip_command_global=@connection.ip_command.nil? ? 'grep $mac /var/log/arpwatch.log|sed -e "s/new station//"|sed -e "s/changed ethernet address//g" |sed -e "s/reused old ethernet //" |tail -1 |cut -d ":" -f 4-| cut -d " " -f 3' : @connection.ip_command
  ip_command_local=options[:ip_command].nil? ? ip_command_global : options[:ip_command]

  ip_command="mac=#{mac}; server_name=#{name}; "+ip_command_local

  ip_address=nil

  if @connection.uri.ssh_enabled?

    # Retrieve the parts we need from the connection to setup our ssh options
    user=connection.uri.user #could be nil
    host=connection.uri.host
    keyfile=connection.uri.keyfile
    port=connection.uri.port

    # Setup the options
    ssh_options={}
    ssh_options[:keys]=[ keyfile ] unless keyfile.nil?
    ssh_options[:port]=port unless keyfile.nil?
    ssh_options[:paranoid]=true if connection.uri.no_verify?

    # TODO: we need to take the time into account, when IP's are re-allocated, we might be executing
    # On the wrong host

    begin
      result=Fog::SSH.new(host, user, ssh_options).run(ip_command)
    rescue Errno::ECONNREFUSED
      raise Fog::Errors::Error.new("Connection was refused to host #{host} to retrieve the ip_address for #{mac}")
    rescue Net::SSH::AuthenticationFailed
      raise Fog::Errors::Error.new("Error authenticating over ssh to host #{host} and user #{user}")
    end

    #TODO: We currently just retrieve the ip address through the ip_command
    #TODO: We need to check if that ip_address is still valid for that mac-address

    # Check for a clean exit code
    if result.first.status == 0
      ip_address=result.first.stdout.strip
    else
      # We got a failure executing the command
      raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
    end

  else
    # It's not ssh enabled, so we assume it is
    if @connection.uri.transport=="tls"
      raise Fog::Errors::Error.new("TlS remote transport is not currently supported, only ssh")
    end

    # Execute the ip_command locally
    # Initialize empty ip_address string
    ip_address=""

    IO.popen("#{ip_command}") do |p|
      p.each_line do |l|
        ip_address+=l
      end
      status=Process.waitpid2(p.pid)[1].exitstatus
      if status!=0
        raise Fog::Errors::Error.new("The command #{ip_command} failed to execute with a clean exit code")
      end
    end

    #Strip any new lines from the string
    ip_address=ip_address.chomp
  end


  # The Ip-address command has been run either local or remote now

  if ip_address==""
    #The grep didn't find an ip address result"
    ip_address=nil
  else
    # To be sure that the command didn't return another random string
    # We check if the result is an actual ip-address
    # otherwise we return nil
    unless ip_address=~/^(\d{1,3}\.){3}\d{1,3}$/
      raise Fog::Errors::Error.new(
        "The result of #{ip_command} does not have valid ip-address format\n"+
        "Result was: #{ip_address}\n"
    )
    end
  end

  return { :public => [ip_address], :private => [ip_address]}
end
create_or_clone_volume() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 108
def create_or_clone_volume

  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

  # Check if a disk template was specified
  unless self.volume_template_name.nil?

    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

    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]}")

    # This gets passed to the domain to know the path of the disk
    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?

    begin
      volume=connection.volumes.create(volume_options)
      self.volume_path=volume.path
      self.volume_format_type=volume.format_type unless self.volume_format_type
    rescue
      raise Fog::Errors::Error.new("Error creating the volume : #{$!}")
    end

  end
end
destroy(options={ :destroy_volumes => false}) click to toggle source

In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine

# File lib/fog/libvirt/models/compute/server.rb, line 203
def destroy(options={ :destroy_volumes => false})
  requires :raw
  if @raw.active?
    @raw.destroy
  end
  @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
  end
end
halt() click to toggle source

Alias for poweroff

# File lib/fog/libvirt/models/compute/server.rb, line 224
def halt
   poweroff
end
ip_address(key) click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 385
def ip_address(key)
  ips=addresses[key]
  unless ips.nil?
    return ips.first
  else
    return nil
  end
end
mac() click to toggle source

Retrieves the mac address from parsing the XML of the domain

# File lib/fog/libvirt/models/compute/server.rb, line 488
def mac
  mac = document("domain/devices/interface/mac", "address")
  return mac
end
poweroff() click to toggle source

In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine

# File lib/fog/libvirt/models/compute/server.rb, line 230
def poweroff
  requires :raw
  @raw.destroy
end
private_ip_address() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 377
def private_ip_address
  ip_address(:private)
end
private_key() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 399
def private_key
  @private_key ||= private_key_path && File.read(private_key_path)
end
private_key_path() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 394
def private_key_path
  @private_key_path ||= Fog.credentials[:private_key_path]
  @private_key_path &&= File.expand_path(@private_key_path)
end
public_ip_address() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 381
def public_ip_address
  ip_address(:public)
end
public_key() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 408
def public_key
  @public_key ||= public_key_path && File.read(public_key_path)
end
public_key_path() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 403
def public_key_path
  @public_key_path ||= Fog.credentials[:public_key_path]
  @public_key_path &&= File.expand_path(@public_key_path)
end
ready?() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 263
def ready?
  state == "running"
end
reboot() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 218
def reboot
  requires :raw
  @raw.reboot
end
resume() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 240
def resume
  requires :raw
  @raw.resume
end
save() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 80
def save

  raise Fog::Errors::Error.new('Resaving an existing server may create a duplicate') if uuid

  validate_template_options

  xml=xml_from_template if xml.nil?

  create_or_clone_volume

  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
    end
  rescue
    raise Fog::Errors::Error.new("Error saving the server: #{$!}")
  end
end
scp(local_path, remote_path, upload_options = {}) click to toggle source

Transfers a file

# File lib/fog/libvirt/models/compute/server.rb, line 441
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
setup(credentials = {}) click to toggle source

Sets up a new key

# File lib/fog/libvirt/models/compute/server.rb, line 454
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
shutdown() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 235
def shutdown
  requires :raw
  @raw.shutdown
end
ssh(commands) click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 412
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)

end
ssh_proxy() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 426
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
start() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 188
def start
  requires :raw

  unless @raw.active?
    begin
      @raw.create
      true
    rescue
      false
    end
  end
end
stop() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 267
def stop
  requires :raw

  @raw.shutdown
end
suspend() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 245
def suspend
  requires :raw
  @raw.suspend
end
to_fog_state(raw_state) click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 250
def to_fog_state(raw_state)
  state=case raw_state
        when 0 then "nostate"
        when 1 then "running"
        when 2 then "blocked"
        when 3 then "paused"
        when 4 then "shutting-down"
        when 5 then "shutoff"
        when 6 then "crashed"
        end
  return state
end
username() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 184
def username
  @username ||= 'root'
end
validate_template_options() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 152
def validate_template_options
  unless self.network_interface_type.nil?
    raise Fog::Errors::Error.new("#{self.network_interface_type} is not a supported interface type") unless ["nat", "bridge"].include?(self.network_interface_type)
  end
end
vnc_port() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 493
def vnc_port

  port = document("domain/devices/graphics[@type='vnc']", "port")
  return port
end
xml_from_template() click to toggle source
# File lib/fog/libvirt/models/compute/server.rb, line 158
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
  }
  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

[Validate]

Generated with the Darkfish Rdoc Generator 2.