#!/usr/bin/env ruby require 'optparse' require 'uri' require 'methadone' require 'filesize' require 'securerandom' require 'uricp' class App include Methadone::Main include Methadone::SH include Methadone::CLILogging main do |from_uri, to_uri,| options['from_uri'] = URI(from_uri) options['to_uri'] = URI(to_uri) options['auth_uri'] = select_auth_url if options['segment-size'] options['segment-size'] = Filesize.from(options['segment-size']) end if options['max-cache'] options['max-cache'] = Filesize.from(options['max-cache']) end validate_options Uricp::OrbitAuth.validate_options(options) set_auth_env Uricp::OrbitAuth.add_auth_token(options) add_cache_name add_temp_area run_command end def self.set_auth_env cla = "" cla << "--auth-user='#{options['auth-user']}' " if options['auth-user'] cla << "--auth-key='#{options['auth-key']}' " if options['auth-key'] cla << "--auth-token='#{options['auth-token']}' " if options['auth-token'] ENV['URICP'] = cla unless cla.empty? debug "#{self.name} Environment Command Line Args are: #{ENV['URICP']}" end def self.run_command command_list = build_command if options['dry-run'] info "Would execute:\n###\n#{command_list}\n###" else sh! pipefail_wrapper(command_list), :on_fail => "Copy from #{options['from_uri']} to #{options['to_uri']} failed" end end def self.build_command command_sequence = Uricp::UriStrategy.choose_strategy(options) debug "#{self.name} Command sequence is #{command_sequence.inspect}" command_sequence.map do |c| debug c.class.name c.command end.join('') end def self.validate_options case when options['from_uri'].path.nil? raise ::OptionParser::InvalidArgument, "'from_uri' has missing path" when options['to_uri'].path.nil? raise ::OptionParser::InvalidArgument, "'to_uri' has missing path" end return if options['cache'] case when options['target-format'] raise ::OptionParser::MissingArgument, "'target-format' requires 'cache' option" when options['max-cache'] raise ::OptionParser::MissingArgument, "'max-cache' requires 'cache' option" end end def self.add_cache_name if options['cache'] options['cache_name'] = File.basename(options['from_uri'].path) end end def self.add_temp_area if options['cache'] options['temp'] = File.join(options['cache'], 'temp/') else options['temp'] = '/tmp' end end def self.select_auth_url [options['from_uri'], options['to_uri']].detect do |x| x && x.scheme =~ /https?/ end end def self.pipefail_wrapper(command) ['bash', '-c', 'set -e -o pipefail;'+command] end # Declare command-line interface here description "Copy one URI to another" Uricp::OrbitAuth.add_auth_to_optionparser(self) on("--cache CACHE_ROOT", "Root directory of cache area") on("--max-cache MAX_CACHE_SIZE", "Maximum size of cached file in [GMk][i]B.") on("--target-format FORMAT", [:qcow2, :raw, :qcow3, :qcow2v3], "Image format of target", "[qcow2, raw, qcow3, qcow2v3]") on("--segment-size SEGMENT_SIZE", "Size of required segment in [GMk][i]B.") on("--[no-]compress", "Compress output") on("--[no-]dry-run", "Show what would be run,", "but don't run the command") on("--dry-cache DRY_CACHE",[:rbd, :partial_rbd], "On dry runs assume the cache is populated", "[rbd, partial_rbd]") on("--[no-]force", "Always write sparsely") #Arguments arg :from_uri, "URI to copy from" arg :to_uri, "URI to copy to" defaults_from_env_var 'URICP' version Uricp::VERSION use_log_level_option :toggle_debug_on_signal => 'USR1' go! end