Class: Fog::Compute::Libvirt::Server
- Includes:
- Fog::Compute::LibvirtUtil
- Defined in:
- lib/fog/libvirt/models/compute/server.rb
Instance Attribute Summary collapse
-
#iso_dir ⇒ Object
The following attributes are only needed when creating a new vm.
-
#iso_file ⇒ Object
The following attributes are only needed when creating a new vm.
-
#network_bridge_name ⇒ Object
Returns the value of attribute network_bridge_name.
-
#network_interface_type ⇒ Object
Returns the value of attribute network_interface_type.
-
#network_nat_network ⇒ Object
Returns the value of attribute network_nat_network.
-
#password ⇒ Object
Returns the value of attribute password.
- #private_key ⇒ Object
- #private_key_path ⇒ Object
- #public_key ⇒ Object
- #public_key_path ⇒ Object
- #username ⇒ Object
-
#volume_allocation ⇒ Object
Returns the value of attribute volume_allocation.
-
#volume_capacity ⇒ Object
Returns the value of attribute volume_capacity.
-
#volume_format_type ⇒ Object
Returns the value of attribute volume_format_type.
-
#volume_name ⇒ Object
Returns the value of attribute volume_name.
-
#volume_path ⇒ Object
Returns the value of attribute volume_path.
-
#volume_pool_name ⇒ Object
Returns the value of attribute volume_pool_name.
-
#volume_template_name ⇒ Object
Returns the value of attribute volume_template_name.
Attributes inherited from Model
Instance Method Summary collapse
-
#addresses(options = {}) ⇒ Object
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.
-
#create_or_clone_volume ⇒ Object
TODO move all of this to the volume class.
-
#destroy(options = { :destroy_volumes => false}) ⇒ Object
In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine.
- #disk_path ⇒ Object
-
#halt ⇒ Object
Alias for poweroff.
-
#initialize(attributes = {}) ⇒ Server
constructor
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 :}.
- #ip_address(key) ⇒ Object
-
#mac ⇒ Object
Retrieves the mac address from parsing the XML of the domain.
- #new? ⇒ Boolean
-
#poweroff ⇒ Object
In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine.
- #private_ip_address ⇒ Object
- #public_ip_address ⇒ Object
- #ready? ⇒ Boolean
- #reboot ⇒ Object
- #resume ⇒ Object
- #save ⇒ Object
-
#scp(local_path, remote_path, upload_options = {}) ⇒ Object
Transfers a file.
-
#setup(credentials = {}) ⇒ Object
Sets up a new key.
- #shutdown ⇒ Object
- #ssh(commands) ⇒ Object
- #ssh_proxy ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
- #stopped? ⇒ Boolean
- #suspend ⇒ Object
- #to_fog_state(raw_state) ⇒ Object
- #validate_template_options ⇒ Object
- #vnc_port ⇒ Object
- #xml_from_template ⇒ Object
Methods included from Fog::Compute::LibvirtUtil
Methods inherited from Model
#inspect, #reload, #to_json, #wait_for
Methods included from Attributes::ClassMethods
#_load, #aliases, #attribute, #attributes, #identity, #ignore_attributes, #ignored_attributes
Methods included from Attributes::InstanceMethods
#_dump, #attributes, #dup, #identity, #identity=, #merge_attributes, #new_record?, #requires, #requires_one
Constructor Details
#initialize(attributes = {}) ⇒ Server
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
:
49 50 51 52 53 54 55 56 57 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 49 def initialize(attributes={} ) # setup all attributes. defaults.merge(attributes).each do |k,v| eval("self.#{k}= v") if self.respond_to?("#{k}=") end super end |
Instance Attribute Details
#iso_dir ⇒ Object
The following attributes are only needed when creating a new vm
36 37 38 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 36 def iso_dir @iso_dir end |
#iso_file ⇒ Object
The following attributes are only needed when creating a new vm
36 37 38 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 36 def iso_file @iso_file end |
#network_bridge_name ⇒ Object
Returns the value of attribute network_bridge_name.
37 38 39 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 37 def network_bridge_name @network_bridge_name end |
#network_interface_type ⇒ Object
Returns the value of attribute network_interface_type.
37 38 39 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 37 def network_interface_type @network_interface_type end |
#network_nat_network ⇒ Object
Returns the value of attribute network_nat_network.
37 38 39 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 37 def network_nat_network @network_nat_network end |
#password ⇒ Object
Returns the value of attribute password.
40 41 42 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 40 def password @password end |
#private_key ⇒ Object
367 368 369 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 367 def private_key @private_key ||= private_key_path && File.read(private_key_path) end |
#private_key_path ⇒ Object
362 363 364 365 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 362 def private_key_path @private_key_path ||= Fog.credentials[:private_key_path] @private_key_path &&= File.(@private_key_path) end |
#public_key ⇒ Object
376 377 378 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 376 def public_key @public_key ||= public_key_path && File.read(public_key_path) end |
#public_key_path ⇒ Object
371 372 373 374 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 371 def public_key_path @public_key_path ||= Fog.credentials[:public_key_path] @public_key_path &&= File.(@public_key_path) end |
#username ⇒ Object
157 158 159 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 157 def username @username ||= 'root' end |
#volume_allocation ⇒ Object
Returns the value of attribute volume_allocation.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_allocation @volume_allocation end |
#volume_capacity ⇒ Object
Returns the value of attribute volume_capacity.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_capacity @volume_capacity end |
#volume_format_type ⇒ Object
Returns the value of attribute volume_format_type.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_format_type @volume_format_type end |
#volume_name ⇒ Object
Returns the value of attribute volume_name.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_name @volume_name end |
#volume_path ⇒ Object
Returns the value of attribute volume_path.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_path @volume_path end |
#volume_pool_name ⇒ Object
Returns the value of attribute volume_pool_name.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_pool_name @volume_pool_name end |
#volume_template_name ⇒ Object
Returns the value of attribute volume_template_name.
38 39 40 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 38 def volume_template_name @volume_template_name end |
Instance Method Details
#addresses(options = {}) ⇒ Object
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
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 251 def addresses(={}) 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=[:ip_command].nil? ? ip_command_global : [: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 ={} [:keys]=[ keyfile ] unless keyfile.nil? [:port]=port unless keyfile.nil? [: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, ).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 ⇒ Object
TODO move all of this to the volume class
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 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 86 def create_or_clone_volume = Hash.new [: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) raise Fog::Errors::Error.new("Template #{self.volume_template_name} not found") unless template_volumes.empty? orig_volume = template_volumes.first volume = orig_volume.clone("#{[: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 else # If no template volume was given, let's create our own volume [:format_type] = self.volume_format_type if volume_format_type [:capacity] = self.volume_capacity if volume_capacity [:allocation] = self.volume_allocation if volume_allocation begin volume = connection.volumes.create() self.volume_path = volume.path self.volume_format_type ||= volume.format_type rescue raise Fog::Errors::Error.new("Error creating the volume : #{$!}") end end end |
#destroy(options = { :destroy_volumes => false}) ⇒ Object
In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 176 def destroy(={ :destroy_volumes => false}) requires :raw poweroff unless stopped? #TODO: add handling of failure @raw.undefine if [:destroy_volumes] # volumes.all filters do not handle nil keys well connection.volumes.all(:path => disk_path).each { |vol| vol.destroy} end end |
#disk_path ⇒ Object
464 465 466 467 468 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 464 def disk_path document("domain/devices/disk/source", "file") rescue [] end |
#halt ⇒ Object
Alias for poweroff
194 195 196 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 194 def halt poweroff end |
#ip_address(key) ⇒ Object
353 354 355 356 357 358 359 360 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 353 def ip_address(key) ips=addresses[key] unless ips.nil? return ips.first else return nil end end |
#mac ⇒ Object
Retrieves the mac address from parsing the XML of the domain
456 457 458 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 456 def mac mac = document("domain/devices/interface/mac", "address") end |
#new? ⇒ Boolean
59 60 61 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 59 def new? uuid.nil? end |
#poweroff ⇒ Object
In libvirt a destroy means a hard power-off of the domain In fog a destroy means the remove of a machine
200 201 202 203 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 200 def poweroff requires :raw @raw.destroy end |
#private_ip_address ⇒ Object
345 346 347 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 345 def private_ip_address ip_address(:private) end |
#public_ip_address ⇒ Object
349 350 351 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 349 def public_ip_address ip_address(:public) end |
#ready? ⇒ Boolean
236 237 238 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 236 def ready? state == "running" end |
#reboot ⇒ Object
188 189 190 191 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 188 def reboot requires :raw @raw.reboot end |
#resume ⇒ Object
210 211 212 213 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 210 def resume requires :raw @raw.resume end |
#save ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 63 def save raise Fog::Errors::Error.new('Resaving an existing server may create a duplicate') unless new? xml ||= xml_from_template 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 self.raw = 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 |
#scp(local_path, remote_path, upload_options = {}) ⇒ Object
Transfers a file
409 410 411 412 413 414 415 416 417 418 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 409 def scp(local_path, remote_path, = {}) requires :public_ip_address, :username = {} [:password] = password unless self.password.nil? [:key_data] = [private_key] if self.private_key [:proxy]= ssh_proxy unless self.ssh_proxy.nil? Fog::SCP.new(public_ip_address, username, ).upload(local_path, remote_path, ) end |
#setup(credentials = {}) ⇒ Object
Sets up a new key
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 422 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 ⇒ Object
205 206 207 208 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 205 def shutdown requires :raw @raw.shutdown end |
#ssh(commands) ⇒ Object
380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 380 def ssh(commands) requires :public_ip_address, :username #requires :password, :private_key ={} [:password] = password unless password.nil? [:key_data] = [private_key] if private_key [:proxy]= ssh_proxy unless ssh_proxy.nil? Fog::SSH.new(public_ip_address, @username, ).run(commands) end |
#ssh_proxy ⇒ Object
394 395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 394 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 ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 161 def start requires :raw unless @raw.active? begin @raw.create true rescue false end end end |
#stop ⇒ Object
240 241 242 243 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 240 def stop requires :raw @raw.shutdown end |
#stopped? ⇒ Boolean
232 233 234 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 232 def stopped? state == "shutoff" end |
#suspend ⇒ Object
215 216 217 218 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 215 def suspend requires :raw @raw.suspend end |
#to_fog_state(raw_state) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 220 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 end |
#validate_template_options ⇒ Object
125 126 127 128 129 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 125 def 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 ⇒ Object
460 461 462 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 460 def vnc_port port = document("domain/devices/graphics[@type='vnc']", "port") end |
#xml_from_template ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/fog/libvirt/models/compute/server.rb', line 131 def xml_from_template ={ :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_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 |