Zuzur's corner technology, the web, programming and a bit of this and that …

31Oct/10Off

Notebook: MacBook – Battery calibation

A few weeks ago, my apr'09 13" MacBook started behaving strangely. After a few minutes off the power cord, it would simply shutdown without warning (no display of the low battery warning message ... blam ! Black screen of death). The led battery indicators would show the battery to be at 80%, and if you started the laptop again, it would work for 5-10 minutes ... then blam !

I've looked for solutions to this issue for a while, this behaviour didn't match apple's documents about battery calibration / PMU reset in their knowledge base, i've tried following every steps documented there (links provided below) to no avail.

resetting the SMC
resetting the PRAM and NVRAM

I finally managed to get back to a properly running mac after following those instructions (Battery calibration) to the letter.

When the system would shutdown improperly, i would just start it up again until next time, and did this for 2 hours (about 6 or 7 power off / power on cycles) until the battery was completely depleted.

Then, i performed a full charge, allowing the system to rest for a few hours while on battery, powered it on, removed the battery adapter with my fingers crossed ... and ... I got my macbook back ! spacer Woooot spacer

Tagged as: apple, battery, sysadmin No Comments
31Oct/10Off

scripting with chef

Chef is a very cool platform management solution. Once it is setup, you have a very clean solution to distribute server configurations across as many servers as you need, very cleanly (Ruby DSL) and quickly. A must on AWS.

One thing that you can't find easily in Chef's documentation is how to use the chef API to write scripts that would use the information chef is storing.

Imagine having a script that would run regularly (cron) and update your internal DNS zone with A records for each server it can find in your chef database.

I'm not sure I used the "right" approach. I just pasted some code i borrowed from knife (chef's command-line tool) and added it to my own script. I intend to find a cleaner approach later (mixins, inheritance, etc ...)

#!/usr/bin/env ruby
require 'rubygems'
require 'chef/application'
require 'chef/client'
 
require 'mixlib/cli'
 
class Client < Chef::Application
  include Mixlib::CLI
 
  banner "Usage: #{$0} (options)"
 
  option :config_file, 
    :short => "-c CONFIG",
    :long  => "--config CONFIG",
    :description => "The configuration file to use"
 
  option :log_level, 
    :short        => "-l LEVEL",
    :long         => "--log_level LEVEL",
    :description  => "Set the log level (debug, info, warn, error, fatal)",
    :proc         => lambda { |l| l.to_sym }
 
  option :log_location,
    :short        => "-L LOGLOCATION",
    :long         => "--logfile LOGLOCATION",
    :description  => "Set the log file location, defaults to STDOUT",
    :proc         => nil
 
  option :editor,
    :short        => "-e EDITOR",
    :long         => "--editor EDITOR",
    :description  => "Set the editor to use for interactive commands",
    :default      => ENV['EDITOR']
 
  option :no_editor,
    :short        => "-n",
    :long         => "--no-editor",
    :description  => "Do not open EDITOR, just accept the data as is",
    :boolean      => true
 
  option :help,
    :short        => "-h",
    :long         => "--help",
    :description  => "Show this message",
    :on           => :tail,
    :boolean      => true
 
  option :node_name,
    :short => "-u USER",
    :long => "--user USER",
    :description => "API Client Username"
 
  option :client_key,
    :short => "-k KEY",
    :long => "--key KEY",
    :description => "API Client Key"
 
  option :chef_server_url,
    :short => "-s URL",
    :long => "--server-url URL",
    :description => "Chef Server URL"
 
  option :yes,
    :short => "-y",
    :long => "--yes",
    :description => "Say yes to all prompts for confirmation"
 
  option :defaults,
    :long => "--defaults",
    :description => "Accept default values for all questions"
 
  option :print_after,
    :short => "-p",
    :long => "--print-after",
    :description => "Show the data after a destructive operation"
 
  option :format,
    :short => "-F FORMAT",
    :long => "--format FORMAT",
    :description => "Which format to use for output",
    :default => "json"
 
  option :version,
    :short        => "-v",
    :long         => "--version",
    :description  => "Show chef version",
    :boolean      => true,
    :proc         => lambda {|v| puts "Chef: #{::Chef::VERSION}"},
    :exit         => 0
 
  def configure_chef
    unless config[:config_file]
      full_path = Dir.pwd.split(File::SEPARATOR)
      (full_path.length - 1).downto(0) do |i|
        config_file_to_check = File.join([ full_path[0..i], ".chef", "client.rb" ].flatten)
        if File.exists?(config_file_to_check)
          config[:config_file] = config_file_to_check 
          break
        end
      end
      # If we haven't set a config yet and $HOME is set, and the home
      # knife.rb exists, use it:
      if (!config[:config_file]) && ENV['HOME'] && File.exist?(File.join(ENV['HOME'], '.chef', 'client.rb'))
        config[:config_file] = File.join(ENV['HOME'], '.chef', 'client.rb')
      end
    end
 
    # Don't try to load a knife.rb if it doesn't exist.
    if config[:config_file]
      Chef::Config.from_file(config[:config_file])
    else
      # ...but do log a message if no config was found.
      self.msg("No knife configuration file found")
    end
 
    Chef::Config[:log_level] = config[:log_level] if config[:log_level]
    Chef::Config[:log_location] = config[:log_location] if config[:log_location]
    Chef::Config[:node_name] = config[:node_name] if config[:node_name]
    Chef::Config[:client_key] = config[:client_key] if config[:client_key]
    Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
    Mixlib::Log::Formatter.show_time = false
    Chef::Log.init(Chef::Config[:log_location])
    Chef::Log.level(Chef::Config[:log_level])
 
    Chef::Log.debug("Using configuration from #{config[:config_file]}")
 
    if Chef::Config[:node_name].nil?
      raise ArgumentError, "No user specified, pass via -u or specifiy 'node_name' in #{config[:config_file] ? config[:config_file] : "~/.chef/knife.rb"}"
    end
  end
 
 
  def parse_options(args=[]) 
    super
    config    
  end
 
  def run(args)
    parse_options(args)
    configure_chef
    Chef::Search::Query.new.search(:node,"*:*") do |n|
       ## iterate on every node. You have access to every information
       ## chef and ohai could collect from the nodes
    end
  end
end
 
Client.new.run

The command line options for your script are the same as knife's. And it works flawlessly.

Tagged as: chef, sysadmin No Comments
12Oct/10Off

notebook: running a unix command for a given amount of time

Sometimes, you need to run a command (capture, etc ...) for a given amount of time. Here's an example of a script capturing mysql traffic for half an hour :

#!/bin/sh
DATE=`date +%Y%m%d%H%M%S`
tcpdump -i eth0 port 3306  -s 65535 -x -n -q -tttt > capture-$DATE.out &
sleep 1800 
kill $!
Tagged as: notebook, shell, unix 1 Comment
10Oct/10Off

notebook: nagios / ndo2db on centOS 5.5 64 bits

Trying to setup nagios 3.1 with ndo2db on a 64bits platform, ndo2bd may not work properly and crash over and over.

The symptoms are:

[1286679019] ndomod: Still unable to connect to data sink.  7575 items lost, 5000 queued items to flush.

in the nagios log file
and /var/log/messages containing reports of ndo2db segfaults ...

Oct 10 12:52:26 ip-10-112-41-174 kernel: ndo2db[15666]: segfault at 00007fff8701cff8 rip 00002aaaabf2d211 rsp 00007fff8701d000 error 6

Apparently, this comes from ndo2db being improperly linked to a 32bits version of the mysql client lib.

You need to configure ndo2db like this :

./configure --prefix=/opt/nagios --enable-mysql --disable-pgsql --with-ndo2db-user=nagios --with-ndo2db-group=nagios --with-mysql-lib=/usr/lib/mysql

then you can go on and install ndo2db as documented, nagios will happily log events into you supervision database

Tagged as: nagios linux sysadmin 1 Comment
4Oct/10Off

Some fun with groovy and AWS Identity And Access Management

I'm currently playing with the all new AWS identity and access management, and wanted to share some groovy magic to play with users and groups ...

@Grapes([
  @Grab(group='com.amazonaws', module='aws-java-sdk', version='1.0.11')
])
 
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient
import com.amazonaws.services.identitymanagement.model.*
 
AWS_ACCESS_KEY='MY AWESOME KEY'
AWS_SECRET_KEY='MY EVEN MORE AWESOME KEY'
 
def cred = new BasicAWSCredentials(AWS_ACCESS_KEY,AWS_SECRET_KEY)
 
def ami = new AmazonIdentityManagementClient(cred)
 
println "Group 'Administrators' ?"
 
def admins = null
try {
 admins = ami.getGroup(new GetGroupRequest().withGroupName('Administrators'))?.group
} catch (NoSuchEntityException e) {
  println "Didn't find group 'Administrators' : creating it ..."
  admins = ami.createGroup(new CreateGroupRequest().withGroupName('Administrators')).group
}
println admins
 
println "User 'erwan' ?"
def erwan = null
 
try {
  erwan = ami.getUser(new GetUserRequest().withUserName('erwan'))?.user
} catch (NoSuchEntityException e) {
  println "Didn't find user 'erwan' : creating it ..."
  erwan = ami.createUser(new CreateUserRequest().withUserName('erwan')).user
}
 
println erwan
 
if 



gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.