summaryrefslogtreecommitdiffstats
path: root/cloudmasterd
diff options
context:
space:
mode:
authorMatthew Hicks <mhicks@mhicks-host.usersys.redhat.com>2008-06-23 15:06:37 -0400
committerMatthew Hicks <mhicks@mhicks-host.usersys.redhat.com>2008-06-24 08:08:25 -0400
commit4ec70ff34acf9ef7733cf6dc606a147a9c3ca9bd (patch)
treeb410d5426238f27edba0eb031e67c13f01de829d /cloudmasterd
parent4b539425989d8c3d10a24a988175be5ba850bbec (diff)
downloadtools-4ec70ff34acf9ef7733cf6dc606a147a9c3ca9bd.tar.gz
tools-4ec70ff34acf9ef7733cf6dc606a147a9c3ca9bd.tar.xz
tools-4ec70ff34acf9ef7733cf6dc606a147a9c3ca9bd.zip
Tools cleanup
Diffstat (limited to 'cloudmasterd')
-rw-r--r--cloudmasterd/Manifest.txt1
-rwxr-xr-xcloudmasterd/bin/cloudmasterd-sync138
-rwxr-xr-xcloudmasterd/extra/cloudmasterd.redhat1
-rw-r--r--cloudmasterd/extra/cloudmasterd.spec4
-rw-r--r--cloudmasterd/lib/cloudmasterd.rb58
-rw-r--r--cloudmasterd/lib/cloudmasterd/syncer.rb171
-rw-r--r--cloudmasterd/lib/cloudmasterd/version.rb6
7 files changed, 212 insertions, 167 deletions
diff --git a/cloudmasterd/Manifest.txt b/cloudmasterd/Manifest.txt
index c734bd7..6060f4e 100644
--- a/cloudmasterd/Manifest.txt
+++ b/cloudmasterd/Manifest.txt
@@ -14,6 +14,7 @@ extra/cloudmasterd.conf
extra/cloudmasterd.redhat
extra/cloudmasterd.spec
lib/cloudmasterd.rb
+lib/cloudmasterd/syncer.rb
lib/cloudmasterd/version.rb
log/debug.log
primedb.rb
diff --git a/cloudmasterd/bin/cloudmasterd-sync b/cloudmasterd/bin/cloudmasterd-sync
index f30a6c4..1681bb0 100755
--- a/cloudmasterd/bin/cloudmasterd-sync
+++ b/cloudmasterd/bin/cloudmasterd-sync
@@ -1,142 +1,10 @@
#!/usr/bin/ruby
require 'rubygems'
-require 'open3'
-require 'sqlite3'
-require 'active_record'
+require 'cloudmasterd/syncer'
-# This is needed to let a 'kill PID' command cleanly
-# kill the process without requiring -9
-Signal.trap("TERM") do
- # Clean up any active record connections
- ActiveRecord::Base.remove_connection
-
- # Cleanly exit
- exit 0
-end
-
-def parse_hosts(func_stderr)
- hosts = []
- func_stderr.split("\n").each do |host_line|
- # Handle a remote exception coming from a disconnected host
- if host_line.index("remote exception") then
- hosts.pop()
- else
- hosts << host_line.split(":")[1][2..-1]
- end
- end
- return hosts
-end
-
-def sync_memory
- current_state = {}
- Open3.popen3("func '*' call virt freemem") do |stdin, stdout, stderr|
- hosts = parse_hosts(stderr.read)
-
- # Parse out the machines that belong to each host and zip them together in a hash
- stdout.read.split("\n").each_with_index do |memory, index|
- current_state[hosts[index]] = memory
- end
- end
-
- Cloud.transaction do
- # Sync up the DB state - delete everything first
- Cloud.delete_all
-
- # Create the current entries
- current_state.each do |host, memory|
- Cloud.create :name => host, :memory => memory
- end
- end
-end
-
-def sync_state
- current_state = {}
- Open3.popen3("func '*' call virt state") do |stdin, stdout, stderr|
- hosts = parse_hosts(stderr.read)
-
- # Parse out the machines that belong to each host and zip them together in a hash
- stdout.read.split("\n").each_with_index do |host, index|
- host[1..-2].split(", ").each do |machine|
- name, state = machine[1..-2].split(" ")
- current_state[name] = {:state => state, :cloud => hosts[index]} unless name == "Domain-0"
- end
- end
- end
-
- # Sync up the state for all the machines
- Machine.find(:all).each do |machine|
- if current_state.has_key?(machine.name) then
- # We have a current state match for this machine
- machine.update_attributes(:cloud => current_state[machine.name][:cloud], :state => current_state[machine.name][:state])
-
- # Delete the key so we can determine unaccounted for machines
- current_state.delete(machine.name)
- else
- # Not good - the machine in the DB isn't locateable
- machine.update_attribute(:state, "missing")
- end
- end
-
- # We need to create an 'unknown' instance for all the remaining keys
- current_state.each do |name, machine|
- Machine.create :name => name, :email => "unknown", :cloud => machine[:cloud], :state => machine[:state]
- end
-end
-
-def sync_owners
- # Sync up any unowned machines that now have an owner (handles race condition with syncing states)
- unowned_machines = {}
- Machine.find(:all, :conditions => "email = 'unknown'").each do |machine|
- unowned_machines[machine.name] = machine
- end
-
- owned_machines = {}
- Machine.find(:all, :conditions => "email <> 'unknown'").each do |machine|
- owned_machines[machine.name] = machine
- end
-
- owned_machines.each do |name, machine|
- if unowned_machines.has_key?(name) then
- # Delete the unowned machine and update the owned one
- u_machine = unowned_machines[name]
- machine.update_attributes(:cloud => u_machine.cloud, :state => u_machine.state)
- u_machine.destroy()
- end
- end
-end
-
-# Wait until the DB is there to establish the connection
-until File.exists?("/var/lib/cloudmaster.db") do
- sleep 10
-end
-
-ActiveRecord::Base.logger = Logger.new('/var/log/cloudmasterd-sync.log', 5, 1024000)
-ActiveRecord::Base.colorize_logging = false
-
-# Setup the database connection
-ActiveRecord::Base.establish_connection(
- :adapter => "sqlite3",
- :dbfile => "/var/lib/cloudmaster.db"
-)
-
-class Machine < ActiveRecord::Base
- set_table_name "cloudmasterd_machine"
-end
-
-class Cloud < ActiveRecord::Base
- set_table_name "cloudmasterd_cloud"
-end
-
-# Constantly keep the database in sync
+syncer = Syncer.new()
while true do
- begin
- sync_memory
- sync_state
- sync_owners
- rescue Exception => e
- puts "ERROR: An error occured during syncing - #{e.to_s}"
- end
-
+ syncer.run
sleep 5
end
diff --git a/cloudmasterd/extra/cloudmasterd.redhat b/cloudmasterd/extra/cloudmasterd.redhat
index dd276a8..0021f44 100755
--- a/cloudmasterd/extra/cloudmasterd.redhat
+++ b/cloudmasterd/extra/cloudmasterd.redhat
@@ -19,6 +19,7 @@ CTL=cloudmasterd-ctl
case "$1" in
start)
echo -n $"Starting cloudmasterd: "
+ rm /var/tmp/cloudmasterd.lock &> /dev/null
/usr/bin/cloudmasterd-sync &
$CTL start
RETVAL=$?
diff --git a/cloudmasterd/extra/cloudmasterd.spec b/cloudmasterd/extra/cloudmasterd.spec
index 2fb4924..7d77ac8 100644
--- a/cloudmasterd/extra/cloudmasterd.spec
+++ b/cloudmasterd/extra/cloudmasterd.spec
@@ -6,10 +6,10 @@
Summary: daemon for machine configuration
Name: rubygem-%{gemname}
-Version: 0.1.10
+Version: 1.0.0
Release: 1%{?dist}
Group: Development/Languages
-License: GPLv2+ or Ruby
+License: GPLv2
URL: http://cloudmasterd.rubyforge.org
Source0: %{gemname}-%{version}.gem
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
diff --git a/cloudmasterd/lib/cloudmasterd.rb b/cloudmasterd/lib/cloudmasterd.rb
index d82f165..b4cbf08 100644
--- a/cloudmasterd/lib/cloudmasterd.rb
+++ b/cloudmasterd/lib/cloudmasterd.rb
@@ -1,7 +1,3 @@
-$: << File.dirname(File.expand_path(__FILE__))
-
-gem 'reststop', '~> 0.2'
-
require 'yaml'
require 'fileutils'
require 'rubygems'
@@ -12,6 +8,7 @@ require 'restr'
require 'xmlrpc/client'
require 'sqlite3'
require 'open3'
+require 'cloudmasterd/syncer'
Camping.goes :Cloudmasterd
Cloudmasterd.picnic!
@@ -137,37 +134,44 @@ module Cloudmasterd::Controllers
email = input.email
cobbler_profile = _get_cobbler_profile(machine_fqdn, repo)
- @host = _get_best_host(cobbler_profile["virt_file_size"], cobbler_profile["virt_ram"])
- begin
- _koan(@host, machine_fqdn, repo)
+ # Synchronize access before making the func calls
+ Syncer::lock do
+ @host = _get_best_host(cobbler_profile["virt_file_size"], cobbler_profile["virt_ram"])
+
+ begin
+ _koan(@host, machine_fqdn, repo)
- Machine.create :name => machine_fqdn, :email => email, :cloud => @host, :state => "Installing"
- render :_koan
- rescue Exception => e
- @exception = e
- render :_error
+ Machine.create :name => machine_fqdn, :email => email, :cloud => @host, :state => "Installing"
+ render :_koan
+ rescue Exception => e
+ @exception = e
+ render :_error
+ end
end
end
def destroy(name)
puts "Destroying image #{name}"
- Machine.find(:all, :conditions => "name = '#{name}'").each do |machine|
- # If the machine is missing, don't bother remotely trying to cleanup
- unless machine.state == "missing" then
- # Destroy the virtual machine
- `func "#{machine.cloud}" call command run "virsh destroy #{machine.name}"`
- `func "#{machine.cloud}" call command run "virsh undefine #{machine.name}"`
-
- # Remove the auto start file if it exists
- `func "#{machine.cloud}" call command run "rm -rf /etc/xen/auto/#{machine.name}"`
-
- # Remove the image file
- `func "#{machine.cloud}" call command run "rm -rf /images/#{machine.name}-disk0"`
- end
- # Delete the DB record
- machine.destroy
+ Syncer::lock do
+ Machine.find(:all, :conditions => "name = '#{name}'").each do |machine|
+ # If the machine is missing, don't bother remotely trying to cleanup
+ unless machine.state == "missing" then
+ # Destroy the virtual machine
+ `func "#{machine.cloud}" call command run "virsh destroy #{machine.name}"`
+ `func "#{machine.cloud}" call command run "virsh undefine #{machine.name}"`
+
+ # Remove the auto start file if it exists
+ `func "#{machine.cloud}" call command run "rm -rf /etc/xen/auto/#{machine.name}"`
+
+ # Remove the image file
+ `func "#{machine.cloud}" call command run "rm -rf /images/#{machine.name}-disk0"`
+ end
+
+ # Delete the DB record
+ machine.destroy
+ end
end
redirect R(Status)
diff --git a/cloudmasterd/lib/cloudmasterd/syncer.rb b/cloudmasterd/lib/cloudmasterd/syncer.rb
new file mode 100644
index 0000000..3e9d493
--- /dev/null
+++ b/cloudmasterd/lib/cloudmasterd/syncer.rb
@@ -0,0 +1,171 @@
+#!/usr/bin/ruby
+
+require 'rubygems'
+require 'open3'
+require 'sqlite3'
+require 'active_record'
+
+# This is needed to let a 'kill PID' command cleanly
+# kill the process without requiring -9
+Signal.trap("TERM") do
+ # Clean up any active record connections
+ ActiveRecord::Base.remove_connection
+
+ # Cleanly exit
+ exit 0
+end
+
+# Define the ActiveRecord classes
+class Machine < ActiveRecord::Base
+ set_table_name "cloudmasterd_machine"
+end
+
+class Cloud < ActiveRecord::Base
+ set_table_name "cloudmasterd_cloud"
+end
+
+class Syncer
+ # This method makes a simple attempt to provide some locking
+ def self.lock
+ lockfile = '/var/tmp/cloudmasterd.lock'
+
+ begin
+ # Wait until the lock is released
+ while File.exists?(lockfile) do
+ sleep 0.5
+ end
+
+ # Obtain the lock
+ File.open(lockfile, "w") {|file| file.puts Thread.object_id.to_s}
+
+ # Make sure the lock is ours - otherwise retry
+ retry unless File.open(lockfile, "r").readline.chomp. == Thread.object_id.to_s
+
+ # Do the lock processing
+ yield
+ ensure
+ # Make sure to delete the lock
+ File.delete(lockfile)
+ end
+ end
+
+ def parse_hosts(func_stderr)
+ hosts = []
+ func_stderr.split("\n").each do |host_line|
+ # Handle a remote exception coming from a disconnected host
+ if host_line.index("remote exception") then
+ hosts.pop()
+ else
+ hosts << host_line.split(":")[1][2..-1]
+ end
+ end
+ return hosts
+ end
+
+ def sync_memory
+ current_state = {}
+ Open3.popen3("func '*' call virt freemem") do |stdin, stdout, stderr|
+ hosts = parse_hosts(stderr.read)
+
+ # Parse out the machines that belong to each host and zip them together in a hash
+ stdout.read.split("\n").each_with_index do |memory, index|
+ current_state[hosts[index]] = memory
+ end
+ end
+
+ Cloud.transaction do
+ # Sync up the DB state - delete everything first
+ Cloud.delete_all
+
+ # Create the current entries
+ current_state.each do |host, memory|
+ Cloud.create :name => host, :memory => memory
+ end
+ end
+ end
+
+ def sync_state
+ current_state = {}
+ Open3.popen3("func '*' call virt state") do |stdin, stdout, stderr|
+ hosts = parse_hosts(stderr.read)
+
+ # Parse out the machines that belong to each host and zip them together in a hash
+ stdout.read.split("\n").each_with_index do |host, index|
+ host[1..-2].split(", ").each do |machine|
+ name, state = machine[1..-2].split(" ")
+ current_state[name] = {:state => state, :cloud => hosts[index]} unless name == "Domain-0"
+ end
+ end
+ end
+
+ # Sync up the state for all the machines
+ Machine.find(:all).each do |machine|
+ if current_state.has_key?(machine.name) then
+ # We have a current state match for this machine
+ machine.update_attributes(:cloud => current_state[machine.name][:cloud], :state => current_state[machine.name][:state])
+
+ # Delete the key so we can determine unaccounted for machines
+ current_state.delete(machine.name)
+ else
+ # Not good - the machine in the DB isn't locateable
+ machine.update_attribute(:state, "missing")
+ end
+ end
+
+ # We need to create an 'unknown' instance for all the remaining keys
+ current_state.each do |name, machine|
+ Machine.create :name => name, :email => "unknown", :cloud => machine[:cloud], :state => machine[:state]
+ end
+ end
+
+ def sync_owners
+ # Sync up any unowned machines that now have an owner (handles race condition with syncing states)
+ unowned_machines = {}
+ Machine.find(:all, :conditions => "email = 'unknown'").each do |machine|
+ unowned_machines[machine.name] = machine
+ end
+
+ owned_machines = {}
+ Machine.find(:all, :conditions => "email <> 'unknown'").each do |machine|
+ owned_machines[machine.name] = machine
+ end
+
+ owned_machines.each do |name, machine|
+ if unowned_machines.has_key?(name) then
+ # Delete the unowned machine and update the owned one
+ u_machine = unowned_machines[name]
+ machine.update_attributes(:cloud => u_machine.cloud, :state => u_machine.state)
+ u_machine.destroy()
+ end
+ end
+ end
+
+ def run
+ # Wait until the DB is there to establish the connection
+ until File.exists?("/var/lib/cloudmaster.db") do
+ sleep 10
+ end
+
+ ActiveRecord::Base.logger = Logger.new('/var/log/cloudmasterd-sync.log', 5, 1024000)
+ ActiveRecord::Base.colorize_logging = false
+
+ # Setup the database connection
+ ActiveRecord::Base.establish_connection(
+ :adapter => "sqlite3",
+ :dbfile => "/var/lib/cloudmaster.db"
+ )
+
+ # Constantly keep the database in sync
+ while true do
+ begin
+ Syncer::lock { sync_memory }
+ Syncer::lock { sync_state }
+ Syncer::lock { sync_owners }
+ rescue Exception => e
+ puts "ERROR: An error occured during syncing - #{e.to_s}"
+ end
+
+ sleep 5
+ end
+ end
+end
diff --git a/cloudmasterd/lib/cloudmasterd/version.rb b/cloudmasterd/lib/cloudmasterd/version.rb
index d618c1c..d25021f 100644
--- a/cloudmasterd/lib/cloudmasterd/version.rb
+++ b/cloudmasterd/lib/cloudmasterd/version.rb
@@ -1,8 +1,8 @@
module Cloudmasterd #:nodoc:
module VERSION #:nodoc:
- MAJOR = 0
- MINOR = 1
- TINY = 10
+ MAJOR = 1
+ MINOR = 0
+ TINY = 0
STRING = [MAJOR, MINOR, TINY].join('.')
end