#!/usr/bin/env ruby # # Copyright (C) 2009 Red Hat, Inc. # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The # ASF licenses this file to you 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 'rubygems' require 'optparse' require 'uri' require 'lib/deltacloud' require 'lib/plain_formatter' include DeltaCloud::PlainFormatter options = { :verbose => false } @optparse = OptionParser.new do |opts| opts.banner = <<BANNER Usage: deltacloudc collection operation [options] URL format: API_URL=http://[user]:[password]@[api_url][port][/uri] Options: BANNER opts.on( '-i', '--id ID', 'ID for operation') { |id| options[:id] = id } opts.on( '-d', '--image-id ID', 'Image ID') { |id| options[:image_id] = id } opts.on( '-a', '--arch ARCH', 'Architecture (x86, x86_64)') { |id| options[:architecture] = id } opts.on( '-p', '--hardware-profile HARDWARE_PROFILE', 'Hardware Profile') { |id| options[:hwp_id] = id } opts.on( '-n', '--name NAME', 'Name (for instance eg.)') { |name| options[:name] = name } opts.on( '-s', '--state STATE', 'Instance state (RUNNING, STOPPED)') { |state| options[:state] = state } opts.on( '-u', '--url URL', 'API url ($API_URL variable)') { |url| options[:api_url] = url } opts.on( '-l', '--list', 'List collections/operations') { |id| options[:list] = true } opts.on( '-h', '--help', 'Display this screen' ) { puts opts ; exit } opts.on( '-v', '--version', 'Display API version' ) { options[:version]=true } opts.on( '-V', '--verbose', 'Print verbose messages' ) { options[:verbose]=true } end def invalid_usage(error_msg='') puts "ERROR: #{error_msg}" exit(1) end @optparse.parse! # First try to get API_URL from environment options[:api_url] = ENV['API_URL'] if options[:api_url].nil? url = URI.parse(options[:api_url]) api_url = "http://#{url.host}#{url.port ? ":#{url.port}" : ''}#{url.path}" options[:collection] = ARGV[0] options[:operation] = ARGV[1] # Connect to Deltacloud API and fetch all entry points client = DeltaCloud.new(url.user || ENV['API_USER'], url.password || ENV['API_PASSWORD'], api_url) collections = client.entry_points.keys # Exclude collection which don't have methods in client library yet collections.delete(:instance_states) # If list parameter passed print out available collection # with API documentation if options[:list] and options[:collection].nil? collections.each do |c| doc = client.fetch_documentation(c.to_s) puts sprintf("%-22s: %s", c.to_s[0, 22], doc[:description]) end exit(0) end # If collection parameter is present and user requested list # print all operation defined for collection with API documentation if options[:list] and options[:collection] doc = client.fetch_documentation(options[:collection]) doc[:operations].each do |c| puts sprintf("%-20s: %s", c[:name][0, 20], c[:description]) end exit(0) end if options[:version] puts "Deltacloud API(#{client.driver_name}) 0.1" exit(0) end # List items from collection (typically /instances) # Do same if 'index' operation is set if options[:collection] and ( options[:operation].nil? or options[:operation].eql?('index') ) invalid_usage("Unknown collection: #{options[:collection]}") unless collections.include?(options[:collection].to_sym) params = {} params.merge!(:architecture => options[:architecture]) if options[:architecture] params.merge!(:id => options[:id]) if options[:id] params.merge!(:state => options[:state]) if options[:state] client.send(options[:collection].to_s, params).each do |model| puts format(model) end exit(0) end if options[:collection] and options[:operation] invalid_usage("Unknown collection: #{options[:collection]}") unless collections.include?(options[:collection].to_sym) params = {} params.merge!(:id => options[:id]) if options[:id] # If collection is set and requested operation is 'show' just 'singularize' # collection name and print item with specified id (-i parameter) if options[:operation].eql?('show') puts format(client.send(options[:collection].gsub(/s$/, ''), options[:id])) exit(0) end # If collection is set and requested operation is create new instance, # --image-id, --hardware-profile and --name parameters are used # Returns created instance in plain form if options[:collection].eql?('instances') and options[:operation].eql?('create') invalid_usage("Missing image-id") unless options[:image_id] if options[:name] and ! client.feature?(:instances, :user_name) invalid_usage("Driver does not support user-supplied name") end params.merge!(:name => options[:name]) if options[:name] params.merge!(:image_id => options[:image_id]) if options[:image_id] params.merge!(:hwp_id => options[:hwp_id]) if options[:hwp_id] instance = client.create_instance(options[:image_id], params) puts format(instance) exit(0) end # All other operations above collections is done there: if options[:collection].eql?('instances') instance = client.instance(options[:id]) instance.send("#{options[:operation]}!".to_s) instance = client.instance(options[:id]) puts format(instance) exit(0) end end # If all above passed (eg. no parameters) puts @optparse