Василец Дмитрий
2009-Jan-21 15:51 UTC
[Ovirt-devel] ovirt-server patch for vm failover and actual data set to db
this patch restart vm from crashed host and set to db current data about vm. please test or criticize it. fencing is ipmi , when domain['state'] set 'crashed' i will reboot host diff --git a/src/db-omatic/db_omatic.rb b/src/db-omatic/db_omatic.rb index 4afffb1..bdab392 100755 --- a/src/db-omatic/db_omatic.rb +++ b/src/db-omatic/db_omatic.rb @@ -74,6 +76,65 @@ class DbOmatic < Qpid::Qmf::Console domain[:synced] = true end + #find hostname from values['node'] where values['class_type'] == 'domain' + def get_host_id(abank,bbank) #?????????? ???????? ?? ?? ??? ???? - ???????? ????????????? ???? ?????????? + begin + @cached_objects.keys.each do |objkey| + if @cached_objects[objkey][:agent_bank].to_s == abank and @cached_objects[objkey][:broker_bank].to_s == bbank and @cached_objects[objkey][:class_type].to_s == 'node' + return Host.find(:first, :conditions => ['hostname ?', at cached_objects[objkey]["hostname"].to_s]).id + break + end + end + rescue => ex + log("error in get_host_id") + log(ex) + end + end + + def set_host(values,digit) + begin + vm = Vm.find(:first, :conditions => ['description = ?',values["name"].to_s]) + if vm and digit + vm.host_id = digit + vm.save! + else + log("this vm not exist #{values["name"]}") + end + rescue => ex + puts "error when set_host for #{values["name"]}" + puts ex + end + end + + def start_crashed_vm(vm) + task = VmTask.new( :user => 'db-omatic', :task_target => vm, :action => 'start_vm', :state => 'queued') + task.save! + log("set task for start crashed vm #{vm.id}") + end + + def set_domain_stopped(domain) + begin + vm = Vm.find(:first, :conditions => ['uuid = ?', domain['uuid']]) + if vm != nil + curstate = vm.state + vm.state = Vm::STATE_STOPPED + vm.host_id = nil + vm.save + domain['state'] = 'crashed' # and now i will use ipmi for reboot anavailable host - simple fencing + if curstate == Vm::STATE_RUNNING + start_crashed_vm(vm) + end + else + log('vm == nil ') + end + log("domain #{domain['id']} already stopped") + rescue => ex + log("can\'t set domain #{domain['id']} stopped") + log(ex) + end + end + + def update_host_state(host_info, state) db_host = Host.find(:first, :conditions => [ "hostname = ?", host_info['hostname'] ]) if db_host @@ -130,20 +190,36 @@ class DbOmatic < Qpid::Qmf::Console end domain_state_change = false - + change_node = false obj.properties.each do |key, newval| if values[key.to_s] != newval values[key.to_s] = newval #log "new value for property #{key} : #{newval}" if type == "domain" and key.to_s == "state" - domain_state_change = true + domain_state_change = true end + if type == "domain" and key.to_s == "node" + change_node = true + end + end end if domain_state_change update_domain_state(values) end + if change_node + values.each do |key,val| + if key == 'state' and val == 'running' + abank = values['node'].to_s.split('-')[3] + bbank = values['node'].to_s.split('-')[4] + @@host_id = get_host_id(abank,bbank) + set_host(values,@@host_id) + log("update node data for #{values['name']}") + break + end + end + end if new_object if type == "node" @@ -187,11 +263,6 @@ class DbOmatic < Qpid::Qmf::Console end end - - def del_agent(agent) - agent_disconnected(agent) - end - # This method marks objects associated with the given agent as timed out/invalid. Called either # when the agent heartbeats out, or we get a del_agent callback. def agent_disconnected(agent) @@ -204,11 +275,13 @@ class DbOmatic < Qpid::Qmf::Console if values[:timed_out] == false if values[:class_type] == 'node' update_host_state(values, Host::STATE_UNAVAILABLE) + values[:timed_out] = true elsif values[:class_type] == 'domain' - update_domain_state(values, Vm::STATE_UNREACHABLE) - end + set_domain_stopped(values) + values[:timed_out] = true + @cached_objects.delete(objkey) + end end - values[:timed_out] = true end end end @@ -248,6 +320,7 @@ class DbOmatic < Qpid::Qmf::Console db_vm = Vm.find(:all) db_vm.each do |vm| log "Marking vm #{vm.description} as stopped." + vm.host_id = nil vm.state = Vm::STATE_STOPPED vm.save end -- ? ?????????, ???????.
Василец Дмитрий
2009-Jan-23 18:48 UTC
[Ovirt-devel] Re: ovirt-server patch for vm failover and actual data set to db
Hello. are this patch not needed ? i can rewrite if bad code -- ? ?????????, ???????.
Ian Main
2009-Jan-27 18:18 UTC
[Ovirt-devel] ovirt-server patch for vm failover and actual data set to db
Sorry I took so long to get back to you on this one. There are some issues with formatting in this patch etc. but mostly I've been thinking that we need to have this configurable in the WUI. I'm curious what other people think about rebooting crashed hosts? Is this a desired feature? Ian On Wed, 21 Jan 2009 18:51:44 +0300 ??????? ??????? <pronix.service at gmail.com> wrote:> this patch restart vm from crashed host and set to db current data about vm. > please test or criticize it. > fencing is ipmi , when domain['state'] set 'crashed' i will reboot host > > > diff --git a/src/db-omatic/db_omatic.rb b/src/db-omatic/db_omatic.rb > index 4afffb1..bdab392 100755 > --- a/src/db-omatic/db_omatic.rb > +++ b/src/db-omatic/db_omatic.rb > @@ -74,6 +76,65 @@ class DbOmatic < Qpid::Qmf::Console > domain[:synced] = true > end > > + #find hostname from values['node'] where values['class_type'] == 'domain' > + def get_host_id(abank,bbank) #?????????? ???????? ?? ?? ??? ???? > - ???????? ????????????? ???? ?????????? > + begin > + @cached_objects.keys.each do |objkey| > + if @cached_objects[objkey][:agent_bank].to_s == abank and > @cached_objects[objkey][:broker_bank].to_s == bbank and > @cached_objects[objkey][:class_type].to_s == 'node' > + return Host.find(:first, :conditions => ['hostname > ?', at cached_objects[objkey]["hostname"].to_s]).id > + break > + end > + end > + rescue => ex > + log("error in get_host_id") > + log(ex) > + end > + end > + > + def set_host(values,digit) > + begin > + vm = Vm.find(:first, :conditions => ['description = ?',values["name"].to_s]) > + if vm and digit > + vm.host_id = digit > + vm.save! > + else > + log("this vm not exist #{values["name"]}") > + end > + rescue => ex > + puts "error when set_host for #{values["name"]}" > + puts ex > + end > + end > + > + def start_crashed_vm(vm) > + task = VmTask.new( :user => 'db-omatic', :task_target => vm, :action > => 'start_vm', :state => 'queued') > + task.save! > + log("set task for start crashed vm #{vm.id}") > + end > + > + def set_domain_stopped(domain) > + begin > + vm = Vm.find(:first, :conditions => ['uuid = ?', domain['uuid']]) > + if vm != nil > + curstate = vm.state > + vm.state = Vm::STATE_STOPPED > + vm.host_id = nil > + vm.save > + domain['state'] = 'crashed' # and now i will use ipmi for reboot > anavailable host - simple fencing > + if curstate == Vm::STATE_RUNNING > + start_crashed_vm(vm) > + end > + else > + log('vm == nil ') > + end > + log("domain #{domain['id']} already stopped") > + rescue => ex > + log("can\'t set domain #{domain['id']} stopped") > + log(ex) > + end > + end > + > + > def update_host_state(host_info, state) > db_host = Host.find(:first, :conditions => [ "hostname = ?", > host_info['hostname'] ]) > if db_host > > @@ -130,20 +190,36 @@ class DbOmatic < Qpid::Qmf::Console > end > > domain_state_change = false > - > + change_node = false > obj.properties.each do |key, newval| > if values[key.to_s] != newval > values[key.to_s] = newval > #log "new value for property #{key} : #{newval}" > if type == "domain" and key.to_s == "state" > - domain_state_change = true > + domain_state_change = true > end > + if type == "domain" and key.to_s == "node" > + change_node = true > + end > + > end > end > > if domain_state_change > update_domain_state(values) > end > + if change_node > + values.each do |key,val| > + if key == 'state' and val == 'running' > + abank = values['node'].to_s.split('-')[3] > + bbank = values['node'].to_s.split('-')[4] > + @@host_id = get_host_id(abank,bbank) > + set_host(values,@@host_id) > + log("update node data for #{values['name']}") > + break > + end > + end > + end > > if new_object > if type == "node" > @@ -187,11 +263,6 @@ class DbOmatic < Qpid::Qmf::Console > end > end > > - > - def del_agent(agent) > - agent_disconnected(agent) > - end > - > # This method marks objects associated with the given agent as > timed out/invalid. Called either > # when the agent heartbeats out, or we get a del_agent callback. > def agent_disconnected(agent) > @@ -204,11 +275,13 @@ class DbOmatic < Qpid::Qmf::Console > if values[:timed_out] == false > if values[:class_type] == 'node' > update_host_state(values, Host::STATE_UNAVAILABLE) > + values[:timed_out] = true > elsif values[:class_type] == 'domain' > - update_domain_state(values, Vm::STATE_UNREACHABLE) > - end > + set_domain_stopped(values) > + values[:timed_out] = true > + @cached_objects.delete(objkey) > + end > end > - values[:timed_out] = true > end > end > end > @@ -248,6 +320,7 @@ class DbOmatic < Qpid::Qmf::Console > db_vm = Vm.find(:all) > db_vm.each do |vm| > log "Marking vm #{vm.description} as stopped." > + vm.host_id = nil > vm.state = Vm::STATE_STOPPED > vm.save > end > > > > > -- > ? ?????????, ???????. > > _______________________________________________ > Ovirt-devel mailing list > Ovirt-devel at redhat.com > https://www.redhat.com/mailman/listinfo/ovirt-devel
Василец Дмитрий
2009-Jan-30 14:43 UTC
[Ovirt-devel] ovirt-server patch for vm failover and actual data set to db
i split patch and reformat it first part is for set actual data to db about vm second add wui button for enable/disable restart vm if crash host and code for do it (without fencing mechanism) if source corrupt by mail agent i attach both files *PATCH.1* diff --git a/src/db-omatic/db_omatic.rb b/src/db-omatic/db_omatic.rb index 4afffb1..c499610 100755 --- a/src/db-omatic/db_omatic.rb +++ b/src/db-omatic/db_omatic.rb @@ -74,6 +74,64 @@ class DbOmatic < Qpid::Qmf::Console domain[:synced] = true end + #find hostname from values['node'] where values['class_type'] ='domain' + def get_host_id(abank,bbank) + begin + @cached_objects.keys.each do |objkey| + if @cached_objects[objkey][:agent_bank].to_s == abank and @cached_objects[objkey][:broker_bank].to_s == bbank and @cached_objects[objkey][:class_type].to_s == 'node' + return Host.find(:first, :conditions => ['hostname ?', at cached_objects[objkey]["hostname"].to_s]).id + break + end + end + rescue => ex + log("error in get_host_id") + log(ex) + end + end + + def set_host(values,digit) + begin + vm = Vm.find(:first, :conditions => ['description ?',values["name"].to_s]) + if vm and digit + vm.host_id = digit + vm.save! + else + log("this vm not exist #{values["name"]}") + end + rescue => ex + puts "error when set_host for #{values["name"]}" + puts ex + end + end + + def start_crashed_vm(vm) + task = VmTask.new( :user => 'db-omatic', :task_target => vm, :action => 'start_vm', :state => 'queued') + task.save! + log("set task for start crashed vm #{vm.id}") + end + + def set_domain_stopped(domain) + begin + vm = Vm.find(:first, :conditions => ['uuid = ?', domain['uuid']]) + if vm != nil + curstate = vm.state + vm.state = Vm::STATE_STOPPED + vm.host_id = nil + vm.save + domain['state'] = 'crashed' # and now i will use ipmi for reboot anavailable host - simple fencing + if curstate == Vm::STATE_RUNNING and vm.ha # vm.ha true or false + start_crashed_vm(vm) + end + else + log('vm == nil ') + end + log("domain #{domain['id']} already stopped") + rescue => ex + log("can\'t set domain #{domain['id']} stopped") + log(ex) + end + end + def update_host_state(host_info, state) db_host = Host.find(:first, :conditions => [ "hostname = ?", host_info['hostname'] ]) if db_host @@ -131,6 +189,7 @@ class DbOmatic < Qpid::Qmf::Console domain_state_change = false + change_node = false obj.properties.each do |key, newval| if values[key.to_s] != newval values[key.to_s] = newval @@ -138,12 +197,30 @@ class DbOmatic < Qpid::Qmf::Console if type == "domain" and key.to_s == "state" domain_state_change = true end + if type == "domain" and key.to_s == "node" + change_node = true + end + + end end if domain_state_change update_domain_state(values) end + if change_node + values.each do |key,val| + if key == 'state' and val == 'running' + abank = values['node'].to_s.split('-')[3] + bbank = values['node'].to_s.split('-')[4] + @@host_id = get_host_id(abank,bbank) + set_host(values,@@host_id) + log("update node data for #{values['name']}") + break + end + end + end + if new_object if type == "node" @@ -187,11 +264,6 @@ class DbOmatic < Qpid::Qmf::Console end end - - def del_agent(agent) - agent_disconnected(agent) - end - # This method marks objects associated with the given agent as timed out/invalid. Called either # when the agent heartbeats out, or we get a del_agent callback. def agent_disconnected(agent) @@ -205,8 +277,10 @@ class DbOmatic < Qpid::Qmf::Console if values[:class_type] == 'node' update_host_state(values, Host::STATE_UNAVAILABLE) elsif values[:class_type] == 'domain' - update_domain_state(values, Vm::STATE_UNREACHABLE) - end + set_domain_stopped(values) + values[:timed_out] = true + @cached_objects.delete(objkey) + end end values[:timed_out] = true end @@ -248,6 +322,7 @@ class DbOmatic < Qpid::Qmf::Console db_vm = Vm.find(:all) db_vm.each do |vm| log "Marking vm #{vm.description} as stopped." + vm.host_id = nil vm.state = Vm::STATE_STOPPED vm.save end *PATCH.2* diff --git a/src/app/controllers/vm_controller.rb b/src/app/controllers/vm_controller.rb index 56501fd..0f43680 100644 --- a/src/app/controllers/vm_controller.rb +++ b/src/app/controllers/vm_controller.rb @@ -20,11 +20,22 @@ require 'socket' class VmController < ApplicationController # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) - verify :method => :post, :only => [ :destroy, :create, :update ], + verify :method => :post, :only => [ :destroy, :create, :update , :change_ha_vm], :redirect_to => { :controller => 'dashboard' } before_filter :pre_vm_action, :only => [:vm_action, :cancel_queued_tasks, :console] + def change_ha_vm + vm = Vm.find_by_id(params[:id]) + if vm.ha + then vm.ha = false + else vm.ha = true + end + vm.save! + alert = "vm was change ha successfully " + render :json => { :object => "vm", :success => true, :alert => alert } + end + def index roles = "('" + Permission::roles_for_privilege(Permission::PRIV_VIEW).join("', '") + diff --git a/src/app/views/vm/show.rhtml b/src/app/views/vm/show.rhtml index f361131..4809bbe 100644 --- a/src/app/views/vm/show.rhtml +++ b/src/app/views/vm/show.rhtml @@ -29,6 +29,9 @@ </a> <% end -%> <% end %> + <a href="#" onClick="change_ha_vm()" rel="facebox[.bolder]"> + <%= image_tag "icon_x.png" %> Change HA + </a> <a href="#confirm_cancel" rel="facebox[.bolder]"> <%= image_tag "icon_x.png" %> Cancel queued tasks </a> @@ -40,6 +43,19 @@ <%= confirmation_dialog("confirm_cancel", "Are you sure?", "cancel_queued_tasks()") %> <%= confirmation_dialog("confirm_delete", "Are you sure?", "delete_vm()") %> <script type="text/javascript"> + function change_ha_vm() + { + $(document).trigger('close.facebox'); + $.post('<%= url_for :controller => "vm", :action => "change_ha_vm", :id => @vm %>', + {x: 1}, + function(data,status){ + $("#vms_grid").flexReload(); + if (data.alert) { + $.jGrowl(data.alert); + } + empty_summary('vms_selection', 'Virtual Machine'); + }, 'json'); + } function cancel_queued_tasks() { $(document).trigger('close.facebox'); diff --git a/src/db/migrate/006_create_vms.rb b/src/db/migrate/006_create_vms.rb index 74794b6..a5460f0 100644 --- a/src/db/migrate/006_create_vms.rb +++ b/src/db/migrate/006_create_vms.rb @@ -34,6 +34,7 @@ class CreateVms < ActiveRecord::Migration t.string :boot_device, :null => false t.integer :vnc_port t.integer :lock_version, :default => 0 + t.boolean :ha , :default => true end execute "alter table vms add constraint fk_vms_hosts foreign key (host_id) references hosts(id)" -- ? ?????????, ???????. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://listman.redhat.com/archives/ovirt-devel/attachments/20090130/6f6b42e9/attachment.htm> -------------- next part -------------- A non-text attachment was scrubbed... Name: part.1.patch Type: text/x-diff Size: 4870 bytes Desc: not available URL: <http://listman.redhat.com/archives/ovirt-devel/attachments/20090130/6f6b42e9/attachment.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: part.2.patch Type: text/x-diff Size: 2858 bytes Desc: not available URL: <http://listman.redhat.com/archives/ovirt-devel/attachments/20090130/6f6b42e9/attachment-0001.bin>