module RHC

Some parts adapted from golang.org/src/pkg/json/decode.go and golang.org/src/pkg/utf8/utf8.go

Note: A group is a set of parameters defined for a subpart of a config file

Constants

API
APP_NAME_MAX_LENGTH
CLEAR_LINE

reset lines r moves the cursor to the beginning of line ANSI escape code to clear line from cursor to end of line "e" is an alternative to "033" cf. en.wikipedia.org/wiki/ANSI_escape_code

DEBUG_INGORE_KEYS
DEFAULT_DELAY
DEFAULT_MAX_LENGTH
MAX_RETRIES
PATTERN_VERSION

Public Class Methods

check_app(app) click to toggle source
# File lib/rhc-common.rb, line 163
def self.check_app(app)
  check_field(app, 'application', APP_NAME_MAX_LENGTH)
end
check_app_available(net_http, app_name, fqdn, health_check_path, result, git_url, repo_dir, no_git) click to toggle source

An application is considered available if the health check URL unambiguously returns a 1 or 0. Otherwise, if the root URL for the app successfully returns content it is also considered successful. In the future, applications that do not expose a public web interface will need a more advanced check mechanism, or the check should not prevent creation.

# File lib/rhc-common.rb, line 741
  def self.check_app_available(net_http, app_name, fqdn, health_check_path, result, git_url, repo_dir, no_git)

    available = MAX_RETRIES.times.any? do |i|
      sleep i * DEFAULT_DELAY

      puts "Checking if the application is available ##{i+1}"
      if health_check_path and !health_check_path.empty?
        value = open("http://#{fqdn}/#{health_check_path}").read[0,1] rescue nil
        # TODO: I should be typed exception ApplicationHealthFailure
        raise "ERROR: The application was unable to start.  Please report this issue via the forums or IRC or file a bug through our public bug tracker." if value == '0'
        next true if value == '1'
      end
      open("http://#{fqdn}") rescue nil
    end

    if available
      puts "Application #{app_name} is available at: http://#{fqdn}/"
      puts "  Git URL: #{git_url}"

      if @mydebug
        unless no_git
          puts "To make changes to '#{app_name}', commit to #{repo_dir}/."
        else
          puts "To make changes to '#{app_name}', you must first clone it with:
git clone #{git_url}

"
          puts "Then run 'git push' to update your OpenShift space."
        end
      end
      if result && !result.empty?
        puts "#{result}"
      end
      true
    else
      puts "Application is not available"
      false
    end
  rescue StandardError => e
    puts e
    false
  end
check_field(field, type, max=0, val_regex=/[^0-9a-zA-Z]/, regex_failed_error='contains non-alphanumeric characters!') click to toggle source
# File lib/rhc-common.rb, line 176
def self.check_field(field, type, max=0, val_regex=%r[^0-9a-zA-Z]/, 
                     regex_failed_error='contains non-alphanumeric characters!')
  if field
    if field =~ val_regex
      say "#{type} " + regex_failed_error
      return false
    end
    if max != 0 && field.length > max
      say "maximum #{type} size is #{max} characters"
      return false
    end
  else
    say "#{type} is required"
    return false
  end
  field
end
check_key(keyname) click to toggle source
# File lib/rhc-common.rb, line 171
def self.check_key(keyname)
  check_field(keyname, 'key name', DEFAULT_MAX_LENGTH, %r[^0-9a-zA-Z]/, 
              'contains invalid characters! Only alpha-numeric characters allowed.')
end
check_namespace(namespace) click to toggle source
# File lib/rhc-common.rb, line 167
def self.check_namespace(namespace)
  check_field(namespace, 'namespace', DEFAULT_MAX_LENGTH)
end
check_rhlogin(rhlogin) click to toggle source

Invalid chars (") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) () (*) (=) (~)

# File lib/rhc-common.rb, line 150
def self.check_rhlogin(rhlogin)
  if rhlogin
    if rhlogin =~ %r["\$\^<>\|%\/;:,\\\*=~]/
      puts 'OpenShift login may not contain any of these characters: (\") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)'
      return false
    end
  else
    puts "OpenShift login is required"
    return false
  end
  true
end
check_version() click to toggle source
# File lib/rhc-common.rb, line 84
def self.check_version
  if @@api_version =~ PATTERN_VERSION
    if API != @@api_version
      puts "\nNOTICE: Client API version (#{API}) does not match the server (#{@@api_version}).\nThough requests may succeed, you should consider updating your client tools.\n\n"
    end
  end
end
connect_timeout(*vals) click to toggle source
# File lib/rhc-common.rb, line 61
def self.connect_timeout(*vals)
  vals.each do |val|
    if val
      unless val.to_i > 0
        puts 'Timeout must be specified as a number greater than 0'
        exit 1
      end
      @connect_timeout = [val.to_i, @connect_timeout].max
      return @connect_timeout
    end
  end
end
create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false, gear_size='small',scale=false) click to toggle source
# File lib/rhc-common.rb, line 479
  def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false, gear_size='small',scale=false)

    # Need to have a fake HTTPResponse object for passing to print_reponse_err
    # May already be initialized if called from another piece of code
    # FIXME: remove this requirement when refactoring rhc
    begin
      Struct::FakeResponse
    rescue NameError
      Struct.new('FakeResponse',:body,:code,:content_type)
    end

    domains = user_info['user_info']['domains']
    if domains.empty?
      emessage = "Please create a domain with 'rhc domain create -n <namespace>' before creating applications."
      print_response_err(Struct::FakeResponse.new(emessage,403))
    end
    namespace = domains[0]['namespace']
    puts "Creating application: #{app_name} in #{namespace}"
    data = {:cartridge => app_type,
            :action => 'configure',
            :node_profile => gear_size,
            :app_name => app_name,
            :rhlogin => rhlogin
           }
    if @mydebug
      data[:debug] = true
    end    

    # Need to use the new REST API for scaling apps
    #  We'll need to then get the new application using the existing
    #  API in order to access the rest of the logic in this function
    if scale
      end_point = "https://#{libra_server}/broker/rest/api"
      client = RHC::Rest::Client.new(end_point, rhlogin, password)

      domain = client.find_domain(user_info['user_info']['domains'][0]['namespace'])

      namespace = domain.id
      # Catch errors
      begin
        application = domain.add_application(app_name,{:cartridge => app_type, :scale => true, :gear_profile => gear_size})

        # Variables that are needed for the rest of the function
        app_uuid = application.uuid
        result = "Successfully created application: #{app_name}"

        # health check path now returned by the API
        health_check_path = application.health_check_path

        puts "DEBUG: '#{app_name}' creation returned success." if @mydebug
      rescue RHC::Rest::ConnectionException, RHC::Rest::ResourceAccessException => e
        print_response_err(Struct::FakeResponse.new(e.message,e.code))
      rescue RHC::Rest::ValidationException => e
        validation_error_code = (e.code.nil?) ? 406 : e.code
        print_response_err(Struct::FakeResponse.new(e.message, validation_error_code))
      rescue RHC::Rest::ServerErrorException => e
        error_code = (e.code.nil?) ? 500 : e.code
        print_response_err(Struct::FakeResponse.new(e.message, error_code))
      end
    else
      json_data = generate_json(data)

      url = URI.parse("https://#{libra_server}/broker/cartridge")
      response = http_post(net_http, url, json_data, password)

      if response.code == '200'
        json_resp = json_decode(response.body)
        print_response_success(json_resp)
        json_data = json_decode(json_resp['data'])
        health_check_path = json_data['health_check_path']
        app_uuid = json_data['uuid']
        result = json_resp['result']
        puts "DEBUG: '#{app_name}' creation returned success." if @mydebug
      else
        print_response_err(response)
      end
    end

    #
    # At this point, we need to register a handler to guarantee app
    # cleanup on any exceptions or calls to exit
    #
    at_exit do
      unless $!.nil? || $!.is_a?(SystemExit) && $!.success?
        puts "Cleaning up application"
        destroy_app(libra_server, net_http, app_name, rhlogin, password)
      end
    end

    rhc_domain = user_info['user_info']['rhc_domain']

    fqdn = "#{app_name}-#{namespace}.#{rhc_domain}"

    loop = 0
    #
    # Confirm that the host exists in DNS
    #
    unless no_dns
      puts "Now your new domain name is being propagated worldwide (this might take a minute)..."
  
      # Allow DNS to propogate
      sleep 15
  
      # Now start checking for DNS
      sleep_time = 2
      while loop < MAX_RETRIES && !hostexist?(fqdn)
          sleep sleep_time
          loop+=1
          print CLEAR_LINE + "    retry # #{loop} - Waiting for DNS: #{fqdn}"
          $stdout.flush
          sleep_time = delay(sleep_time)
      end
    end
    
    # if we have executed print statements, then move to the next line
    if loop > 0
      puts
    end
    
    # construct the Git URL
    git_url = "ssh://#{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain}/~/git/#{app_name}.git/"

    # If the hostname couldn't be resolved, print out the git URL
    # and exit cleanly.  This will help solve issues where DNS times
    # out in APAC, etc on resolution.
    if loop >= MAX_RETRIES
        puts "
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING: We were unable to lookup your hostname (#{fqdn}) 
in a reasonable amount of time.  This can happen periodically and will just
take an extra minute or two to propagate depending on where you are in the
world.  Once you are able to access your application in a browser, you can then
clone your git repository.

  Application URL: http://#{fqdn}

  Git Repository URL: #{git_url}

  Git Clone command: 
    git clone #{git_url} #{repo_dir}

If you can't get your application '#{app_name}' running in the browser, you can
also try destroying and recreating the application as well using:

  rhc app destroy -a #{app_name} -l #{rhlogin}

If this doesn't work for you, let us know in the forums or in IRC and we'll
make sure to get you up and running.

  Forums: https://openshift.redhat.com/community/forums/openshift

  IRC: #openshift (on Freenode)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

"
        exit 0
    end
    
    #
    # Pull new repo locally
    #
    
    unless no_git
        puts "Pulling new repo down" if @mydebug
    
        quiet = (@mydebug ? ' ' : '--quiet ')
        puts "git clone #{quiet}#{git_url} #{repo_dir}" if @mydebug
        git_clone = %x[git clone #{quiet} #{git_url} #{repo_dir} 2>&1]
        if $?.exitstatus != 0

          if RHC::Helpers.windows? 

            %xnslookup #{app_name}-#{namespace}.#{rhc_domain}`
            windows_nslookup = $?.exitstatus == 0
            %xping #{app_name}-#{namespace}.#{rhc_domain} -n 2`
            windows_ping = $?.exitstatus == 0
            
            if windows_nslookup and !windows_ping # this is related to BZ #826769
              puts "
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING: We were unable to lookup your hostname (#{fqdn}) 
in a reasonable amount of time.  This can happen periodically and will just
take up to 10 extra minutes to propagate depending on where you are in the
world. This may also be related to an issue with Winsock on Windows [1][2]. 
We recommend you wait a few minutes then clone your git repository manually.

  Git Clone command: 
    git clone #{git_url} #{repo_dir}

[1] http://support.microsoft.com/kb/299357
[2] http://support.microsoft.com/kb/811259

If this doesn't work for you, let us know in the forums or in IRC and we'll
make sure to get you up and running.

  Forums: https://openshift.redhat.com/community/forums/openshift

  IRC: #openshift (on Freenode)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

"
              exit 0
            end
          end
          puts "Error in git clone"
          puts git_clone
          exit 216
        end
    else
      if is_embedded_jenkins
        # if this is a jenkins client application to be embedded, 
        # then print this message only in debug mode
        if @mydebug
          puts "
Note: There is a git repo for your Jenkins application '#{app_name}'
but it isn't being downloaded as part of this process.  In most cases
it isn't needed but you can always clone it later.

"
        end
      else         
        puts "
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
IMPORTANT: Since the -n flag was specified, no local repo has been created.
This means you can't make changes to your published application until after
you clone the repo yourself.  See the git url below for more information.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

"
      end
    end
    
    #
    # At this point, we need to register a handler to guarantee git
    # repo cleanup on any exceptions or calls to exit
    #
    unless no_git
      at_exit do
          unless $!.nil? || $!.is_a?(SystemExit) && $!.success?
              puts "Cleaning up git repo"
              FileUtils.rm_rf repo_dir
          end
      end
    end
    return {:app_name => app_name,
            :fqdn => fqdn,
            :health_check_path => health_check_path,
            :git_url => git_url,
            :repo_dir => repo_dir,
            :result => result
           }
  end
ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil, print_result=true) click to toggle source
# File lib/rhc-common.rb, line 795
def self.ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil, print_result=true)
  data = {:action => action,
          :app_name => app_name,
          :rhlogin => rhlogin
         }
  
  data[:server_alias] = server_alias if server_alias
  if framework
    data[:cartridge] = framework
  end
  
  if @mydebug
    data[:debug] = true
  end
  
  json_data = generate_json(data)

  url = nil
  if embedded
    url = URI.parse("https://#{libra_server}/broker/embed_cartridge")
  else
    url = URI.parse("https://#{libra_server}/broker/cartridge")
  end
  response = http_post(net_http, url, json_data, password)
  
  if response.code == '200'
    json_resp = json_decode(response.body)
    print_response_success(json_resp, print_result || @mydebug)
  else
      print_response_err(response)
  end
  json_decode(response.body)
end
debug(bool) click to toggle source
# File lib/rhc-common.rb, line 74
  def self.debug(bool)
    @mydebug = bool
end
delay(time, adj=DEFAULT_DELAY) click to toggle source
# File lib/rhc-common.rb, line 92
def self.delay(time, adj=DEFAULT_DELAY)
  (time*=adj).to_int
end
destroy_app(libra_server, net_http, app_name, rhlogin, password) click to toggle source
# File lib/rhc-common.rb, line 785
def self.destroy_app(libra_server, net_http, app_name, rhlogin, password)
  json_data = generate_json(
                     {:action => 'deconfigure',
                      :app_name => app_name,
                      :rhlogin => rhlogin
                      })
  url = URI.parse("https://#{libra_server}/broker/cartridge")
  http_post(net_http, url, json_data, password)
end
generate_json(data) click to toggle source
# File lib/rhc-common.rb, line 104
def self.generate_json(data)
    data['api'] = API
    json = json_encode(data)
    json
end
get_cartridge_listing(carts, sep, libra_server, net_http, cart_type="standalone", print_result=nil) click to toggle source
# File lib/rhc-common.rb, line 143
def self.get_cartridge_listing(carts, sep, libra_server, net_http, cart_type="standalone", print_result=nil)
  carts = get_cartridges_list(libra_server, net_http, cart_type, print_result) if carts.nil?
  carts.join(sep)
end
get_cartridges_list(libra_server, net_http, cart_type="standalone", print_result=nil) click to toggle source
# File lib/rhc-common.rb, line 110
def self.get_cartridges_list(libra_server, net_http, cart_type="standalone", print_result=nil)
  puts "Obtaining list of cartridges (please excuse the delay)..."
  data = {'cart_type' => cart_type}
  if @mydebug
    data[:debug] = true
  end
  print_post_data(data)
  json_data = generate_json(data)

  url = URI.parse("https://#{libra_server}/broker/cartlist")
  response = http_post(net_http, url, json_data, "none")

  unless response.code == '200'
    print_response_err(response)
    return []
  end
  begin
    json_resp = json_decode(response.body)
  rescue RHC::JsonError
    exit 1
  end
  update_server_api_v(json_resp)
  if print_result
    print_response_success(json_resp)
  end
  begin
    carts = (json_decode(json_resp['data']))['carts']
  rescue RHC::JsonError
    exit 1
  end
  carts
end
get_password() click to toggle source
# File lib/rhc-common.rb, line 349
def self.get_password
  password = nil
  begin
    password = ask_password
  rescue Interrupt
    puts "\n"
    exit 1
  end
  puts "\n"
  password
end
get_ssh_keys(libra_server, rhlogin, password, net_http) click to toggle source

Public: Get a list of ssh keys

type - The String type RSA or DSS. libra_server - The String DNS for the broker rhlogin - The String login name password - The String password for login net_http - The NET::HTTP Object to use

Examples

RHC::get_ssh_keys('openshift.redhat.com',
                  'mylogin@example.com',
                  'mypassword',
                  RHC::Config.default_proxy)
# => { "ssh_type" => "ssh-rsa",
       "ssh_key" => "AAAAB3NzaC1yc2EAAAADAQAB....",
       "fingerprint" => "ea:08:e3:c7:e3:c3:8e:6a:66:34:65:e4:56:f4:3e:ff"}

FIXME! Exits on failure! Should return something instead

Returns Hash on success or exits on failure

# File lib/rhc-common.rb, line 276
def self.get_ssh_keys(libra_server, rhlogin, password, net_http)
  data = {'rhlogin' => rhlogin, 'action' => 'list-keys'}
  if @mydebug
    data[:debug] = true
  end
  print_post_data(data)
  json_data = generate_json(data)

  url = URI.parse("https://#{libra_server}/broker/ssh_keys")
  response = http_post(net_http, url, json_data, password)

  unless response.code == '200'
    if response.code == '401'
      puts "Invalid user credentials"
      exit 97
    else
      print_response_err(response)
    end
    exit 1
  end
  begin
    json_resp = json_decode(response.body)
  rescue RHC::JsonError
    exit 1
  end
  update_server_api_v(json_resp)
  begin
    ssh_keys = (json_decode(json_resp['data'].to_s))
  rescue RHC::JsonError
    exit 1
  end

  # Inject public fingerprint into key.
  begin
    if ssh_keys['ssh_type'].nil? or ssh_keys['ssh_type'].empty?
      ssh_keys['fingerprint'] = nil
    else
      ssh_keys['fingerprint'] =            Net::SSH::KeyFactory.load_data_public_key(
          "#{ssh_keys['ssh_type']} #{ssh_keys['ssh_key']}").fingerprint
    end
  rescue NoMethodError 
    #older net/ssh (mac for example)
    tempfile = %xmktemp /tmp/openshift.XXXXXXXX`
    %xecho "#{ssh_keys['ssh_type']} #{ssh_keys['ssh_key']}" > #{tempfile}`
    ssh_keys['fingerprint'] = %xssh-keygen -lf #{tempfile}`.split(' ')[1]
  rescue Net::SSH::Exception, NotImplementedError, OpenSSL::PKey::PKeyError
    # Could be a new unsupported key type or invalid data on the server
    ssh_keys['fingerprint'] = 'Key type is not recognized.  Please check this key is valid.'
  end

  if ssh_keys['keys'] && ssh_keys['keys'].kind_of?(Hash)
    ssh_keys['keys'].each do |name, keyval|
      type = keyval['type']
      key = keyval['key']
      begin
        ssh_keys['keys'][name]['fingerprint'] =              Net::SSH::KeyFactory.load_data_public_key(
            "#{type} #{key}").fingerprint
      rescue NoMethodError
        #older net/ssh (mac for example)
        tempfile = %xmktemp /tmp/openshift.XXXXXXXX`
        %xecho "#{type} #{key}" > #{tempfile}`
        ssh_keys['keys'][name]['fingerprint'] = %xssh-keygen -lf #{tempfile}`.split(' ')[1]
      rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
        # Could be a new unsupported key type or invalid data on the server
        ssh_keys['keys'][name]['fingerprint'] = 'Key type is not recognized.  Please check this key is valid.'
      end
    end
  end
  ssh_keys
end
get_user_info(libra_server, rhlogin, password, net_http, print_result, not_found_message=nil) click to toggle source
# File lib/rhc-common.rb, line 211
def self.get_user_info(libra_server, rhlogin, password, net_http, print_result, not_found_message=nil)
  data = {'rhlogin' => rhlogin}
  if @mydebug
    data[:debug] = true
  end
  print_post_data(data)
  json_data = generate_json(data)

  url = URI.parse("https://#{libra_server}/broker/userinfo")
  response = http_post(net_http, url, json_data, password)

  unless response.code == '200'
    if response.code == '404'
      if not_found_message
        puts not_found_message
      else
        puts "A user with rhlogin '#{rhlogin}' does not have a registered domain.  Be sure to run 'rhc domain create' before using the other rhc tools."
      end
      exit 99
    elsif response.code == '401'
      puts "Invalid user credentials"
      exit 97
    else
      print_response_err(response)
    end
    exit 1
  end
  begin
    json_resp = json_decode(response.body)
  rescue RHC::JsonError
    exit 1
  end
  update_server_api_v(json_resp)
  if print_result
    print_response_success(json_resp)
  end
  begin
    user_info = json_decode(json_resp['data'].to_s)
  rescue RHC::JsonError
    exit 1
  end
  user_info
end
hostexist?(host) click to toggle source

Check if host exists

# File lib/rhc-common.rb, line 473
def self.hostexist?(host)
    dns = Resolv::DNS.new
    resp = dns.getresources(host, Resolv::DNS::Resource::IN::A)
    return resp.any?
end
http_post(http, url, json_data, password) click to toggle source
# File lib/rhc-common.rb, line 361
def self.http_post(http, url, json_data, password)
  req = http::Post.new(url.path)

  puts "Contacting #{url.scheme}://#{url.host}" if @mydebug
  req.set_form_data({'json_data' => json_data, 'password' => password})
  req['User-Agent'] = RHC::Helpers.user_agent

  http = http.new(url.host, url.port)
  http.open_timeout = @connect_timeout
  http.read_timeout = @read_timeout
  if url.scheme == "https"
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
  begin
    response = http.start {|http| http.request(req)}
    if response.code == '404' && response.content_type == 'text/html'
      # TODO probably want to remove this at some point
      puts "!!!! WARNING !!!! WARNING !!!! WARNING !!!!"
      puts "RHCloud server not found.  You might want to try updating your rhc client tools."
      exit 218
    end
    response
  rescue Exception => e
    puts "There was a problem communicating with the server. Response message: #{e.message}"
    puts "If you were disconnected it is possible the operation finished without being able to report success."
    puts "You can use 'rhc domain show' and 'rhc app status' to learn about the status of your user and application(s)."
    exit 219
  end
end
json_decode(json) click to toggle source
# File lib/rhc-common.rb, line 100
def self.json_decode(json)
  RHC::Json.decode(json)
end
json_encode(data) click to toggle source
# File lib/rhc-common.rb, line 96
def self.json_encode(data)
  RHC::Json.encode(data)
end
print_json_body(json_resp, print_result=true) click to toggle source
print_post_data(h) click to toggle source
# File lib/rhc-common.rb, line 194
def self.print_post_data(h)
  if (@mydebug)
    puts 'Submitting form:'
    h.each do |k,v|
      if k.to_s != 'password'
        puts "#{k.to_s}: #{v.to_s}"
      else
        print 'password: '
        for i in (1..v.length)
          print 'X'
        end
        puts ''
      end
    end
  end
end
print_response_err(response) click to toggle source
print_response_message(message) click to toggle source
print_response_messages(json_resp) click to toggle source
print_response_success(json_resp, print_result=false) click to toggle source
snapshot_create(rhc_domain, namespace, app_name, app_uuid, filename, debug=false) click to toggle source
# File lib/rhc-common.rb, line 829
def self.snapshot_create(rhc_domain, namespace, app_name, app_uuid, filename, debug=false)

  ssh_cmd = "ssh #{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain} 'snapshot' > #{filename}"
  puts "Pulling down a snapshot to #{filename}..."
  puts ssh_cmd if debug
  puts 

  begin

    if ! RHC::Helpers.windows?
      output = %x#{ssh_cmd}`
      if $?.exitstatus != 0
        puts output
        puts "Error in trying to save snapshot.  You can try to save manually by running:"
        puts
        puts ssh_cmd
        puts
        return 1
      end
    else
      Net::SSH.start("#{app_name}-#{namespace}.#{rhc_domain}", app_uuid) do |ssh|
        File.open(filename, 'wb') do |file|
          ssh.exec! "snapshot" do |channel, stream, data|
            if stream == :stdout
              file.write(data)
            else
              puts data if debug
            end
          end
        end
      end
    end
  rescue Exception => e
    puts e.backtrace if debug
    puts "Error in trying to save snapshot.  You can try to save manually by running:"
    puts
    puts ssh_cmd
    puts
    return 1
  end
  true
end
snapshot_restore(rhc_domain, namespace, app_name, app_uuid, filename, debug=false) click to toggle source
# File lib/rhc-common.rb, line 872
def self.snapshot_restore(rhc_domain, namespace, app_name, app_uuid, filename, debug=false)
  if File.exists? filename

    include_git = RHC::Helpers.windows? ? false : RHC::TarGz.contains(filename, './*/git')

    ssh_cmd = "cat #{filename} | ssh #{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
    puts "Restoring from snapshot #{filename}..."
    puts ssh_cmd if debug
    puts 

    begin
      if ! RHC::Helpers.windows?
        output = %x#{ssh_cmd}`
        if $?.exitstatus != 0
          puts output
          puts "Error in trying to restore snapshot.  You can try to restore manually by running:"
          puts
          puts ssh_cmd
          puts
          return 1
        end
      else
        ssh = Net::SSH.start("#{app_name}-#{namespace}.#{rhc_domain}", app_uuid)
        ssh.open_channel do |channel|
          channel.exec("restore#{include_git ? ' INCLUDE_GIT' : ''}") do |ch, success|
            channel.on_data do |ch, data|
              puts data
            end
            channel.on_extended_data do |ch, type, data|
              puts data
            end
            channel.on_close do |ch|
              puts "Terminating..."
            end
            File.open(filename, 'rb') do |file|
              file.chunk(1024) do |chunk|
                channel.send_data chunk
              end
            end
            channel.eof!
          end
        end
        ssh.loop
      end
    rescue Exception => e
      puts e.backtrace
      puts "Error in trying to restore snapshot.  You can try to restore manually by running:"
      puts
      puts ssh_cmd
      puts
      return 1
    end

  else
    puts "Archive not found: #{filename}"
    return 255
  end
  true
end
timeout(*vals) click to toggle source
# File lib/rhc-common.rb, line 48
def self.timeout(*vals)
  vals.each do |val|
    if val
      unless val.to_i > 0
        puts 'Timeout must be specified as a number greater than 0'
        exit 1
      end
      @read_timeout = [val.to_i, @read_timeout].max
      return @read_timeout
    end
  end
end
update_server_api_v(dict) click to toggle source
# File lib/rhc-common.rb, line 78
def self.update_server_api_v(dict)
  if !dict['api'].nil? && (dict['api'] =~ PATTERN_VERSION)
    @@api_version = dict['api']
  end
end