class GaddyGaddy_Client

Public Class Methods

alert(type) click to toggle source
# File lib/gaddygaddy-client.rb, line 437
def self.alert(type)
  alert_timing = case type
                   when :no_config_file
                     {:on => 0.1, :off => 0.1,:alert_text => 'Could not found any gaddy config file in /conf/gaddy_XXXX.gcf'}
                   when :no_network
                     {:on => 1,:off => 1, :alert_text => 'Could not connect to internet, network configuration seems broken, restart when fixed'}
                 end
  begin
    `echo none >/sys/class/leds/led0/trigger`
    count = 0
    send_info_count = 20 / (alert_timing[:on] + alert_timing[:off])
    do_alert = true
    while do_alert do
      if (count % send_info_count) == 0
        puts alert_timing[:alert_text]
        ESpeak.speak alert_timing[:alert_text]
      end
      `echo 1 >/sys/class/leds/led0/brightness`
      sleep alert_timing[:on]
      `echo 0 >/sys/class/leds/led0/brightness`
      sleep alert_timing[:off]
      count += 1
    end
  ensure
    `echo mmc0 >/sys/class/leds/led0/trigger`
  end
end
ip_to_verify() click to toggle source
# File lib/gaddygaddy-client.rb, line 465
def self.ip_to_verify
  '8.8.8.8'
end
network_failed?() click to toggle source
# File lib/gaddygaddy-client.rb, line 469
def self.network_failed?
  ping_result = `ping -w 10 #{ip_to_verify} -c 1`
  ping_result.index("100% packet loss") || ($?.exitstatus !=0)
end
new() click to toggle source
# File lib/gaddygaddy-client.rb, line 55
def initialize
  logger.outputters = Log4r::Outputter.stdout
end
verify_installation() click to toggle source

Verify that we have a conf file and verify network connection

# File lib/gaddygaddy-client.rb, line 481
  def self.verify_installation
    conf_file = Dir.glob(File.join('/','conf', "gaddy*.gcf"))
    alert(:no_config_file) if conf_file.empty?
    if network_failed?
#      install_network
      alert(:no_network)
    end
  end

Public Instance Methods

conf_dir() click to toggle source

Get the config directory

# File lib/gaddygaddy-client.rb, line 230
def conf_dir
  @options[:conf_dir]
end
config_valid() click to toggle source

Check that the config file exist and has valid content, this will also be validated toward the server

# File lib/gaddygaddy-client.rb, line 372
def config_valid
  config_ok = false
  config_file_name = Dir.glob(File.join(conf_dir, @options[:conf_file]))[0]
  logger.debug "Will validate config for #{config_file_name}"
  if File.exists?(config_file_name)
    begin
      conf_file = File.open(config_file_name)
      config = JSON.parse(conf_file.read)
    rescue Exception => e
      raise "Could not read from file #{config_file_name}"
    end
    logger.debug "Have read from file #{config_file_name}"
    config_ok = config["device_id"]
  end
  # TODO validate the client against the client service
  config_ok
end
create_gaddy(gaddy_name, user_name, password) click to toggle source
# File lib/gaddygaddy-client.rb, line 310
def create_gaddy(gaddy_name, user_name, password)
  url = Request.get_base_url(get_host) + "/installation/device/1"
  params = {:device_name => gaddy_name,
            :user_name => user_name,
            :user_password => password
  }
  response = Request.client_service_post url, params
  logger.debug "The response for the request is #{response} #{response.class}"
  raise JCouldNotPostClientDataException.new({:message=> "Could not post data to the gaddygaddy service, error code is #{response.body}"}) unless response[:status].to_i == 0
end
create_new?(name, type) click to toggle source
# File lib/gaddygaddy-client.rb, line 321
def create_new?(name, type)
  inp = ''
  unless @options[:create]
    puts "#{type} #{name} doesn't exist, would you like to create it (Y/N)"
    answer = nil
    while answer.nil?
      inp = gets.chomp.upcase
      if inp
        answer = ['Y','N'].index(inp[0]) ? inp : nil
      else
        puts
        puts "#{type} #{name} doesn't exist, would you like to create it (Y/N)"
      end
    end
  end
  @options[:create] || (inp == 'Y')
end
create_user(user_name, password) click to toggle source

Create a new user

# File lib/gaddygaddy-client.rb, line 296
def create_user(user_name, password)
  url = Request.get_base_url(get_host) + "/user/1"
  params = {
    :model =>
      {
        :user_email => URI.encode(user_name),
        :user_password => password
      }
  }.to_json
  response = Request.client_service_post url, params
  logger.debug "The response for the request is #{response} #{response.class}"
  raise JCouldNotPostClientDataException.new({:message=> "Could not post data to the gaddygaddy service, error code is #{response.body}"}) unless response[:status].to_i == 0
end
gaddy_config(gaddy_name, user_name, password) click to toggle source

Get the gaddy configuration and place it in /conf named gaddy_NAME.gcf

# File lib/gaddygaddy-client.rb, line 340
def gaddy_config(gaddy_name, user_name, password)
  raise "You need to pass name of gaddy, username and password as parameters, see gaddygaddy-client gaddy_file --help" unless gaddy_name && password && user_name
  begin
    FileUtils.mkdir_p conf_dir
  rescue Exception => e
    raise e.inspect
  end
  puts "1"
  begin
    status_gaddy = get_conf_file['status']
  rescue RestClient::Unauthorized => e
    if create_new?(user_name, 'User')
      logger.info "Will create a new user #{user_name}"
      create_user(user_name, password)
    end
    status_gaddy = get_conf_file['status']
  end
  if status_gaddy == 12 || status_gaddy == 4
    if create_new?(gaddy_name, 'Gaddy')
      logger.info "Will create a new gaddy named #{gaddy_name}"
      create_gaddy(gaddy_name, user_name, password)
      if get_conf_file['status'] == 12
        puts "Can't find gaddy with name #{name}"
      end
    else
      puts "Can't find gaddy with name #{name}"
      puts 'If you would like to create it add parameter --create to the command'
    end
  end
end
get_chef_config() click to toggle source
# File lib/gaddygaddy-client.rb, line 253
def get_chef_config
  begin
    FileUtils.mkdir_p conf_dir
  rescue Exception => e
    raise e.inspect
  end
  conf_content = get_chef_config_file
  chef_config = conf_content['variables']
  chef_config['run_list'] = conf_content['run_list']

  conf_file = File.open File.join(conf_dir, CONFIG_FILE_NAME), "w"
  conf_file.write chef_config.to_json
  conf_file.close
end
get_chef_config_file() click to toggle source
# File lib/gaddygaddy-client.rb, line 246
def get_chef_config_file
  response = Request.client_service_get get_host, "/chef/node_json/1/#{gg_config.user_id_salt}/#{gg_config.device_id}/#{gg_config.token}"
  raise "Could not get config file for device #{gg_config.device_id}" unless response["run_list"].length > 0
  logger.debug "Got config file: #{response}"
  response
end
get_conf_file() click to toggle source

Get the config file and return the response

# File lib/gaddygaddy-client.rb, line 277
def get_conf_file
  name = @options[:gaddy_name]
  conf_content = get_gaddy_config(name, @options[:user_name], @options[:password])
  gaddy_file_name = "gaddy_#{name}.gcf"
  conf_file_name = File.join(conf_dir, gaddy_file_name)
  if conf_content['device_name'] && conf_content['device_name'] == name
    begin
      conf_file = File.open conf_file_name, "w"
      conf_file.write conf_content.to_json
      conf_file.close
      logger.info "Have created the configuration file for the gaddy in #{conf_file_name}"
    rescue
      logger.error "Could not write configuration #{conf_file_name}"
    end
  end
  conf_content
end
get_gaddy_config(name, user, password) click to toggle source
# File lib/gaddygaddy-client.rb, line 268
def get_gaddy_config(name, user, password)
  path = URI.encode("/device/config_file/1/#{name}?user_name=#{user}&user_password=#{password}").gsub('+', '%2B')
  response = Request.client_service_get get_host, path
  logger.debug "Got config file: #{response}"
  response
end
get_host() click to toggle source

Should try to get the host from options or config

# File lib/gaddygaddy-client.rb, line 236
def get_host
  host = @options[:host]
  # This is a temporary fix to handle the move to Amazon
  if host == 'ap.gaddygaddy.com:86'
    host = 'ap-pre.gaddygaddy.com:86'
  end
  host
end
gg_config() click to toggle source
# File lib/gaddygaddy-client.rb, line 225
def gg_config
  @gg_config ||= GGConfig.new(:conf_dir => @options[:conf_dir], :conf_file => @options[:conf_file])
end
hardware_id() click to toggle source

Get a device id, to start with only implemented for Raspberry

# File lib/gaddygaddy-client.rb, line 391
def hardware_id
  hardware_id = `cat /proc/cpuinfo|grep Serial`.strip[10..-1].to_s.strip
  logger.debug "The device id is #{hardware_id}"
  if hardware_id == ""
    hardware_id = 'test_device'
  end
  raise JNoDeviceIDFound.new({:message => "Could not found a device id for this computer, a device id is needed, see further help"}) unless hardware_id
  hardware_id
end
install_network() click to toggle source

Will run chef for network config to try to install network

# File lib/gaddygaddy-client.rb, line 475
  def install_network
#    chef_cmd = CHEF_CMD + '
#    run_cmd()
  end
read_options() click to toggle source
# File lib/gaddygaddy-client.rb, line 67
def read_options
  # This hash will hold all of the options
  # parsed from the command-line by
  # OptionParser.
  @options = {}


  global_options do |opts|
    opts.banner = "Usage: gaddygaddy-client [options] [subcommand [options]]"
    opts.description = "GaddyGaddy client for the GaddyGaddy service"
    opts.separator ""
    opts.separator "Global options are:"

    @options[:conf_dir] = DEFAULT_CONF_DIR
    opts.on( '--config_dir CONF-DIR', "Directory containing the client configuration files, default is #{DEFAULT_CONF_DIR}" ) do |conf_dir|
      @options[:conf_dir] = conf_dir
    end

    @options[:conf_file] = DEFAULT_CONF_FILE
    opts.on( '--config_file CONF-FILE', "File name (without) path for the configuration file, default is #{DEFAULT_CONF_FILE}" ) do |conf_file|
      @options[:conf_file] = conf_file
    end

    @options[:log_file] = nil
    opts.on( '-L', '--logfile FILE', 'Write log to FILE, defaults to STDOUT' ) do|file|
      @options[:log_file] = file
    end

    @options[:file_host] = "config2.gaddygaddy.com"
    opts.on( '--file_host FILE_HOST', 'The file host to get files like cookbooks from' ) do|file_host|
      @options[:file_host] = file_host
    end

    @options[:host] = "https://www.gaddygaddy.com:8012"
    opts.on( '-H', '--host HOST', 'The host to connect to' ) do|host|
      @options[:host] = host
    end

    @options[:log_level] = 'info'
    opts.on( '-l', '--log_level level', 'Set the log level (debug, info, warn, error, fatal)' ) do|level|
      @options[:log_level] = level
    end

    @options[:test_mode] = false
    opts.on( '--test_mode', 'Used for testing, will only retry once for example' ) do
      @options[:test_mode] = true
    end

    @options[:token] = nil
    opts.on( '-t', '--token TOKEN', 'The token to be used to access' ) do|token|
      @options[:token] = token
    end



  end

  add_help_option

  command :get_cookbooks do |opts|
    opts.banner = "Usage: get_cookbooks [options]"
    opts.description = "Will download the cookbooks from the GaddyGaddy service"
    @options[:chef_dir] = DEFAULT_CHEF_DIR
    opts.on( '--chef_dir CHEF-DIR', "The chef dir to place the files into, default is #{DEFAULT_CHEF_DIR}" ) do |chef_dir|
      @options[:chef_dir] = chef_dir
    end
    @options[:cookbooks_version] = nil
    opts.on( '--cookbooks_version COOKBOOKS_VERSION', "Override the setting of which cookbook version to download" ) do |cookbooks_version|
      @options[:cookbooks_version] = cookbooks_version
    end
  end

  command :chef_config do |opts|
    opts.banner = "Usage: chef_config [options]"
    opts.description = "Will download the chef config and place it in a directory"
  end

  command :gaddy_file do |opts|
    opts.banner = "Usage: gaddy_file [options]"
    opts.description = "Will download the gaddy config and place it in /conf"
    opts.on("-g", "--gaddy gaddy_name", "Name of gaddy") do |gaddy_name|
      @options[:gaddy_name] = gaddy_name
    end
    opts.on("-u", "--user user_name", "User name") do |user_name|
      @options[:user_name] = user_name
    end
    opts.on("-p", "--password password", "Password") do |password|
      @options[:password] = password
    end
    opts.on("-c", "--create", "Create new gaddy if it doesn't exist") do
      @options[:create] = true
    end
  end

  command :send_device_data do |opts|
    opts.banner = "Usage: send_device_data [options]"
    opts.description = "Will send information about the gaddy to gaddygaddy.com"
  end

  command :upload_diagnose_data do |opts|
    opts.banner = "Usage: upload_diagnose_data[options]"
    opts.description = "Will upload diagnose data"
  end

  command :upload_log_file do |opts|
    opts.banner = "Usage: upload_log_file[options]"
    opts.description = "Will upload log files"
    @options[:lines] = 100
    opts.on("-i", "--lines lines", "Number of lines to upload, count from end of file") do |lines|
      @options[:lines] = lines
    end
    opts.on("-f", "--id function_id", "Function id") do |function_id|
      @options[:function_id] = function_id
    end
    @options[:upload_log_file] = nil
    opts.on("-u", "--upload_log_file upload_log_file", "Name of log file to upload, mandatory") do |upload_log_file|
      @options[:upload_log_file] = upload_log_file
    end
  end

  command :verify_installation do |opts|
    opts.banner = "Usage: verify_installation[options]"
    opts.description = "Will verify the installation and check for gaddy file and network configuration"
  end

  command :notify do |opts|
    opts.banner = "Usage: verify_installation[options]"
    opts.description = "Will verify the installation and check for gaddy file and network configuration"
    @options[:event] = nil
    opts.on("-e", "--event event", "Event to notify, should be json format") do |event|
      @options[:event] = event
    end
  end

  cmd = nil
  begin
    cmd = opt_parse
    mandatory =  []
    missing = mandatory.select{ |param| @options[param].nil? }
    unless missing.empty?
      puts "Missing options: #{missing.join(', ')}"                  #
      puts opt_parse                                                  #
      exit 1
    end
    unless cmd
      puts "No command is specified\n\n"
      usage
      puts print_actions
      exit 1
    end
  rescue OptionParser::InvalidOption, OptionParser::MissingArgument      #
    puts $!.to_s                                                           # Friendly output when parsing fails
    puts opt_parse                                                          #
    exit 1                                                                #
  end
  cmd
end
read_settings() click to toggle source
# File lib/gaddygaddy-client.rb, line 490
def read_settings
  environment = ENV['RACK_ENV'] || ENV['ENV'] || 'gaddy'
  YAML.load(File.read(File.join(File.dirname(__FILE__), '..','conf', "#{environment}.yml")))
end
run() click to toggle source
# File lib/gaddygaddy-client.rb, line 495
def run
  cmd = read_options
  settings = read_settings
  begin
    Retriable.set_test_mode if @options[:test_mode]
    @device_info = DeviceInfo.new(get_host, gg_config)
    set_log_level @options[:log_level]
    set_log_file @options[:log_file] if @options[:log_file]
    logger.info "Will start #{APPLICATION_NAME} with command #{cmd}"
    case cmd
      when "get_cookbooks"
        chef_files = ChefFiles.new(gg_config, get_host, @options[:chef_dir])
        chef_files.get_cookbooks @options[:file_host], @options[:cookbooks_version]
      when "chef_config"
        get_chef_config
      when 'gaddy_file'
        gaddy_config(@options[:gaddy_name], @options[:user_name], @options[:password])
      when 'send_device_data'
        send_device_data
      when "verify_installation"
        self.class.verify_installation
      when 'notify'
        Notification::FileNotification.file_dir = settings['file_dir']
        notification = Notification::Send.new(:speech_enabled => settings['speech_enabled'])
        notification.event = @options[:event]
        notification.notify gg_config.device_id
      when 'upload_diagnose_data'
        upload_diagnose_data
      when 'upload_log_file'
        upload_log_file
      else
        usage
        raise "No valid command entered, the command is #{cmd}"
    end

  rescue Exception => e
    logger.error e.message
    logger.error "Enable full stack trace with -l DEBUG" unless logger.debug?
    logger.error "Backtrace:\n\t#{e.backtrace.join("\n\t")}" if logger.debug?
    exit -1
  end
end
send_device_data() click to toggle source

Will send ohai device data to gaddygaddy

# File lib/gaddygaddy-client.rb, line 402
def send_device_data
  @device_info.post
end
upload_diagnose_data() click to toggle source
# File lib/gaddygaddy-client.rb, line 406
def upload_diagnose_data
  url = Request.get_base_url(get_host) + "/device/upload_diagnose_data/1/#{gg_config.user_id_salt}/#{gg_config.device_id}/#{gg_config.token}"
  diagnose_data = DiagnoseData.get_all_diag_info
  params = {:diagnose_data => diagnose_data,
            :diagnose_time_stamp => Time.now
  }
  response = Request.client_service_post url, params
  logger.debug "The response for the request is #{response} #{response.class}"
  raise JCouldNotPostClientDataException.new({:message=> "Could not post data to the gaddygaddy service, error code is #{response.body}"}) unless response[:status].to_i == 0
end
upload_log_file() click to toggle source
# File lib/gaddygaddy-client.rb, line 417
def upload_log_file
  raise "Missing option upload_log_file" unless @options[:upload_log_file]
  log_file_name = @options[:upload_log_file].split('/').last
  log_file_name = log_file_name[0..-5] if log_file_name[-4..-1] == '.log'
  logger.debug "Log file name is #{log_file_name}"
  full_log_file_name = @options[:upload_log_file]
  url = Request.get_base_url(get_host) + "/device/upload_log_file/1/#{gg_config.user_id_salt}/#{gg_config.device_id}/#{gg_config.token}/#{log_file_name}"
  log_data = LogData.get_log_data(@options[:upload_log_file], @options[:lines])
  log_time_stamp = LogData.get_log_file_time(@options[:upload_log_file])
  params = {:log_data => log_data,
            :log_time_stamp => log_time_stamp,
            :full_log_file_name => full_log_file_name,
  }
  params[:function_id] = @options[:function_id] if @options[:function_id]
  response = Request.client_service_post url, params
  logger.debug "The response for the request is #{response} #{response.class}"
  raise JCouldNotPostClientDataException.new({:message=> "Could not post data to the gaddygaddy service, error code is #{response.body}"}) unless response[:status].to_i == 0
end
usage() click to toggle source
# File lib/gaddygaddy-client.rb, line 59
def usage
  puts "gaddygaddy-client [OPTIONS]"
  puts "The client to run for the GaddyGaddy service"
  puts "For more information about the commands run gaddygaddy-client --help"
  puts "Revision :#{REVISION}"
  puts
end