Addresses
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 621 def addresses(credentials, opts={}) addrs_to_instance = {} ips_per_vsys = {} safely do client = new_client(credentials) opts ||= {} public_ips = client.list_public_ips(opts[:realm_id])['publicips'] return [] if public_ips.nil? or public_ips[0]['publicip'].nil? # first discover the VSYS each address belongs to public_ips[0]['publicip'].each do |ip| if not opts[:id] or opts[:id] == ip['address'][0] ips_per_vsys[ip['vsysId'][0]] ||= [] ips_per_vsys[ip['vsysId'][0]] << ip['address'][0] end end ips_per_vsys.each_pair do |vsys_id, ips| #nat rules show both mapped and unmapped IP addresses #may not have privileges to view nat rules on this vsys begin fw_id = "#{vsys_id}-S-0001" nat_rules = client.get_efm_configuration(fw_id, 'FW_NAT_RULE')['efm'][0]['firewall'][0]['nat'][0]['rules'][0] rescue RuntimeError => ex raise ex unless ex.message =~ %r^(ACCESS_NOT_PERMIT).*/ end if nat_rules and nat_rules['rule'] # collect all associated IP addresses (pub->priv) in vsys associated_ips = {} nat_rules['rule'].each do |rule| if opts[:id].nil? or opts[:id] == rule['publicIp'][0] # filter on public IP if specified associated_ips[rule['publicIp'][0]] = rule['privateIp'][0] if rule['privateIp'] end end # each associated target private IP belongs to either a vserver or SLB # 1. for vservers, obtain all ids from get_vsys_configuration in one call vsys = client.get_vsys_configuration(vsys_id) vsys['vsys'][0]['vservers'][0]['vserver'].each do |vserver| if determine_server_type(vserver) == 'vserver' vnic = vserver['vnics'][0]['vnic'][0] associated_ips.find do |pub,priv| addrs_to_instance[pub] = vserver['vserverId'][0] if priv == vnic['privateIp'][0] end if vnic['privateIp'] # when an instance is being created, the private ip is not known yet end end # of loop over vsys' vservers # 2. for slbs, obtain all ids from list_efm if addrs_to_instance.keys.size < associated_ips.keys.size # only if associated ips left to process if slbs = client.list_efm(vsys_id, 'SLB')['efms'] slbs[0]['efm'].find do |slb| associated_ips.find do |pub,priv| addrs_to_instance[pub] = slb['efmId'][0] if priv == slb['slbVip'][0] end addrs_to_instance.keys.size < associated_ips.keys.size # stop if no associated ips left to process end end end end # of nat_rules has rules end # of ips_per_vsys.each end addresses = [] ips_per_vsys.values.each do |pubs| addresses += pubs.collect do |pub| Address.new(:id => pub, :instance_id => addrs_to_instance[pub]) end end addresses end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 743 def associate_address(credentials, opts={}) safely do client = new_client(credentials) vsys_id = client.extract_vsys_id(opts[:instance_id]) begin client.attach_public_ip(vsys_id, opts[:id]) rescue Exception => ex raise ex unless ex.message =~ %r^ALREADY_ATTACHED.*/ end # retrieve private address # use get_vsys_configuration (instead of get_vserver_configuration) to also know if instance is an SLB vsys_config = client.get_vsys_configuration(vsys_id) vserver = vsys_config['vsys'][0]['vservers'][0]['vserver'].find { |e| e['vserverId'][0] == opts[:instance_id] } case determine_server_type(vserver) when 'vserver' private_ip = vserver['vnics'][0]['vnic'][0]['privateIp'][0] when 'SLB' if slbs = client.list_efm(vsys_id, 'SLB')['efms'] private_ip = slbs[0]['efm'].find { |slb| slb['slbVip'][0] if slb['efmId'][0] == opts[:instance_id] } end end if vserver fw_id = "#{vsys_id}-S-0001" nat_rules = client.get_efm_configuration(fw_id, 'FW_NAT_RULE')['efm'][0]['firewall'][0]['nat'][0]['rules'][0] if nat_rules and not nat_rules.empty? # happens only if no enabled IP address? nat_rules['rule'].each do |rule| if rule['publicIp'][0] == opts[:id] rule['privateIp'] = [ private_ip ] rule['snapt'] = [ 'true' ] else rule['snapt'] = [ 'false' ] end end end new_rules = { 'configuration' => [ 'firewall_nat' => [nat_rules] ]} # create FW configuration xml file with new rules conf_xml_new = XmlSimple.xml_out(new_rules, 'RootName' => 'Request' ) client.update_efm_configuration(fw_id, 'FW_NAT_RULE', conf_xml_new) Address.new(:id => opts[:id], :instance_id => opts[:instance_id]) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 521 def attach_storage_volume(credentials, opts={}) safely do client = new_client(credentials) client.attach_vdisk(opts[:instance_id], opts[:id]) end storage_volumes(credentials, opts).first end
following method enables region drop-down box on GUI
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1335 def configured_providers Deltacloud::Drivers::driver_config[:fgcp][:entrypoints]['default'].keys.sort end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 700 def create_address(credentials, opts={}) safely do client = new_client(credentials) opts ||= {} if opts[:realm_id] # just in case a network realm was passed in opts[:realm_id] = client.extract_vsys_id(opts[:realm_id]) else # get first vsys xml = client.list_vsys['vsyss'] opts[:realm_id] = xml[0]['vsys'][0]['vsysId'][0] if xml end client.allocate_public_ip(opts[:realm_id]) end # new address not returned immediately! Address.new(:id => 'PENDING-xxx.xxx.xxx.xxx') end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 955 def create_firewall(credentials, opts={}) safely do client = new_client(credentials) begin # using 'description' as vsysDescriptor vsys_id = client.create_vsys(opts['description'], opts['name'])['vsysId'][0] rescue Exception => ex raise ex unless ex.message =~ %rTemplate does not exist.*/ descriptors = client.list_vsys_descriptor['vsysdescriptors'][0]['vsysdescriptor'].collect { |desc| desc['vsysdescriptorId'][0] } raise "Descriptor [#{opts['name']}] does not exist. Specify one of [#{descriptors.join(', ')}] as firewall description" end fw_id = vsys_id + '-S-0001' Firewall.new({ :id => fw_id, :name => opts['name'], :description => opts['description'], :owner_id => '', :rules => [] }) end end
Create a new image from the given instance, with optionally provided name and description
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 133 def create_image(credentials, opts={}) safely do client = new_client(credentials) if opts[:name].nil? # default to instance name instance = client.get_vserver_attributes(opts[:id]) opts[:name] ||= instance['vserver'][0]['vserverName'] opts[:description] ||= opts[:name] end client.register_private_disk_image(opts[:id], opts[:name], opts[:description]) hwps = hardware_profiles(credentials) #can't retrieve image info until it's completed Image.new( :id => "PENDING-#{opts[:name]}", #TODO: add check to create_instance to raise error for this image ID? :name => opts[:name], :description => opts[:description], :state => 'PENDING', :hardware_profiles => hwps ) end end
Create a new instance, given an image id opts can include an optional name for the instance, hardware profile (hwp_id) and realm_id
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 345 def create_instance(credentials, image_id, opts={}) name = opts[:name] # default to 'economy' or obtain latest hardware profiles and pick the lowest spec profile? hwp = opts[:hwp_id] || 'economy' network_id = opts[:realm_id] safely do client = new_client(credentials) if not network_id xml = client.list_vsys['vsyss'] # use first returned system's DMZ as realm network_id = xml ? xml[0]['vsys'][0]['vsysId'][0] + '-N-DMZ' : nil end xml = client.create_vserver(name, hwp, image_id, network_id) # returns vserver details instances(credentials, {:id => xml['vserverId'][0]}).first end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1194 def create_load_balancer(credentials, opts={}) safely do client = new_client(credentials) # if opts['realm_id'].nil? network id specified, pick first vsys' DMZ? # CreateEFM -vsysId vsysId -efmType SLB -efmName opts['name'] -networkId opts['realm_id'] network_id = opts[:realm_id] if not network_id xml = client.list_vsys['vsyss'] # use first returned system's DMZ as realm network_id = xml ? xml[0]['vsys'][0]['vsysId'][0] + '-N-DMZ' : nil end efm = client.create_efm('SLB', opts[:name], network_id) # [{:load_balancer_port => opts['listener_balancer_port'], # :instance_port => opts['listener_instance_port'], # :protocol => opts['listener_protocol']}] # ) load_balancer(credentials, {:id => efm['efmId'][0]}) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 596 def create_storage_snapshot(credentials, opts={}) safely do client = new_client(credentials) client.backup_vdisk(opts[:volume_id]) end StorageSnapshot.new( :id => "PENDING-#{opts[:volume_id]}", # don't know id until backup completed :state => 'PENDING', # OK to make up a state like that? :storage_volume_id => opts[:volume_id], :created => Time.now.to_s ) end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 478 def create_storage_volume(credentials, opts={}) opts ||= {} opts[:name] ||= Time.now.to_s opts[:capacity] ||= '1' # DC default #size has to be a multiple of 10: round up. opts[:capacity] = ((opts[:capacity].to_f / 10.0).ceil * 10.0).to_s safely do client = new_client(credentials) if opts[:realm_id] # just in case the user got confused and specified a network id opts[:realm_id] = client.extract_vsys_id(opts[:realm_id]) elsif xml = client.list_vsys['vsyss'] # use first vsys returned as realm opts[:realm_id] = xml[0]['vsys'][0]['vsysId'][0] if xml end vdisk_id = client.create_vdisk(opts[:realm_id], opts[:name], opts[:capacity])['vdiskId'][0] StorageVolume.new( :id => vdisk_id, :created => Time.now.to_s, :name => opts[:name], :capacity => opts[:capacity], :realm_id => client.extract_vsys_id(opts[:realm_id]), :instance_id => nil, :state => 'DEPLOYING', # aligning with rhevm, which returns 'system' or 'data' :kind => 'data', :actions => [] ) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 977 def delete_firewall(credentials, opts={}) safely do client = new_client(credentials) begin # try to stop FW first opts[:id] =~ %r^(.*-S-)\d\d\d\d/ fw_id = $1 + '0001' client.stop_efm(fw_id) rescue Exception => ex raise ex if not ex.message =~ %rALREADY_STOPPED.*/ client.destroy_vsys(client.extract_vsys_id(opts[:id])) return end Thread.new { attempts = 0 begin sleep 30 # this may fail if the FW is still stopping client.destroy_vsys(client.extract_vsys_id(opts[:id])) rescue Exception => ex raise unless attempts < 20 and ex.message =~ %rSERVER_RUNNING.*/ # Stopping takes a few minutes, so keep trying for a while attempts += 1 retry end } raise 'Firewall will be deleted once it has stopped' end end
FW rule creation not supported: fgcp backend requires a mandatory rule id to create (insert) a new rule into the existing accept/deny rules. Also, the first two digits of the five digit rule identify what from and to network segment (e.g. Internet to DMZ, or Secure2 to Secure1) the rule applies to. The current Deltacloud firewall collection API does not cover such functionality so it was deemed not suitable to implement.
def create_firewall_rule(credentials, opts={}) p opts end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1019 def delete_firewall_rule(credentials, opts={}) # retrieve current FW rules, delete rule, send back to API server safely do client = new_client(credentials) conf_xml_old = "<?xml version="1.0" encoding ="UTF-8"?> <Request> <configuration> <firewall_policy> </firewall_policy> </configuration> </Request> " # retrieve current rules fw = client.get_efm_configuration(opts[:firewall], 'FW_POLICY', conf_xml_old) rule50000_log = 'On' # delete specified rule and special rule 50000 (handled later) fw['efm'][0]['firewall'][0]['directions'][0]['direction'].reject! do |direction| direction['policies'][0]['policy'].reject! do |policy| rule_id = policy['id'][0] # need to use (final) 3 digit id policy['id'][0] = rule_id[2..4] # storage rule 50000's log attribute for later rule50000_log = policy['log'][0] if rule_id == '50000' # some elements not allowed if service is NTP, DNS, etc. if not policy['dstService'][0] == 'NONE' policy.delete('dstType') policy.delete('dstPort') policy.delete('protocol') end rule_id == opts[:rule_id] or rule_id == '50000' end direction['policies'][0]['policy'].empty? end # add entry for 50000 special rule fw['efm'][0]['firewall'][0]['directions'][0]['direction'] << { 'policies' => [ 'policy' => [ 'log' => [ rule50000_log ] ] ] } new_rules = { 'configuration' => [ 'firewall_policy' => [ 'directions' => fw['efm'][0]['firewall'][0]['directions'] ] ]} # create FW configuration xml file with new rules conf_xml_new = XmlSimple.xml_out(new_rules, 'RootName' => 'Request' ) conf_xml_new.gsub!(%r(<(to|from)>).+(INTERNET|INTRANET)/, '\1\3') client.update_efm_configuration(opts[:firewall], 'FW_POLICY', conf_xml_new) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 719 def destroy_address(credentials, opts={}) opts ||= {} safely do client = new_client(credentials) if opts[:realm_id] opts[:realm_id] = client.extract_vsys_id(opts[:realm_id]) else xml = client.list_public_ips['publicips'] if xml xml[0]['publicip'].find do |ip| opts[:realm_id] = ip['vsysId'][0] if opts[:id] == ip['address'][0] end end end begin # detach just in case client.detach_public_ip(opts[:realm_id], opts[:id]) rescue Exception => ex raise ex unless ex.message =~ %r^ALREADY_DETACHED.*/ end client.free_public_ip(opts[:realm_id], opts[:id]) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 158 def destroy_image(credentials, image_id) safely do client = new_client(credentials) client.unregister_disk_image(image_id) end end
Destroy an instance, given its id.
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 365 def destroy_instance(credentials, id) safely do client = new_client(credentials) vsys_id = client.extract_vsys_id(id) if id == "#{vsys_id}-S-0001" # if FW client.destroy_vsys(vsys_id) else # vserver or SLB (no way to tell which from id) begin client.destroy_vserver(id) rescue Exception => ex # if not found, try destroying as SLB if not ex.message =~ %rVALIDATION_ERROR.*/ raise ex else begin client.destroy_efm(id) rescue # if that fails as well, just raise the original error raise ex end end end end end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1215 def destroy_load_balancer(credentials, id) safely do client = new_client(credentials) client.destroy_efm(id) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 610 def destroy_storage_snapshot(credentials, opts={}) vdisk_id, backup_id = split_snapshot_id(opts[:id]) safely do client = new_client(credentials) client.destroy_vdisk_backup(client.extract_vsys_id(opts[:id]), backup_id) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 514 def destroy_storage_volume(credentials, opts={}) safely do client = new_client(credentials) client.destroy_vdisk(opts[:id]) end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 529 def detach_storage_volume(credentials, opts={}) safely do client = new_client(credentials) client.detach_vdisk(opts[:instance_id], opts[:id]) end storage_volumes(credentials, opts) end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 799 def disassociate_address(credentials, opts={}) safely do client = new_client(credentials) if not opts[:realm_id] if public_ips = client.list_public_ips['publicips'] public_ips[0]['publicip'].find do |ip| opts[:realm_id] = ip['vsysId'][0] if opts[:id] == ip['address'][0] end end end vsys_id = client.extract_vsys_id(opts[:realm_id]) fw_id = "#{vsys_id}-S-0001" nat_rules = client.get_efm_configuration(fw_id, 'FW_NAT_RULE')['efm'][0]['firewall'][0]['nat'][0]['rules'][0] if nat_rules and not nat_rules.empty? # happens only if no enabled IP address? nat_rules['rule'].reject! { |rule| rule['publicIp'][0] == opts[:id] } end new_rules = { 'configuration' => [ 'firewall_nat' => [nat_rules] ]} # create FW configuration xml file with new rules conf_xml_new = XmlSimple.xml_out(new_rules, 'RootName' => 'Request' ) client.update_efm_configuration(fw_id, 'FW_NAT_RULE', conf_xml_new) client.detach_public_ip(client.extract_vsys_id(opts[:realm_id]), opts[:id]) end end
Firewalls
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 840 def firewalls(credentials, opts={}) firewalls = [] fw_name = 'Firewall' # currently always 'Firewall' safely do client = new_client(credentials) if opts and opts[:id] # get details incl. rules on single FW rules = [] configuration_xml = "<?xml version="1.0" encoding ="UTF-8"?> <Request> <configuration> <firewall_policy> </firewall_policy> </configuration> </Request> " begin fw = client.get_efm_configuration(opts[:id], 'FW_POLICY', configuration_xml) rescue Exception => ex return [] if ex.message =~ %rRESOURCE_NOT_FOUND/ raise end fw_name = fw['efm'][0]['efmName'][0] # currently always 'Firewall' fw_owner_id = fw['efm'][0]['creator'][0] rule50000_log = true if fw['efm'][0]['firewall'][0]['directions'] and fw['efm'][0]['firewall'][0]['directions'][0]['direction'] fw['efm'][0]['firewall'][0]['directions'][0]['direction'].each do |direction| direction['policies'][0]['policy'].each do |policy| sources = [] ['src', 'dst'].each do |e| if policy[e] and policy[e][0] and not policy[e][0].empty? ip_address_type = policy["#{e}Type"][0] address = policy[e][0] address.sub!('any', '0.0.0.0/0') if ip_address_type == 'IP' address += '/32' if ip_address_type == 'IP' and not address =~ %r.*\/.*/ sources << { :type => 'address', :family => 'ipv4', :address => address.split('/').first, :prefix => ip_address_type == 'IP' ? address.split('/').last : nil } end end # defining ingress as access going from Internet/Intranet -> DMZ -> SECURE1 -> SECURE2 ingress = policy['id'][0] =~ %r[13].*/ ? 'ingress' : 'egress' rules << FirewallRule.new({ :id => policy['id'][0], :rule_action => policy['action'][0].downcase, :log_rule => policy['log'][0] == 'On', :allow_protocol => policy['protocol'][0], :port_from => policy['srcPort'] ? policy['srcPort'][0] : nil, # not set for e.g. ICMP :port_to => policy['dstPort'] ? policy['dstPort'][0] : nil, # not set for e.g. ICMP :direction => ingress, :sources => sources }) unless policy['id'][0] == '50000' # special case added later rule50000_log = (policy['log'][0] == 'On') if policy['id'][0] == '50000' end end end # add "all deny" rule 50000 source_any = { :type => 'address', :family => 'ipv4', :address => '0.0.0.0', :prefix => '0' } rules << FirewallRule.new({ :id => '50000', :rule_action => 'deny', :log_rule => rule50000_log, :sources => [source_any] }) vsys = client.get_vsys_attributes(client.extract_vsys_id(opts[:id]))['vsys'][0] firewalls << Firewall.new({ :id => opts[:id], :name => fw_name, :description => "#{vsys['vsysName'][0]} [#{vsys['baseDescriptor'][0]}]", :owner_id => fw_owner_id, :rules => rules }) else xml = client.list_vsys['vsyss'] return [] if xml.nil? firewalls = xml[0]['vsys'].collect do |vsys| Firewall.new({ :id => vsys['vsysId'][0] + '-S-0001', :name => fw_name, :description => "#{vsys['vsysName'][0]} [#{vsys['baseDescriptor'][0]}]", :rules => [], :owner_id => vsys['creator'][0] }) end end end firewalls end
Hardware profiles
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 67 def hardware_profiles(credentials, opts=nil) safely do client = new_client(credentials) xml = client.list_server_types @hardware_profiles = [] if xml['servertypes'] xml['servertypes'][0]['servertype'].each do |type| arch = type['cpu'][0]['cpuArch'][0] # returns 'IA' or 'SPARC'. IA currently offered is x86_64 cpu = type['cpu'][0]['cpuPerf'][0].to_f * type['cpu'][0]['numOfCpu'][0].to_i @hardware_profiles << ::Deltacloud::HardwareProfile.new(type['name'][0]) { cpu cpu.to_f == cpu.to_f.floor ? cpu.to_i : cpu.to_f # omit '.0' if whole number memory (type['memory'][0]['memorySize'][0].to_f * 1024) # converted to MB architecture (arch == 'IA') ? 'x86_64' : arch #storage <- defined by image, not hardware profile #if 'storage' is not added, displays 'storage:0' in GUI #storage '' } end end end filter_hardware_profiles(@hardware_profiles, opts) end
Images
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 96 def images(credentials, opts={}) images = [] safely do client = new_client(credentials) xml = client.list_disk_images hwps = hardware_profiles(credentials) # use client to get a list of images from the back-end cloud and then create # a Deltacloud Image object for each of these. Filter the result # (eg specific image requested) and return to user if xml['diskimages'] # not likely to not be so, but just in case xml['diskimages'][0]['diskimage'].each do |img| images << Image.new( :id => img['diskimageId'][0], :name => img['diskimageName'][0].to_s, :description => img['description'][0].to_s, :owner_id => img['registrant'][0].to_s, # or 'creatorName'? :state => 'AVAILABLE', #server keeps no particular state. If it's listed, it's available for use. # This will determine image architecture using OS name. # Usually the OS name includes '64bit' or '32bit'. If not, # it will fall back to 64 bit. :architecture => img['osName'][0].to_s =~ %r.*32.?bit.*/ ? 'i386' : 'x86_64', :hardware_profiles => hwps ) if opts[:id].nil? or opts[:id] == img['diskimageId'][0] end end end images = filter_on( images, :id, opts ) images = filter_on( images, :architecture, opts ) images = filter_on( images, :owner_id, opts ) images.sort_by{|e| [e.owner_id, e.architecture, e.name, e.description]} end
Instances
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 226 def instances(credentials, opts={}) instances = [] safely do client = new_client(credentials) if opts and opts[:id] or opts[:realm_id] vsys_id = client.extract_vsys_id(opts[:id] || opts[:realm_id]) vsys_config = client.get_vsys_configuration(vsys_id) vsys_config['vsys'][0]['vservers'][0]['vserver'].each do |vserver| network_id = vserver['vnics'][0]['vnic'][0]['networkId'][0] # :realm_id can point to system or network if vsys_id == opts[:realm_id] or vserver['vserverId'][0] == opts[:id] or network_id == opts[:realm_id] # skip firewall if filtering by realm unless opts[:realm_id] and determine_server_type(vserver) == 'FW' # check state first as it may be filtered on state_data = instance_state_data(vserver, client) if opts[:state].nil? or opts[:state] == state_data[:state] instance = convert_to_instance(client, vserver, state_data) add_instance_details(instance, client, vserver) instances << instance end end end end elsif xml = client.list_vsys['vsyss'] return [] if xml.nil? xml[0]['vsys'].each do |vsys| # use get_vsys_configuration (instead of get_vserver_configuration) to retrieve all vservers in one call vsys_config = client.get_vsys_configuration(vsys['vsysId'][0]) vsys_config['vsys'][0]['vservers'][0]['vserver'].each do |vserver| # skip firewalls - they probably don't belong here and their new type ('firewall' instead of # 'economy') causes errors when trying to map to available profiles) unless determine_server_type(vserver) == 'FW' # to keep the response time of this method acceptable, retrieve state # only if required because state is filtered on state_data = opts[:state] ? instance_state_data(vserver, client) : nil # filter on state if opts[:state].nil? or opts[:state] == state_data[:state] instances << convert_to_instance(client, vserver, state_data) end end end end end end instances = filter_on( instances, :state, opts ) filter_on( instances, :id, opts ) end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1125 def load_balancer(credentials, opts={}) balancer = nil safely do client = new_client(credentials) # use get_vsys_configuration (instead of list_efm) to retrieve all SLBs incl. realms in one call? vsys_id = client.extract_vsys_id(opts[:id]) vsys_config = client.get_vsys_configuration(vsys_id) vsys_config['vsys'][0]['vservers'][0]['vserver'].each do |vserver| if vserver['vserverId'][0] == opts[:id] vserver['vnics'][0]['vnic'][0]['networkId'][0] =~ %r^.*\b(\w+)$/ realm_name = vsys_id + ' [' + $1 + ']' # vsys name + network [DMZ/SECURE1/SECURE2] realm = Realm::new( :id => vserver['vnics'][0]['vnic'][0]['networkId'][0], :name => realm_name, :limit => '[Network]', :state => 'AVAILABLE' # map to state of FW/VSYS (reconfiguring = unavailable)? ) balancer = LoadBalancer.new({ :id => vserver['vserverId'][0], :realms => [realm], :listeners => [], :instances => [], :public_addresses => [] }) begin slb_rule = client.get_efm_configuration(opts[:id], 'SLB_RULE') if slb_rule['efm'][0]['loadbalancer'][0]['groups'] slb_rule['efm'][0]['loadbalancer'][0]['groups'][0]['group'].each do |group| group['targets'][0]['target'].each do |server| balancer.instances << Instance::new( :id => server['serverId'][0], :name => server['serverName'][0], :realm_id => realm, :private_addresses => [InstanceAddress.new(server['ipAddress'][0])] ) balancer.add_listener({ :protocol => slb_rule['efm'][0]['loadbalancer'][0]['groups'][0]['group'][0]['protocol'][0], :load_balancer_port => slb_rule['efm'][0]['loadbalancer'][0]['groups'][0]['group'][0]['port1'][0], :instance_port => server['port1'][0] }) end end end slb_vip = slb_rule['efm'][0]['slbVip'][0] opts[:id] =~ %r^(.*-S-)\d\d\d\d/ fw_id = $1 + '0001' nat_rules = client.get_efm_configuration(fw_id, 'FW_NAT_RULE')['efm'][0]['firewall'][0]['nat'][0]['rules'][0] if nat_rules and not nat_rules.empty? nat_rules['rule'].each do |rule| balancer.public_addresses << InstanceAddress.new(rule['publicIp'][0]) if rule['privateIp'] and rule['privateIp'][0] == slb_vip end end rescue Exception => ex raise ex unless ex.message =~ %r(ACCESS_NOT_PERMIT|ILLEGAL_STATE).*/ end end end end balancer end
Load Balancers
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1088 def load_balancers(credentials, opts={}) balancers = [] safely do client = new_client(credentials) xml = client.list_vsys['vsyss'] return [] if xml.nil? xml[0]['vsys'].each do |vsys| # use get_vsys_configuration (instead of list_efm) to retrieve all SLBs incl. realms in one call vsys_config = client.get_vsys_configuration(vsys['vsysId'][0]) vsys_config['vsys'][0]['vservers'][0]['vserver'].each do |vserver| if determine_server_type(vserver) == 'SLB' vserver['vnics'][0]['vnic'][0]['networkId'][0] =~ %r^.*\b(\w+)$/ realm_name = vsys['vsysId'][0] + ' [' + $1 + ']' # vsys name + network [DMZ/SECURE1/SECURE2] realm = Realm::new( :id => vserver['vnics'][0]['vnic'][0]['networkId'][0], :name => realm_name, :limit => '[Network]', :state => 'AVAILABLE' # map to state of FW/VSYS (reconfiguring = unavailable)? ) balancer = LoadBalancer.new({ :id => vserver['vserverId'][0], :realms => [realm], :listeners => [], :instances => [], :public_addresses => [] }) balancers << balancer end end end end balancers end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1274 def metric(credentials, opts={}) safely do client = new_client(credentials) begin perf = client.get_performance_information(opts[:id], 'hour') rescue Exception => ex return nil if ex.message =~ %rRESOURCE_NOT_FOUND/ raise end metric = Metric.new( :id => opts[:id], :entity => perf['serverName'][0], :properties => [] ) # if instance hasn't been running for an hour, no info will be returned unless perf['performanceinfos'].nil? or perf['performanceinfos'][0].nil? or perf['performanceinfos'][0]['performanceinfo'].nil? perf['performanceinfos'][0]['performanceinfo'].each do |sample| timestamp = Time.at(sample['recordTime'][0].to_i / 1000) sample.each do |measure| measure_name = measure[0] unless measure_name == 'recordTime' unit = metric_unit_for(measure_name) average = (unit == 'Percent') ? measure[1][0].to_f * 100 : measure[1][0] properties = metric.add_property(measure_name).properties property = properties.find { |p| p.name == measure_name } property.values ||= [] property.values << { :average => average, :timestamp => timestamp, :unit => unit } end end metric.properties.sort! {|a,b| a.name <=> b.name} end end metric end end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1222 def metrics(credentials, opts={}) opts ||= {} metrics_arr = [] safely do client = new_client(credentials) realms = [] # first check for cases of id or realm_id specified if opts[:id] metrics_arr << Metric.new( :id => opts[:id], :entity => client.get_vserver_attributes(opts[:id])['vserver'][0]['vserverName'][0] ) elsif opts[:realm_id] # if realm is set, list vservers in that realm (vsys/network ID), else list from all vsys realms << opts[:realm_id] else # list all vsys xml = client.list_vsys['vsyss'] realms = xml[0]['vsys'].collect { |vsys| vsys['vsysId'][0] } if xml end # list all vservers realms.each do |realm_id| xml = client.list_vservers(client.extract_vsys_id(realm_id))['vservers'] if xml and xml[0]['vserver'] xml[0]['vserver'].each do |vserver| # should check whether vserver is actually in opts[:realm_id] if network segment? metrics_arr << Metric.new( :id => vserver['vserverId'][0], :entity => vserver['vserverName'][0] ) end end end # add metric names to metrics metrics_arr.each do |metric| @@METRIC_NAMES.each do |name| metric.add_property(name) end metric.properties.sort! {|a,b| a.name <=> b.name} end end metrics_arr end
Providers
output of this method is used to list regions (id, url) under /api/drivers/fgcp
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 1324 def providers(credentials, opts={}) configured_providers.collect do |region| Provider.new( :id => "fgcp-#{region}", :name => "Fujitsu Global Cloud Platform - #{region.upcase}", :url => Deltacloud::Drivers::driver_config[:fgcp][:entrypoints]['default'][region] ) end end
Realms
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 168 def realms(credentials, opts={}) realms = [] safely do client = new_client(credentials) if opts and opts[:id] # determine id belongs to system or network vsys_id = client.extract_vsys_id(opts[:id]) vsys = client.get_vsys_attributes(vsys_id)['vsys'][0] realm_name = vsys['vsysName'][0] limit = '[System]' if opts[:id] != vsys_id # network id specified opts[:id] =~ %r^.*\b(\w+)$/ realm_name += ' [' + $1 + ']' # system name or system name + network [DMZ/SECURE1/SECURE2] limit = '[Network]' end realms << Realm::new( :id => opts[:id], :name => realm_name, #:limit => :unlimited, :limit => limit, :state => 'AVAILABLE' # map to state of FW/VSYS (reconfiguring = unavailable)? ) elsif xml = client.list_vsys['vsyss'] return [] if xml.nil? xml[0]['vsys'].each do |vsys| realms << Realm::new( :id => vsys['vsysId'][0], # vsysId or networkId :name => vsys['vsysName'][0], # system name or system name + network (DMZ/SECURE1/SECURE2) #:limit => :unlimited, :limit => '[System]', :state => 'AVAILABLE' # map to state of FW/VSYS (reconfiguring = unavailable)? ) # then retrieve and add list of network segments client.get_vsys_configuration(vsys['vsysId'][0])['vsys'][0]['vnets'][0]['vnet'].each do |vnet| vnet['networkId'][0] =~ %r^.*\b(\w+)$/ realm_name = vsys['vsysName'][0].to_s + ' [' + $1 + ']' # vsys name or vsys name + network [DMZ/SECURE1/SECURE2] realms << Realm::new( :id => vnet['networkId'][0], # vsysId or networkId :name => realm_name, #:limit => :unlimited, :limit => '[Network]', :state => 'AVAILABLE' # map to state of FW/VSYS (reconfiguring = unavailable)? ) end end end end filter_on(realms, :id, opts) end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 392 def run_on_instance(credentials, opts={}) target = instance(credentials, opts) safely do param = {} param[:port] = opts[:port] || '22' param[:ip] = opts[:ip] || target.public_addresses.first.address param[:credentials] = { :username => target.username } if opts[:private_key] and opts[:private_key].length > 1 param[:private_key] = opts[:private_key] else password = (opts[:password] and opts[:password].length > 0) ? opts[:password] : target.password param[:credentials].merge!({ :password => password }) end Deltacloud::Runner.execute(opts[:cmd], param) end end
Start an instance, given its id.
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 283 def start_instance(credentials, id) safely do client = new_client(credentials) if id =~ %r^.*-S-0001/ # FW client.start_efm(id) else # vserver or SLB (no way to tell which from id) begin client.start_vserver(id) rescue Exception => ex # if not found, try starting as SLB if not ex.message =~ %rVALIDATION_ERROR.*/ raise ex else begin client.start_efm(id) rescue # if that fails as well, just raise the original error raise ex end end end end end instances(credentials, {:id => id}).first end
Stop an instance, given its id.
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 311 def stop_instance(credentials, id) safely do client = new_client(credentials) if id =~ %r^.*-S-0001/ # FW client.stop_efm(id) else # vserver or SLB (no way to tell which from id) begin client.stop_vserver(id) rescue Exception => ex #if not found, try stopping as SLB if not ex.message =~ %rVALIDATION_ERROR.*/ raise ex else begin client.stop_efm(id) rescue # if that fails as well, just raise the original error raise ex end end end end end instances(credentials, {:id => id}).first end
Storage Snapshots
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 540 def storage_snapshots(credentials, opts={}) snapshots = [] safely do client = new_client(credentials) if opts and opts[:id] vdisk_id, backup_id = split_snapshot_id(opts[:id]) begin if backups = client.list_vdisk_backup(vdisk_id)['backups'] backups[0]['backup'].each do |backup| snapshots << StorageSnapshot.new( :id => opts[:id], #:state => ?, :storage_volume_id => vdisk_id, :created => backup['backupTime'][0] ) if backup_id = backup['backupId'][0] end end rescue Exception => ex return [] if ex.message =~ %rRESOURCE_NOT_FOUND/ raise end elsif xml = client.list_vsys['vsyss'] return [] if xml.nil? xml[0]['vsys'].each do |vsys| vdisks = client.list_vdisk(vsys['vsysId'][0])['vdisks'][0] if vdisks['vdisk'] vdisks['vdisk'].each do |vdisk| backups = client.list_vdisk_backup(vdisk['vdiskId'][0]) if backups['backups'] and backups['backups'][0]['backup'] backups['backups'][0]['backup'].each do |backup| snapshots << StorageSnapshot.new( :id => generate_snapshot_id(vdisk['vdiskId'][0], backup['backupId'][0]), #:state => ?, :storage_volume_id => vdisk['vdiskId'][0], :created => backup['backupTime'][0] ) end end end end end end end snapshots end
Storage volumes
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 414 def storage_volumes(credentials, opts={}) volumes = [] safely do client = new_client(credentials) if opts and opts[:id] begin vdisk = client.get_vdisk_attributes(opts[:id])['vdisk'][0] rescue Exception => ex return [] if ex.message =~ %rVALIDATION_ERROR.*t exist./ raise end state = client.get_vdisk_status(opts[:id])['vdiskStatus'][0] actions = [] if state == 'NORMAL' if vdisk['attachedTo'].nil? state = 'AVAILABLE' actions = [:attach, :destroy] else state = 'IN-USE' actions = [:detach] end end volumes << StorageVolume.new( :id => opts[:id], :name => vdisk['vdiskName'][0], :capacity => vdisk['size'][0], :instance_id => vdisk['attachedTo'].nil? ? nil : vdisk['attachedTo'][0], :state => state, :actions => actions, # aligning with rhevm, which returns 'system' or 'data' :kind => determine_storage_type(opts[:id]), :realm_id => client.extract_vsys_id(opts[:id]) ) elsif xml = client.list_vsys['vsyss'] return [] if xml.nil? xml[0]['vsys'].each do |vsys| vdisks = client.list_vdisk(vsys['vsysId'][0])['vdisks'][0] if vdisks['vdisk'] vdisks['vdisk'].each do |vdisk| #state requires an additional call per volume. Only set if attached. #exclude system disks as they are not detachable? volumes << StorageVolume.new( :id => vdisk['vdiskId'][0], :name => vdisk['vdiskName'][0], :capacity => vdisk['size'][0], :instance_id => vdisk['attachedTo'].nil? ? nil : vdisk['attachedTo'][0], :realm_id => client.extract_vsys_id(vdisk['vdiskId'][0]), # aligning with rhevm, which returns 'system' or 'data' :kind => determine_storage_type(vdisk['vdiskId'][0]), :state => vdisk['attachedTo'].nil? ? nil : 'IN-USE' ) end end end end end volumes end
# File lib/deltacloud/drivers/fgcp/fgcp_driver.rb, line 38 def valid_credentials?(credentials) begin client = new_client(credentials) # use a relativily cheap operation that is likely to succeed # (i.e. not requiring particular access privileges) client.list_server_types rescue return false end true end