MySQL Gem Installation Under RedHat Enterprise Linux

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 , , ,  | Tags , , ,

Using Mixins With Rails

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 , ,  | Tags ,

Creating XML With Rails 2.1

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 , ,  | Tags ,

gem update One-Liner To Update Everything

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 ,  | Tags , , , ,

Ruby Script For Checking Memory Usage in domU From dom0 in Xen

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}"

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 , , , ,  | Tags , , , , ,

Finding Disk Usage in DomU from Dom0 in 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 , ,  | Tags , , ,

Recursively Counting Lines of Code for An Entire Project Folder

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 , , ,  | Tags , ,

Command Line For Starting Mongrel

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

Installing a Specific gem Package Version

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 Class For Operating OpenVZ

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.

#!/usr/bin/env ruby
#
#  Created by Tres Wong-Godfrey on 2006-11-11.
#  Copyright (c) 2006. All rights reserved.


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


#create 
  def create()
#    firewall = Firewall.new
    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()
=begin
    firewall = Firewall.new
    firewall.veid = @veid
    firewall.plan = @plan_id
    firewall.addresses = @addresses
    firewall.setup
=end

  end


#create_tun_dev
  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

#set nameserver
  def set_nameserver()
    nameserverstring = String.new
    nameservers = @nameservers.to_s
    nameservers.each(',') {|address| nameserverstring.concat(" --nameserver #{address} ")}
    system("vzctl set #{@veid} #{nameserverstring} --save")    
  end

#set password
  def set_password()
    system("vzctl set #{@veid} --userpasswd root:#{@password} --save")

  end

#set hostname
  def set_hostname()
    system("vzctl set #{@veid} --hostname #{@hostname} --save")
  end

#destroy
  def destroy()
    system("vzctl destroy #{@veid}")
    firewall = new Firewall()
    firewall.veid = @veid
    firewall.plan = @plan_id
    firewall.addresses = @addresses
    firewall.delete()
  end

#add_ip
  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

#remove_ip
  def remove_ip()
    system("vzctl set #{@veid} --ipdel all --save")
    @addresses.each {|address| system("vzctl set #{@veid} --ipadd #{address} --save") }
  end

#disable
  def disable()
    old_location = "#{@scriptsDir}/#{@veid}.conf"
    new_location = "#{@backupDir}/#{@veid}.conf"
    self.stop()
    FileUtils.move( old_location, new_location )
  end

#enable
  def enable()
    new_location = "#{@scriptsDir}/#{@veid}.conf"
    old_location = "#{@backupDir}/#{@veid}.conf"
    FileUtils.move( old_location, new_location )
    self.start()
  end

#upgrade
  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

#downgrade
  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

#start
  def start()
    system("vzctl start #{@veid}")
  end

#stop
  def stop()
    system("vzctl stop #{@veid}")
  end

#migrate
  def migrate()
    system("vzmigrate #{@hardwareNode} #{@veid}")
  end

#check_status
  def check_sys_status()
    self.sys_status = `vzlist | grep #{@veid} | awk '{ print $3 }`
  end

#check_net_status
  def check_net_status()

  end

#check_net_usage
  def check_net_usage()

  end


#check_disk_usage
  def check_disk_usage()
    output = `vzquota -b show #{@veid} | head -1`
    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

#check_cpu_usage
  def check_cpu_usage()

  end

#check_memory_usage
  def check_mem_usage()
    usage = `vzmemcheck -A #{@veid} | tail -2 | head -1`
    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 , ,  | Tags , ,