Василец Дмитрий
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>