#!/usr/bin/env oo-ruby
#--
# Copyright 2014 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++

require 'etc'
require 'fileutils'
require 'openshift-origin-node'
require 'openshift-origin-node/utils/cgroups/libcgroup'

require 'commander/import'
$name = File.basename __FILE__

program :name, $name
program :version, %q(1.0.0)
program :description, %q(Perform operation on gear)
program :help, 'Copyright', %q(2014 Red Hat, Inc)
program :help, 'License', %q(ASL 2.0)
program :help, 'Note #1', %q(This command should be run as root)
program :int_message, %q(Warning: Processing was interrupted before it could complete.)

unless 'root' == Etc.getpwuid(Process::uid).name
  $stderr.puts("Must be run as root\n Use #{$name} --help to obtain help")
  exit! 1
end

global_option('-c', '--with-container-uuid UUID', 'Unique identifier for the gear, if provided must be first argument')

def usage(message, details = nil)
  $stderr.puts details + "\n\n" if details
  $stderr.puts "Usage: #{message}"
  exit! 255
end

def run(command, options = Commander::Command::Options.new)
  puts command if options.trace
  output = %x[#{command} 2>&1].squeeze
  puts %Q(#{command}:\n  #{output}) unless $?.exitstatus == 0 || output.empty?
end

def rm(path, options = Commander::Command::Options.new)
  Dir[path].each do |file|
    puts %Q(Deleting file: #{file})
    FileUtils.rm_r(file, verbose: options.trace)
  end
end

command :destroygear do |c|
  c.syntax      = %Q(#{$name} #{c.name} --with-container-uuid UUID)
  c.description = %q(Remove any remnants of a failed gear destroy)

  c.option '-f', '--fqdn FQDN', 'Fully Qualified Domain Name'
  c.action do |_, options|
    if options.with_container_uuid.nil? || options.with_container_uuid.empty?
      usage(c.syntax)
    end

    fqdn = %x[grep #{options.with_container_uuid} /var/lib/openshift/.httpd.d/nodes.txt |awk -F '( |/)' '{print $1}']
    fqdn = fqdn.split("\n").first.chomp unless fqdn.empty?
    options.default fqdn: fqdn

    begin
      path  = Dir["/cgroup/*/openshift/#{options.with_container_uuid}/freezer.state"].first
      state = IO.read(path).chomp
      puts %Q(Gear cgroup state: #{state}) if options.trace
      unless state == 'THAWED'
        puts 'Thawing gear...'
        IO.write(path, 'THAWED')
      end
    rescue
    end

    uid = Etc.getpwnam(options.with_container_uuid).uid rescue nil
    if uid.nil?
      puts "Killing gear processes for name:#{options.with_container_uuid}..."
      # Killing off processes without a passwd entry is hard...
      run %Q(/usr/bin/skill -9 #{options.with_container_uuid})

      tasks = IO.read Dir["/cgroup/*/openshift/#{options.with_container_uuid}/tasks"].first rescue nil
      unless tasks.nil? || tasks.empty?
        run %Q(/bin/kill -9 -- #{tasks.gsub("\n", ' ')})
      end
    else
      puts "Killing gear processes for uid:#{uid}..."
      run %Q(/usr/bin/pkill -9 -u #{uid})
    end

    if uid
      puts 'Deleting unix account...'
      run %Q(/usr/sbin/userdel --remove --force #{options.with_container_uuid})
    end

    rm %Q(/var/lib/openshift/.tc_user_dir/#{options.with_container_uuid}_throttle), options
    rm %Q(/var/lib/openshift/#{options.with_container_uuid}), options
    rm %Q(/var/lib/openshift/.last_access/#{options.with_container_uuid}), options
    rm %Q(/etc/security/limits.d/*-#{options.with_container_uuid}.conf), options

    begin
      puts 'Deleting cgroup info...'
      OpenShift::Runtime::Utils::Cgroups::Libcgroup.new(options.with_container_uuid).delete
    rescue => e
      puts "Failed to delete cgroup info: #{e.message}"
      puts e.backtrace.join("\n") if options.trace
    end

    begin
      $stdout.write "Deleting stale info from /var/lib/openshift/.httpd.d/ files...\n  for #{options.with_container_uuid}"
      OpenShift::Runtime::FrontendHttpServer.purge(options.with_container_uuid)

      if options.fqdn && ! options.fqdn.empty?
        $stdout.write "\n  for #{options.fqdn}"
        OpenShift::Runtime::FrontendHttpServer.purge(options.fqdn)
      else
        $stdout.write %Q[\n  (You may need to use the --fqdn option to remove any remaining configuration.)]
      end
      puts
    rescue => e
      puts "\nFailed to delete .httpd.d info: #{e.message}"
      puts e.backtrace.join("\n") if options.trace
    end
  end
end
