Posted by Tres
Mon, 03 Nov 2008 09:34:00 GMT
Installing the mysql Gem under RHEL/CentOS requires you to specify where MySQL is installed. Just point Gem to the mysql-config bin & you’re good to go:
gem install mysql -- --with-mysql-config=/usr/bin/mysql_config
Posted in Red Hat Enterprise Linux, Ruby, Sysadmin, Ruby on Rails | Tags Configuration, installation, Red Hat, ruby
Posted by Tres
Thu, 28 Aug 2008 12:53:00 GMT
Mixins are one of the most powerful constructs that Ruby provides. Mixins give you the power of multiple inheritance without all the inherent complexities and problems associated with multiple inheritance. The best part of using mixins is how extremely simple they are to use. Just include the module you want to mixin and then call any of the functions defined in the module.
Using mixins with rails is just as easy, the only problem is figuring out where to put your mixin (opinionated programming, you know). Just put your mixin into the lib directory of your rails project and you’ll be good to go. Once you’ve got the file in the right spot, just
require 'module_file_name'
include ModuleName
Then call the function you want to use, and you’re set.
Posted in Ruby, Development, Ruby on Rails | Tags mixins, rails
Posted by Tres
Sun, 10 Aug 2008 18:08:00 GMT
So there’s lots of documentation out there on creating XML via Rails. The problem is that it’s not really kept up with all the changes that have occurred. Here’s a few quick items that may be helpful when creating XML with Rails 2.1.
• When creating an instance of XMLBuilder, use ::Builder::XmlMarkup.new instead of Builder::XmlMarkup.new.
• When creating your view, use the extension .xml.builder instead of .xml.erb
• When rendering the template from the controller, make sure that the content type headers are set for xml and that you’re not rendering the layout. The controller should have a section that looks something like this:
headers["Content-Type"] = "text/xml"
respond_to do |format|
format.xml { render :template => 'options.xml.builder', :layout => false }
end
Posted in Ruby, Development, Ruby on Rails | Tags XML Builder, Rails 2.1
Posted by Tres
Wed, 14 May 2008 01:44:00 GMT
Here’s an easy one-liner to get ruby gem and all installed gems up to the latest available version:
gem update -y --system --include-dependencies && gem update -y --include-dependencies
Newer versions of gem include dependency installs and are not interactive, so you don’t need to use the flags outlined above. Just use:
gem update --system && gem update
Posted in Ruby, Sysadmin | Tags gem, liners, one, ruby, update
Posted by Tres
Sun, 20 Apr 2008 00:36:00 GMT
Here’s a little ruby hackery to do convert the output we got here into something like this:
MB total: 2432.0
MB used: 479.6953125
MB free: 1952.3046875
#!/usr/bin/env ruby
require 'optparse'
options = {}
outprint = {}
ot = String
opts = OptionParser.new do |opts|
opts.on("-p X", "--path X", String, "path to partition for host") do |path|
options[:path] = path
end
end
opts.parse!(ARGV)
output = `dumpe2fs -h #{options[:path]}`
output.squeeze!(" ")
output.each do | line |
line.grep(/Block count:/) { | total | outprint[:total_label] ,outprint[:total_data] = total.chomp.split(/\s*\:\s*/) }
line.grep( /Free blocks:/) { | free | outprint[:free_label], outprint[:free_data] = free.chomp.split(/\s*\:\s*/) }
line.grep(/Block size:/) { | size | outprint[:block_size_label], outprint[:block_size_data] = size.chomp.split(/\s*\:\s*/) }
line.grep(/Reserved block count:/) { | reserved | outprint[:reserved_label], outprint[:reserved_data] = reserved.chomp.split(/\s*\:\s*/) }
end
mb_available = ( outprint[:block_size_data].to_f / 1048576 * outprint[:total_data].to_f )
mb_free = ( outprint[:block_size_data].to_f / 1048576 * outprint[:free_data].to_f )
mb_used = ( mb_available.to_f - mb_free.to_f )
puts "MB total: #{mb_available}"
puts "MB used: #{mb_used}"
puts "MB free: #{mb_free}"
typo:code>
The ruby script takes a single argument, the path to the device that is going to be looked at. It can be passed with either a -p or –path.
Posted in Linux, Ruby, Sysadmin, Xen, Development | Tags DomU, memory, monitor, ruby, script, Xen
Posted by Tres
Sat, 12 Apr 2008 11:48:00 GMT
If you’re trying to monitor disk usage in a Xen domU and are using ext3fs formatted filesystems on LVM partitions, you can use dumpe2fs -h to get an idea of the current disk usage in domU from dom0.
[tres blas.phemo.us ~]$ sudo dumpe2fs -h /dev/vol00/xen_root_img
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:
Last mounted on:
Filesystem UUID: d18fab79-7123-4289-bd28-222ec8739874
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal resize_inode dir_index filetype needs_recovery sparse_super large_file
Default mount options: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 311296
Block count: 622592
Reserved block count: 31129
Free blocks: 336965
Free inodes: 256927
First block: 0
Block size: 4096
Fragment size: 4096
Reserved GDT blocks: 151
Blocks per group: 32768
Fragments per group: 32768
Inodes per group: 16384
Inode blocks per group: 512
Filesystem created: Tue Feb 5 18:57:47 2008
Last mount time: Fri Feb 15 14:42:15 2008
Last write time: Fri Feb 15 14:42:15 2008
Mount count: 6
Maximum mount count: 25
Last checked: Tue Feb 5 19:01:06 2008
Check interval: 15552000 (6 months)
Next check after: Sun Aug 3 20:01:06 2008
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
First orphan inode: 32775
Default directory hash: tea
Directory Hash Seed: d3f9829f-e127-427b-be56-4e840a139ccf
Journal backup: inode blocks
Journal size: 64M
So amongst all of the output, there are three lines that provide the magic: Block count:, Block size: and Free blocks:.
It’s easy enough to grab the three lines and then process them however you need to. This is a link to a ruby script that will check domU disk usage from dom0
Posted in Ruby, Sysadmin, Xen | Tags disk, DomU, monitor, usage
Posted by Tres
Wed, 09 Apr 2008 20:50:00 GMT
Here’s a little bash shell foo to figure out how many lines of code are in a specific directory and all its subdirectories.
As written, it looks for java files and excludes blank lines as well as subversion management directories:
totalcount=0
for i in `find . -name "*.java" -print | grep -v ".svn"`
do newcount=`cat $i | grep -v "^$" | wc -l`
totalcount=$(($totalcount+$newcount))
done
echo "totalcount: $totalcount"
Posted in PHP, Ruby, Java, Development | Tags count, line, Source
Posted by Tres
Sun, 16 Dec 2007 19:05:00 GMT
Here’s the command needed to start mongrel_rails for testing or if you don’t feel like running fastcgi through apache or lighttpd:
mongrel_rails start -a 127.0.0.1 -e production -c /var/www/blogomatic -l
log/mongrel.log --user mongrel --group mongrel -p 1292 -d
Posted in Ruby
Posted by Tres
Sun, 16 Dec 2007 19:01:00 GMT
Say you want to install a specific version of rails through gem because of some requirement for a specific version. Just use the following:
gem install --version '= 1.2.0' rails
You can also use greater than or less than versions to define what version to install
gem install --version '> 1.1.2' packagename
Posted in Ruby, Sysadmin
Posted by Tres
Mon, 15 Jan 2007 11:33:00 GMT
This class was written as a means to allow a “management node” to automatically change the state of a “hardware node” on which client virtual private servers are running. It’s referenced in the earlier article on using CFEngine to build an OpenVZ node. There are some unfinished methods for monitoring, but does provide all standard vzctl functionality. By design, the management node would be running some kind of billing software. By monitoring state changes in the billing software’s database, you can automatically provision new accounts, disable for late payments, delete accounts, add services, add resources, and do it all while you’re asleep.
By using SSH public keys and sudo, you can have the management node make any changes required to the state of a VPS on a hardware node. Why not just use vzctl via SSH? The problem with vzctl is that you’re implicitly granting privileges for the management node to do anything that vzctl can do. Second, it’s easier and more reliable to extend a class to do other things required things like firewall rules, bandwidth monitoring, rate limiting, etc. than it is to create a server-side (i.e. management node) script that will try to do all these things.
This class allows you to write scripts that only have the ability to do one thing. I’ll try to upload my scripts in a separate article later (they’re very small–if you know some Ruby, it should be easy to write them yourself). This means that you can add these scripts to your sudoers file, and reliably limit the kind of changes that can be made from the hardware node. Remember, the ultimate goal here is to automate all of this stuff; we not only have to make sure that the automated system won’t screw up, we have to make sure that we can also hook into the billing system’s database.
class Vps
attr_accessor :veid, :hostname, :nameservers, :ostemplate, :addresses, :plan_id, :password, :net_status, :cpu_usage, :disk_status, :disk_usage, :mem_usage, :sys_status, :net_usage, :batch_mode
require ("/usr/local/lib/vpsadmin/firewall.rb")
require ("optparse")
def initialize( )
@vzDir = "/vz"
@scriptsDir = "#{@vzDir}/scripts/"
@backupDir = "#{@scriptsDir}/backups/"
@disabledDir = "#{@scriptsDir}/disabled/"
@batch_mode = false
end
def create()
addressstring = String.new
addresses = @addresses.to_s
address_list = addresses.split(/\s*\,\s*/)
address_list.each { |address| addressstring.concat(" --ipadd #{address} ") }
system("vzctl create #{@veid} --ostemplate #{@ostemplate} --hostname #{@hostname} #{addressstring} --config #{@plan_id}")
self.set_nameserver()
self.set_password()
self.start()
sleep(60)
self.create_tun_dev()
end
def create_tun_dev()
system("vzctl exec #{@veid} mkdir -p /dev/net")
system("vzctl exec #{@veid} mknod /dev/net/tun c 10 200")
system("vzctl exec #{@veid} chmod 600 /dev/net/tun")
end
def set_nameserver()
nameserverstring = String.new
nameservers = @nameservers.to_s
nameservers.each(',') {|address| nameserverstring.concat(" --nameserver #{address} ")}
system("vzctl set #{@veid} #{nameserverstring} --save")
end
def set_password()
system("vzctl set #{@veid} --userpasswd root:#{@password} --save")
end
def set_hostname()
system("vzctl set #{@veid} --hostname #{@hostname} --save")
end
def destroy()
system("vzctl destroy #{@veid}")
firewall = new Firewall()
firewall.veid = @veid
firewall.plan = @plan_id
firewall.addresses = @addresses
firewall.delete()
end
def add_ip()
@addresses.each {|address| system("vzctl set #{@veid} --ipadd #{address} --save") }
firewall = new Firewall()
firewall.veid = @veid
firewall.plan = @plan_id
firewall.addresses = @addresses
firewall.setup()
end
def remove_ip()
system("vzctl set #{@veid} --ipdel all --save")
@addresses.each {|address| system("vzctl set #{@veid} --ipadd #{address} --save") }
end
def disable()
old_location = "#{@scriptsDir}/#{@veid}.conf"
new_location = "#{@backupDir}/#{@veid}.conf"
self.stop()
FileUtils.move( old_location, new_location )
end
def enable()
new_location = "#{@scriptsDir}/#{@veid}.conf"
old_location = "#{@backupDir}/#{@veid}.conf"
FileUtils.move( old_location, new_location )
self.start()
end
def upgrade_plan()
system("vzctl set #{@veid} --applyconfig @plan_id --save")
firewall = new Firewall()
firewall.veid = @veid
firewall.plan_id = @plan_id
firewall.addresses = @addresses
firewall.setup()
end
def downgrade_plan()
system("vzctl set #{@veid} --applyconfig @plan_id --save")
firewall = new Firewall()
firewall.veid = @veid
firewall.plan_id = @plan_id
firewall.addresses = @addresses
firewall.setup()
end
def start()
system("vzctl start #{@veid}")
end
def stop()
system("vzctl stop #{@veid}")
end
def migrate()
system("vzmigrate #{@hardwareNode} #{@veid}")
end
def check_sys_status()
self.sys_status = `vzlist | grep
end
def check_net_status()
end
def check_net_usage()
end
def check_disk_usage()
output = `vzquota -b show
output_array = output.scan(/\w+/)
usage = output_array[0]
softlimit = output_array[1]
hardlimit = output_array[2]
self.disk_usage = ( (usage.to_f / softlimit.to_f ) * 100 )
end
def check_cpu_usage()
end
def check_mem_usage()
usage = `vzmemcheck -A
self.mem_usage = usage[2]
end
def add(args)
usage = <<-"EOF"
usage: #{@MYNAME} [-h] [-v VEID] [-H hostname] [-n "comma,separated,nameservers"] [-o ostemplate]
[[-a "comma,separated,ip_addresses"] [-p plan_id] [-P password] ]
EOF
banner = <<-"EOF"
#{@MYNAME} #{@Version} (#{@MYDATE})
#{usage}
EOF
opts = OptionParser.new
opts.on("-h", "--help", "Show this message") {
print opts
exit 0
}
opts.on("-v", "--veid veid", String, "Virtual Environment Identifiation Number") { |veid| self.veid = veid }
opts.on("-a", "--addresses addresses", String, "Comma Separated List of IP Addresses") { |addresses| self.addresses = addresses }
opts.on("-H", "--hostname hostname", String, "Hostname of server") { |hostname| self.hostname = hostname }
opts.on("-n", "--nameservers nameservers", String, "Comma Separated List of Name Servers") { |nameservers| self.nameservers = nameservers }
opts.on("-o", "--ostemplate ostemplate", String, "Operating System Template") { |ostemplate| self.ostemplate = ostemplate }
opts.on("-p", "--plan_id plan_id", String, "Plan Level") { |plan_id| self.plan_id = plan_id }
opts.on("-P", "--password password", String, "root User Password") { |password| self.password = password }
host = opts.parse(args)
error_string = String.new
if (self.veid == nil)
error_string.concat(" ERROR: VEID required (-v)\n" )
end
if (self.addresses == nil)
error_string.concat( " ERROR: IP Addresses required in a comma separated list (-a)\n" )
end
if (self.hostname == nil)
error_string.concat( " ERROR: fully qualified domain name required (-H)\n" )
end
if (self.nameservers == nil)
error_string.concat( " ERROR: comma separated list of name server IP addresses required (-n)\n" )
end
if (self.ostemplate == nil)
error_string.concat( " ERROR: OS template required (-o)\n" )
end
if (self.plan_id == nil)
error_string.concat( " ERROR: VPS plan ID required (-p)\n" )
end
if (self.password == nil)
error_string.concat( " ERROR: VPS root password required (-P)\n" )
end
if (error_string == "")
self.create
else
puts usage
puts error_string
end
end
def check(args)
usage = <<-"EOF"
usage: #{@MYNAME} [-bhmsnudc] [-v VEID]
EOF
banner = <<-"EOF"
#{@MYNAME} #{@Version} (#{@MYDATE})
#{usage}
EOF
opts = OptionParser.new
opts.on("-h", "--help", "Show this message") {
print opts
exit 0
}
opts.on("-v", "--veid veid", String, "Virtual Environment Identifiation Number") { |veid| self.veid = veid }
opts.on("-m", "--memory", "Check Memory Usage") { |memory| self.check_mem_usage }
opts.on("-s", "--status", "Current Status of Server") { |status| self.check_sys_status }
opts.on("-n", "--netstat", "Check Network Status of Server") { |net_stat| self.check_net_status }
opts.on("-u", "--netuse", "Check Network Bandwidth Usage") { |net_use| self.check_net_usage }
opts.on("-d", "--diskuse", "Check Disk Usage") { |disk_use| self.check_disk_usage }
opts.on("-c", "--cpuuse", "Check CPU Usage") { |cpu_use| self.check_cpu_usage }
opts.on("-b", "--batch", "Batch Mode") { self.batch_mode = true }
host = opts.parse(args)
error_string = String.new
output_string = String.new
if (self.veid == nil)
error_string.concat(" ERROR: VEID required (-v)\n" )
end
if ( self.batch_mode != true )
if (self..mem_usage != nil)
output_string.concat( " Current Memory Usage: #{self.mem_usage} MB\n" )
end
if (self.sys_status != nil)
output_string.concat( " Current Virtual System Status: #{self.sys_status} \n" )
end
if (self.net_status != nil)
output_string.concat( " Current Virtual System Network Status: #{self.net_status} \n" )
end
if (self.net_usage != nil)
output_string.concat( " Current Virtual System Network Usage: #{self.net_usage} \n" )
end
if (self.disk_usage != nil)
output_string.concat( " Current Virtual System Disk Usage: #{self.disk_usage} \n" )
end
if (self.cpu_usage != nil)
output_string.concat( " Current CPU Usage: #{self.cpu_usage} \n" )
end
puts output_string
else
if (self.mem_usage != nil)
puts( "#{self.mem_usage}" )
end
if (self.sys_status != nil)
puts( "#{self.sys_status}" )
end
if (self.net_status != nil)
puts( "#{self.net_status}" )
end
if (self.net_usage != nil)
puts( "#{self.net_usage}" )
end
if (self.disk_usage != nil)
puts( "#{self.disk_usage}" )
end
if (self.cpu_usage != nil)
puts( "#{self.cpu_usage}" )
end
end
if (error_string != "")
puts usage
puts error_string
end
end
end
Posted in OpenVZ, Ruby, Sysadmin | Tags Automation, management, OpenVZ