Skip to content

Commit dba8d95

Browse files
authored
added ibmcloud support (openshift#2700)
1 parent 6bb4d23 commit dba8d95

File tree

4 files changed

+207
-2
lines changed

4 files changed

+207
-2
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ gem 'azure_mgmt_compute', '~>0.18.0'
3535
gem 'azure_mgmt_resources', '~>0.17.0'
3636
gem 'azure_mgmt_network', '~>0.17.0'
3737

38+
###### IBM cloud
39+
gem 'ibm_vpc'
3840
# gem 'timers'
3941
## Logging
4042
gem 'term-ansicolor'

lib/launchers/ibmcloud.rb

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,90 @@
44
unless $LOAD_PATH.any? {|p| File.expand_path(p) == lib_path}
55
$LOAD_PATH.unshift(lib_path)
66
end
7-
87
require 'collections'
98
require 'common'
9+
require 'cgi'
10+
11+
require "ibm_vpc"
1012

1113
module BushSlicer
1214
class IBMCloud
1315
include Common::Helper
1416
include CollectionsIncl
15-
attr_reader :config
17+
attr_reader :config, :vpc, :regions
18+
attr_accessor :region
1619

1720
def initialize(**opts)
1821
@config = conf[:services, opts.delete(:service_name) || :ibmcloud]
22+
authenticator = IbmVpc::Authenticators::IamAuthenticator.new(
23+
apikey: @config[:auth][:apikey]
24+
)
25+
@vpc = IbmVpc::VpcV1.new(authenticator: authenticator)
26+
@regions ||= vpc.list_regions.result['regions']
27+
if opts[:region]
28+
puts("Setting region to #{opts[:region]}...\n")
29+
region=(opts[:region])
30+
end
31+
end
32+
33+
# @return Array of region hash
34+
# {"name"=>"us-south", "href"=>"https://us-south.iaas.cloud.ibm.com/v1/regions/us-south", "endpoint"=>"https://us-south.iaas.cloud.ibm.com", "status"=>"available"}
35+
def regions
36+
@regions ||= self.vpc.list_regions.result['regions']
37+
end
38+
39+
# @return Hash containing region information
40+
def get_region(name)
41+
region_hash = self.regions.select {|r| r['name'] == name}.first
42+
raise "Unsupported region '#{name}" unless region_hash
43+
return region_hash
1944
end
45+
46+
def set_region(reg_name)
47+
region_info = self.get_region(reg_name)
48+
self.vpc.service_url = region_info['endpoint'] + "/v1"
49+
end
50+
# @returns current region hash
51+
def current_region
52+
self.vpc.service_url
53+
self.regions.select {|r| r['endpoint'].start_with? self.vpc.service_url[0..-4]}.first
54+
end
55+
56+
def instances
57+
start = nil
58+
instances = []
59+
loop do
60+
response = self.vpc.list_instances(start: start)
61+
instances += response.result["instances"]
62+
63+
next_link = response.result.dig("next", "href")
64+
break if next_link.nil?
65+
66+
start = CGI.parse(URI(next_link).query)["start"].first
67+
end
68+
return instances
69+
end
70+
71+
def get_instances_by_status(status: 'running', region: nil)
72+
instances = self.instances
73+
if instances.count > 0
74+
insts = instances.select {|i| i['status'] == status }
75+
instances = insts
76+
end
77+
return instances
78+
end
79+
80+
def instance_uptime(instance)
81+
((Time.now.utc - Time.parse(instance['created_at'])) / (60 * 60)).round(2)
82+
end
83+
2084
end
2185
end
86+
87+
if __FILE__ == $0
88+
extend BushSlicer::Common::Helper
89+
ibm = BushSlicer::IBMCloud.new(region: 'eu-gb')
90+
insts2 = ibm.instances
91+
print inst2
92+
end
93+

tools/cloud_usage.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ def run
8181
ps.get_summary(target_region: options.region, options: options)
8282
end
8383
end
84+
command :"ibmcloud" do |c|
85+
c.syntax = "#{File.basename __FILE__} -r <ibmcloud_region_name> [--all]"
86+
c.description = 'display summary of running instances'
87+
c.option("-r", "--region region_name", "report on this region only")
88+
c.option("-u", "--uptime cluter uptime limit", "report for clusters having uptime over this limit")
89+
c.action do |args, options|
90+
ps = IBMCloudSummary.new(svc_name: "ibmcloud", jenkins: @jenkins)
91+
options.config = conf
92+
say 'Getting summary...'
93+
ps.get_summary(target_region: options.region, options: options)
94+
end
95+
end
8496
command :"gce" do |c|
8597
c.syntax = "#{File.basename __FILE__} -r <gce_region_name> [--all]"
8698
c.description = 'display summary of running instances'

tools/instance_summary.rb

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,126 @@ def get_summary(target_region: nil, options: nil, global_region: "alicloud-v4")
869869
end
870870
print_grand_summary(grand_summary)
871871
end
872+
end
873+
874+
class IBMCloudSummary < InstanceSummary
875+
attr_accessor :ibm, :ibm_prices
876+
def initialize(svc_name: :ibmcloud, jenkins: nil)
877+
@ibm = IBMCloud.new(service_name: svc_name, region: 'us-east')
878+
@jenkins = jenkins
879+
@table = Text::Table.new
880+
# hard-coded pricing lookup table name: => price/hr
881+
@ibm_prices = {
882+
"bx2-2x8" => 0.096,
883+
"bx2d-2x8" => 0.104,
884+
"bx2-4x16" => 0.192,
885+
"bx2d-4x16" => 0.208,
886+
"bx2-8x32" => 0.384,
887+
"bx2d-8x32" => 0.417,
888+
"bx2-16x64" => 0.768,
889+
"bx2d-16x64" => 0.834,
890+
"bx2-32x128" => 1.536,
891+
"bx2d-32x128" => 1.668,
892+
"bx2-48x192" => 2.305,
893+
"bx2d-48x192" => 2.502,
894+
"bx2-64x256" => 3.073,
895+
"bx2d-64x256" => 3.336,
896+
"bx2-96x384" => 4.609,
897+
"bx2d-96x384" => 5.004,
898+
"bx2-128x512" => 6.146,
899+
"bx2d-128x512" => 6.672,
900+
}
901+
end
902+
903+
# @return <Hashed Array of Instances> with each hash key being keyed on the `owned` tag.
904+
def regroup_instances(instances)
905+
cluster_map = {}
906+
instances.each do |r|
907+
begin
908+
owned = r.dig("resource_group", "name")
909+
rescue
910+
# for bastion hosts, there doesn't seem to be a tag associated with
911+
# them, so just set it as empty
912+
owned = no_owner
913+
end
914+
if cluster_map[owned]
915+
cluster_map[owned] << r
916+
else
917+
cluster_map[owned] = [r]
918+
end
919+
end
920+
return cluster_map
921+
end
922+
923+
# @instances <Array of unordered Instance obj>
924+
def summarize_instances(region, instances)
925+
summary = []
926+
ibm = @ibm
927+
jenkins = @jenkins
928+
cm = regroup_instances(instances)
929+
cm.each do | owned, inst_list |
930+
inst_list.each do | inst |
931+
inst_summary = {}
932+
# inst_summary[:inst_obj] = inst
933+
inst_summary[:region] = region
934+
inst_summary[:name]= inst["name"]
935+
inst_summary[:type] = inst['profile']['name']
936+
inst_summary[:uptime]= ibm.instance_uptime inst
937+
inst_hourly_price = @ibm_prices[inst_summary[:type]]
938+
cost = 0.0
939+
if inst_hourly_price.nil?
940+
inst_hourly_price = 0.0
941+
puts "##### WARNING, setting hourly price for '#{inst_summary[:type]}' to 0.0 because it's not known"
942+
end
943+
944+
cost = inst_summary[:uptime] * inst_hourly_price
945+
inst_summary[:cost] = cost.round(2)
946+
inst_summary[:owned] = owned
947+
if inst_summary[:owned]
948+
inst_summary[:flexy_job_id], inst_summary[:inst_prefix] = jenkins.get_jenkins_flexy_job_id(inst_summary[:owned])
949+
else
950+
inst_summary[:flexy_job_id], inst_summary[:inst_prefix] = nil, nil
951+
end
952+
summary << inst_summary
953+
end
954+
end
955+
return summary
956+
end
872957

958+
def get_summary(target_region: nil, options: nil, global_region: "ibmcloud")
959+
regions = ibm.regions
960+
ibm_instances = {}
961+
threads = []
962+
# regions is an Array of ihash
963+
# for example: {"name"=>"au-syd", "href"=>"https://us-south.iaas.cloud.ibm.com/v1/regions/au-syd", "endpoint"=>"https://au-syd.iaas.cloud.ibm.com", "status"=>"available"
964+
regions.each do | region |
965+
if target_region
966+
# first check name is valid
967+
raise "Unsupported region '#{target_region}'" unless regions.map {|r| r['name']}.include? target_region
968+
region_name = target_region
969+
else
970+
region_name = region['name']
971+
end
972+
end_point = region.dig('endpoint')
973+
puts ("Getting instances for region '#{region_name}'...\n")
974+
ibm = IBMCloud.new(region_id: region_name)
975+
ibm.set_region(region_name)
976+
instances = ibm.get_instances_by_status(status: 'running') #, region_name: region['name'], region_endpoint: end_point)
977+
ibm_instances[region_name] = instances
978+
break if target_region
979+
end
980+
grand_summary = []
981+
ibm_instances.each do |region, inst_list|
982+
total_cost = 0.0
983+
summary = summarize_instances(region, inst_list)
984+
print_summary(summary) if inst_list.count > 0
985+
options.platform = "IBMCloud #{region}"
986+
print_longlived_clusters(summary, options) if inst_list.count > 0
987+
summary.each { |s| total_cost += s[:cost]}
988+
grand_summary << {platform: 'IBMCloud', region: region, inst_count: inst_list.count, total_cost: total_cost}
989+
end
990+
print_grand_summary(grand_summary)
991+
end
873992
end
874993
end
875994

0 commit comments

Comments
 (0)