Alex Ruiz Estradera f615e10861 Fix the types for midonet gateway type
Change-Id: I1bb96901856173de8d9b5d7d20016d9a2a10467f
2016-10-10 17:02:06 +02:00

358 lines
12 KiB
Ruby

if RUBY_VERSION == '1.8.7'
require 'rubygems'
end
require 'uri'
require 'faraday'
require 'json'
require 'ipaddr'
Puppet::Type.type(:midonet_gateway_bgp).provide(:midonet_api_caller) do
def create
if resource[:bgp_neighbors].class == Hash
bgp_neighbors_resource = [resource[:bgp_neighbors]]
else
bgp_neighbors_resource = resource[:bgp_neighbors]
end
if resource[:bgp_advertised_networks].class == String
bgp_advertised_networks_resource = [resource[:bgp_advertised_networks]]
else
bgp_advertised_networks_resource = resource[:bgp_advertised_networks]
end
define_connection(resource[:midonet_api_url])
entered_neighbors_parsed = bgp_neighbors_resource.collect { |x| {'ip_address' => x['ip_address'], 'remote_asn' => x['remote_asn'].to_i} }
# Get the edge router uuid
provider_router = call_get_provider_router()[0]
provider_router_id = provider_router['id']
# Assign local ASN to the provider router
asn = provider_router['asNumber']
call_assign_asn(provider_router, resource[:bgp_local_as_number]) unless asn.to_i == resource[:bgp_local_as_number].to_i
# Sync BGP peers
bgp_neighbors = call_get_bgp_peers(provider_router_id)
m = Array.new
bgp_neighbors.each do |bgp_neighbor|
n = { "ip_address" => bgp_neighbor["address"],
"remote_asn" => bgp_neighbor["asNumber"] }
m << n
end
tbd_peers = m - entered_neighbors_parsed
tba_peers = entered_neighbors_parsed - m
tba_peers.each { |a| call_add_bgp_peer(provider_router_id, a['ip_address'], a['remote_asn']) }
tbd_peers.each do |d|
bgp_peer_id = bgp_neighbors.select { |bgp_neighbor| bgp_neighbor['asNumber'] == d['remote_asn'] }[0]["id"]
call_delete_bgp_peer(bgp_peer_id)
end
# Advertise floating IP networks
bgp_advertised_networks = call_get_bgp_networks(provider_router_id)
j = Array.new
bgp_advertised_networks.each do |bgp_advertised_network|
k = [ bgp_advertised_network["subnetAddress"], bgp_advertised_network["subnetLength"] ].join("/")
j << k
end
tbd_bgp_networks = j - bgp_advertised_networks_resource
tba_bgp_networks = bgp_advertised_networks_resource - j
tbd_bgp_networks.each do |d|
bgp_network_id = bgp_advertised_networks.select { |bgp_advertised_network| bgp_advertised_network['subnetAddress'] == d.split("/")[0] && bgp_advertised_network['subnetLength'] == d.split("/")[1] }[0]["id"]
call_delete_bgp_network(bgp_network_id)
end
tba_bgp_networks.each { |a| call_advertise_bgp_network(provider_router_id, a) }
# Get routes and see which ones do we need to actually create
dup_routes = Array.new
existing_bgp_routes = call_get_bgp_routes(provider_router_id)
neighbors_remote_net = bgp_neighbors_resource.map { |x| x['remote_net'] }.uniq
existing_bgp_routes.each do |r|
dup_routes << r if neighbors_remote_net.select { |net| net == "#{r['dstNetworkAddr']}/#{r['dstNetworkLength']}" }
end
# Add routes to remote BGP peers
tba_routes = neighbors_remote_net - dup_routes.map { |dr| "#{dr['dstNetworkAddr']}/#{dr['dstNetworkLength']}" }
tba_routes.each do |r|
call_add_bgp_route(provider_router_id, r)
end
# Add default routes
dup_routes = Array.new
existing_bgp_routes = call_get_bgp_routes(provider_router_id)
neighbors_remote_ips = bgp_neighbors_resource.map { |x| x['ip_address'] }.uniq
existing_bgp_routes.each do |r|
dup_routes << r if neighbors_remote_ips.select { |ip| ip == "#{r['nextHopGateway']}" }
end
# Add routes to remote BGP peers
tba_routes = neighbors_remote_ips - dup_routes.map { |dr| "#{dr['nextHopGateway']}" }
tba_routes.each do |ip|
b = bgp_neighbors_resource.select { |neighbor| neighbor['ip_address'] == ip }
call_add_default_routes(provider_router_id, bgp_neighbors_resource.select { |neighbor| neighbor['ip_address'] == ip }[0])
end
end
def destroy
define_connection(resource[:midonet_api_url])
# Get the edge router uuid
provider_router_id = call_get_provider_router()[0]['id']
# "Unset" asNumber by setting it to -1 (default value)
call_assign_asn(provider_router_id, "-1")
# Remove BGP peers from router
bgp_peers = call_get_bgp_peers(provider_router_id)
bgp_peers.each do |bgp_peer|
call_delete_bgp_peer(bgp_peer["id"])
end
# De-advertise floating IP networks
bgp_networks = call_get_bgp_networks(provider_router_id)
bgp_networks.each do |bgp_network|
call_delete_bgp_network(bgp_network["id"])
end
end
def exists?
if resource[:bgp_neighbors].class == Hash
bgp_neighbors_resource = [resource[:bgp_neighbors]]
else
bgp_neighbors_resource = resource[:bgp_neighbors]
end
if resource[:bgp_advertised_networks].class == String
bgp_advertised_networks_resource = [resource[:bgp_advertised_networks]]
else
bgp_advertised_networks_resource = resource[:bgp_advertised_networks]
end
define_connection(resource[:midonet_api_url])
entered_neighbors_parsed = bgp_neighbors_resource.collect { |x| {'ip_address' => x['ip_address'], 'remote_asn' => x['remote_asn'].to_i} }
# Get the edge router uuid
provider_router = call_get_provider_router()[0]
provider_router_id = provider_router['id']
result_array = Array.new
# Check if local ASN is the same
result_array.push(provider_router["asNumber"].to_i == resource[:bgp_local_as_number].to_i)
# Check if BGP neighbors are the same
bgp_neighbors = call_get_bgp_peers(provider_router_id)
m = Array.new
bgp_neighbors.each do |bgp_neighbor|
n = { "ip_address" => bgp_neighbor["address"],
"remote_asn" => bgp_neighbor["asNumber"] }
m << n
end
result_array.push(m == entered_neighbors_parsed)
# Check if advertised networks are the same
bgp_advertised_networks = call_get_bgp_networks(provider_router_id)
j = Array.new
bgp_advertised_networks.each do |bgp_advertised_network|
k = [ bgp_advertised_network["subnetAddress"], bgp_advertised_network["subnetLength"] ].join("/")
j << k
end
result_array.push(j == bgp_advertised_networks_resource)
# Test if all tests are positive
return result_array.uniq == [true]
end
def define_connection(url)
@connection = Faraday.new(:url => url,
:ssl => { :verify =>false }) do |builder|
builder.request(:retry, {
:max => 5,
:interval => 0.05,
:exceptions => [
Faraday::Error::TimeoutError,
Faraday::ConnectionFailed,
Errno::ETIMEDOUT,
'Timeout::Error',
],
})
builder.request(:basic_auth, resource[:username], resource[:password])
builder.adapter(:net_http)
end
@connection.headers['X-Auth-Token'] = call_get_token()
end
def call_get_token()
res = @connection.get do |req|
req.headers['X-Auth-Project'] = resource[:tenant_name]
req.url "/midonet-api/login"
end
return JSON.parse(res.body)['key']
end
def call_get_provider_router()
res = @connection.get do |req|
req.url "/midonet-api/routers"
end
output = JSON.parse(res.body)
provider_router = output.select { |r| r['name'] == resource[:router]}
raise "Router #{resource[:router]} does not exist" if provider_router.empty?
return provider_router
end
def call_assign_asn( provider_router, bgp_local_as_number )
res = @connection.put do |req|
req.url "/midonet-api/routers/#{provider_router['id']}"
req.headers['Content-Type'] = "application/vnd.org.midonet.Router-v3+json"
req.body = {
'asNumber' => bgp_local_as_number,
'adminStateUp' => provider_router['adminStateUp'],
'inboundFilterId' => provider_router['inboundFilterId'],
'inboundMirrorIds' => provider_router['inboundMirrorIds'],
'name' => provider_router['name'],
'outboundFilterId' => provider_router['outboundFilterId'],
'outboundMirrorIds' => provider_router['outboundMirrorIds'],
'tenantId' => provider_router['tenantId']
}.to_json
end
end
def call_add_bgp_peer( provider_router_id, ip_address, remote_asn )
res = @connection.post do |req|
req.url "/midonet-api/routers/#{provider_router_id}/bgp_peers"
req.headers['Content-Type'] = "application/vnd.org.midonet.BgpPeer-v1+json"
req.body = { 'address' => ip_address,
'asNumber' => remote_asn }.to_json
end
end
def call_add_bgp_route( provider_router_id, remote_network )
net_address, net_length = remote_network.split("/")
port = ''
router_ports = call_get_router_ports(provider_router_id)
router_ports.each do |rp|
port = rp if IPAddr.new("#{remote_network}").include?(rp['portAddress'])
end
unless port.empty?
res = @connection.post do |req|
req.url "/midonet-api/routers/#{provider_router_id}/routes"
req.headers['Content-Type'] = "application/vnd.org.midonet.Route-v1+json"
req.body = {
'dstNetworkAddr' => net_address,
'dstNetworkLength' => net_length,
'nextHopPort' => port['id'],
'srcNetworkAddr' => '0.0.0.0',
'srcNetworkLength' => '0',
'type' => 'Normal',
'weight' => '71'
}.to_json
end
end
end
def call_add_default_routes( provider_router_id, bgp_neighbor )
remote_ip = bgp_neighbor['remote_net']
remote_network = bgp_neighbor['remote_net']
net_address, net_length = remote_network.split("/")
port = ''
router_ports = call_get_router_ports(provider_router_id)
router_ports.each do |rp|
port = rp if IPAddr.new("#{remote_network}").include?(rp['portAddress'])
end
unless port.empty?
res = @connection.post do |req|
req.url "/midonet-api/routers/#{provider_router_id}/routes"
req.headers['Content-Type'] = "application/vnd.org.midonet.Route-v1+json"
req.body = {
'dstNetworkAddr' => '0.0.0.0',
'dstNetworkLength' => '0',
'nextHopPort' => port['id'],
'nextHopGateway' => bgp_neighbor['ip_address'],
'srcNetworkAddr' => '0.0.0.0',
'srcNetworkLength' => '0',
'type' => 'Normal',
'weight' => '100'
}.to_json
end
end
end
def call_advertise_bgp_network( provider_router_id, bgp_advertised_network )
subnet_address, subnet_length = bgp_advertised_network.split("/")
res = @connection.post do |req|
req.url "/midonet-api/routers/#{provider_router_id}/bgp_networks"
req.headers['Content-Type'] = "application/vnd.org.midonet.BgpNetwork-v1+json"
req.body = { 'subnetAddress' => subnet_address,
'subnetLength' => subnet_length }.to_json
end
end
def call_delete_bgp_peer(bgp_peer_id)
res = @connection.delete do |req|
req.url "/midonet-api/bgp_peers/#{bgp_peer_id}"
end
end
def call_delete_bgp_network(bgp_network)
res = @connection.delete do |req|
req.url "/midonet-api/bgp_networks/#{bgp_network}"
end
end
def call_delete_bgp_route(route)
res = @connection.delete do |req|
req.url "/midonet-api/routes/#{route}"
end
end
def call_get_bgp_peers(provider_router_id)
res = @connection.get do |req|
req.url "/midonet-api/routers/#{provider_router_id}/bgp_peers"
end
output = JSON.parse(res.body)
return output
end
def call_get_router_ports(provider_router_id)
res = @connection.get do |req|
req.url "/midonet-api/routers/#{provider_router_id}/ports"
end
output = JSON.parse(res.body)
return output
end
def call_get_bgp_routes(provider_router_id)
res = @connection.get do |req|
req.url "/midonet-api/routers/#{provider_router_id}/routes"
end
output = JSON.parse(res.body)
return output
end
def call_get_bgp_networks(provider_router_id)
res = @connection.get do |req|
req.url "/midonet-api/routers/#{provider_router_id}/bgp_networks"
end
output = JSON.parse(res.body)
return output
end
private :call_get_provider_router
:define_connection
:call_assign_asn
:call_add_bgp_peer
:call_get_bgp_networks
:call_get_bgp_peers
:call_delete_bgp_network
:call_delete_bgp_peer
:call_advertise_bgp_network
end