| 1 |
#!/usr/bin/env ruby |
|---|
| 2 |
# |
|---|
| 3 |
# Demonstrates more complex arguments and commands than |
|---|
| 4 |
# math.rb, including a two-phase command (edit). |
|---|
| 5 |
# |
|---|
| 6 |
# == Authors |
|---|
| 7 |
# |
|---|
| 8 |
# * Ben Bleything <bbleything@laika.com> |
|---|
| 9 |
# |
|---|
| 10 |
# == Copyright |
|---|
| 11 |
# |
|---|
| 12 |
# Copyright (c) 2008 LAIKA, Inc. |
|---|
| 13 |
# |
|---|
| 14 |
# This code released under the terms of the BSD license. |
|---|
| 15 |
# |
|---|
| 16 |
# == Version |
|---|
| 17 |
# |
|---|
| 18 |
# $Id$ |
|---|
| 19 |
# |
|---|
| 20 |
|
|---|
| 21 |
require 'rubygems' |
|---|
| 22 |
require 'linen' |
|---|
| 23 |
require 'ostruct' |
|---|
| 24 |
require 'ping' |
|---|
| 25 |
require 'socket' |
|---|
| 26 |
|
|---|
| 27 |
class HostPlugin < Linen::Plugin |
|---|
| 28 |
description "Inspect and check machines on your network." |
|---|
| 29 |
|
|---|
| 30 |
argument :ip, |
|---|
| 31 |
:prompt => 'Please enter the IP address: ', |
|---|
| 32 |
:regex => , |
|---|
| 33 |
:process => lambda { |ip| |
|---|
| 34 |
ip.split('.').each do |octet| |
|---|
| 35 |
octet = octet.to_f |
|---|
| 36 |
|
|---|
| 37 |
fail "#{ip} is not valid: #{octet.to_i} must be between 0 and 255." if octet < 0 or octet > 255 |
|---|
| 38 |
end |
|---|
| 39 |
|
|---|
| 40 |
return ip |
|---|
| 41 |
} |
|---|
| 42 |
|
|---|
| 43 |
argument :hostname, |
|---|
| 44 |
:prompt => 'Please enter the hostname: ', |
|---|
| 45 |
:regex => |
|---|
| 46 |
# pattern yoinked from http://regexlib.com/REDetails.aspx?regexp_id=391 |
|---|
| 47 |
|
|---|
| 48 |
argument :mac, |
|---|
| 49 |
:prompt => 'Please enter the MAC address: ', |
|---|
| 50 |
:process => proc {|mac| |
|---|
| 51 |
stripped_mac = mac.gsub( , '' ) |
|---|
| 52 |
fail "MAC Address is too short." unless stripped_mac.length == 12 |
|---|
| 53 |
fail "MAC Address contains invalid characters." unless stripped_mac =~ |
|---|
| 54 |
|
|---|
| 55 |
return stripped_mac.scan( ).join( ':' ) |
|---|
| 56 |
} |
|---|
| 57 |
|
|---|
| 58 |
command :lookup do |
|---|
| 59 |
help_message "Attempts to do a DNS lookup on the IP or hostname provided." |
|---|
| 60 |
|
|---|
| 61 |
one_of :ip, :hostname |
|---|
| 62 |
|
|---|
| 63 |
action do |
|---|
| 64 |
ip_addr_info = Socket.getaddrinfo( ip, nil ) rescue nil |
|---|
| 65 |
hn_addr_info = Socket.getaddrinfo( hostname, nil ) rescue nil |
|---|
| 66 |
|
|---|
| 67 |
if ip_addr_info |
|---|
| 68 |
say "IP address #{ip} has hostname #{ip_addr_info[0][2]}." |
|---|
| 69 |
elsif hn_addr_info |
|---|
| 70 |
say "Hostname '#{hostname}' has IP address #{hn_addr_info[0][3]}." |
|---|
| 71 |
else |
|---|
| 72 |
say "You said something I do not understand. I am sorry." |
|---|
| 73 |
end |
|---|
| 74 |
end |
|---|
| 75 |
end |
|---|
| 76 |
|
|---|
| 77 |
command :check do |
|---|
| 78 |
help_message "Attempts to ping the IP or hostname provided." |
|---|
| 79 |
|
|---|
| 80 |
one_of :ip, :hostname |
|---|
| 81 |
|
|---|
| 82 |
require_confirmation |
|---|
| 83 |
|
|---|
| 84 |
action do |
|---|
| 85 |
to_check = ip || hostname |
|---|
| 86 |
|
|---|
| 87 |
if Ping.pingecho( to_check, 5 ) |
|---|
| 88 |
say "Host #{to_check} is alive!" |
|---|
| 89 |
else |
|---|
| 90 |
say "Host #{to_check} appears to be dead :(" |
|---|
| 91 |
end |
|---|
| 92 |
end |
|---|
| 93 |
end |
|---|
| 94 |
|
|---|
| 95 |
command :edit, :lookup_first => true do |
|---|
| 96 |
help_message "Lets you pretend to change the host's IP and MAC addresses. Lookup by hostname." |
|---|
| 97 |
|
|---|
| 98 |
lookup_by :hostname do |hostname| |
|---|
| 99 |
out = OpenStruct.new |
|---|
| 100 |
out.hostname = hostname |
|---|
| 101 |
out.ip = Socket.getaddrinfo( hostname, nil )[0][3] |
|---|
| 102 |
|
|---|
| 103 |
# yoinked this from a thread on ruby-talk about UUID generation |
|---|
| 104 |
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/242664 |
|---|
| 105 |
out.mac = ("%012x" % rand(1 << 12*4)).scan( ).join( ':') |
|---|
| 106 |
|
|---|
| 107 |
# return |
|---|
| 108 |
out |
|---|
| 109 |
end |
|---|
| 110 |
|
|---|
| 111 |
inspect do |
|---|
| 112 |
say "Hostname: #{hostname.hostname}" |
|---|
| 113 |
say "IP Address: #{hostname.ip}" |
|---|
| 114 |
say "MAC Address: #{hostname.mac}" |
|---|
| 115 |
end |
|---|
| 116 |
|
|---|
| 117 |
editable_attributes :ip, :mac |
|---|
| 118 |
|
|---|
| 119 |
action do |
|---|
| 120 |
say "If this was real, you would have just changed #{hostname.hostname}'s IP address to " + |
|---|
| 121 |
"#{ip.empty? ? 'nothing' : ip} and its MAC address to #{mac.empty? ? 'nothing' : mac}. " + |
|---|
| 122 |
"It's not real, though, so rest easy." |
|---|
| 123 |
end |
|---|
| 124 |
end |
|---|
| 125 |
end |
|---|
| 126 |
|
|---|
| 127 |
Linen::CLI.prompt = "host > " |
|---|
| 128 |
Linen.start |
|---|