
I've found problems running JSON on Ubuntu 14.04 even it seems like for ruby 1.9.3 JSON class should be loaded by default. Better meake sure it is loaded by forcing `require 'json'` in the begging of the providers. Change-Id: Ia01822b30d0a8a9f391fcd4f56b76bb7ce039258
310 lines
9.1 KiB
Ruby
310 lines
9.1 KiB
Ruby
if RUBY_VERSION == '1.8.7'
|
||
require 'rubygems'
|
||
end
|
||
|
||
require 'uri'
|
||
require 'faraday'
|
||
require 'json'
|
||
|
||
Puppet::Type.type(:midonet_gateway).provide(:midonet_api_caller) do
|
||
|
||
def create
|
||
define_connection(resource[:midonet_api_url])
|
||
# For each remote BGP peer, create a virtual port on
|
||
# the MidoNet Provider Router that is going to be used
|
||
# for the BGP communication. Connection to midonet api
|
||
# is assumed
|
||
|
||
router_id = call_get_provider_router()[0]['id']
|
||
|
||
message = Hash.new
|
||
message['portAddress'] = resource[:bgp_port]["port_address"]
|
||
message['networkAddress'] = resource[:bgp_port]["net_prefix"]
|
||
message['networkLength'] = resource[:bgp_port]["net_length"].to_i
|
||
message['type'] = "Router"
|
||
|
||
port = call_create_uplink_port(router_id, message)
|
||
port_id = port[0]['id']
|
||
|
||
# Configure BGP on the virtual ports. Port is
|
||
# assumed created
|
||
remote_peers = resource[:remote_peers]
|
||
if remote_peers.class == Hash
|
||
remote_peers = [remote_peers]
|
||
end
|
||
remote_peers.each do |rp|
|
||
message = Hash.new
|
||
message['localAS'] = resource[:local_as]
|
||
message['peerAS'] = rp["as"]
|
||
message['peerAddr'] = rp["ip"]
|
||
|
||
call_add_bgp_to_port(port_id, message)
|
||
end
|
||
|
||
# Add route for 'MidoNet Provider Router' uplink port
|
||
message = Hash.new
|
||
message['type'] = "Normal"
|
||
message['srcNetworkAddr'] = "0.0.0.0"
|
||
message['srcNetworkLength'] = 0
|
||
message['dstNetworkAddr'] = resource[:bgp_port]["net_prefix"]
|
||
message['dstNetworkLength'] = resource[:bgp_port]["net_length"].to_i
|
||
message['weight'] = 100
|
||
message['nextHopPort'] = port_id
|
||
|
||
call_add_route_for_uplink_port(router_id, message)
|
||
|
||
# In order to provide external connectivity for hosted
|
||
# virtual machines, the floating IP network has to be
|
||
# advertised to the BGP peers. BGP connection is assumed created
|
||
bgp_connections = call_get_bgp_connections(port_id)
|
||
|
||
#TODO(carmela): make this modification more elegant... or whatever
|
||
advertise_networks = resource[:advertise_net]
|
||
if advertise_networks.class == Hash
|
||
advertise_networks = [advertise_networks]
|
||
end
|
||
bgp_connections.each do |bgp_c|
|
||
advertise_networks.each do |net|
|
||
message = Hash.new
|
||
message['nwPrefix'] = net["net_prefix"]
|
||
message['prefixLength'] = net["net_length"]
|
||
|
||
bgp_id = bgp_c["id"]
|
||
call_advertise_route_to_bgp(bgp_id, message)
|
||
end
|
||
end
|
||
|
||
# Bind the MidoNet Provider Router’s virtual ports to
|
||
# the physical network interfaces on the Gateway Nodes.
|
||
# Host and port are assumed created. Interface name should
|
||
# be an string
|
||
host_id = call_get_host()[0]['id']
|
||
|
||
message = Hash.new
|
||
message['interfaceName'] = resource[:interface]
|
||
message['portId'] = port_id
|
||
|
||
call_bind_port_to_interface(host_id, message)
|
||
|
||
# Configure a stateful port group
|
||
spg = call_get_stateful_port_group()
|
||
if spg.empty?
|
||
message = Hash.new
|
||
message['name'] = "uplink-spg"
|
||
message['stateful'] = "true"
|
||
message['tenantId'] = call_get_tenant()
|
||
|
||
spg = call_create_stateful_port_group(message)
|
||
end
|
||
|
||
# Add the ports to the port group
|
||
message = Hash.new
|
||
message['portId'] = port_id
|
||
|
||
call_add_ports_to_port_group(spg[0]["id"], message)
|
||
end
|
||
|
||
def destroy
|
||
define_connection(resource[:midonet_api_url])
|
||
|
||
router_id = call_get_provider_router()[0]['id']
|
||
port_address = resource[:bgp_port]['port_address']
|
||
|
||
port = call_get_uplink_port(router_id, port_address)
|
||
port_id = port[0]["id"]
|
||
|
||
# Delete the stateful port group
|
||
# TODO(carmela): delete only in case is the last port on the port group
|
||
# port_group_id = call_get_stateful_port_group()[0]['id']
|
||
# call_delete_stateful_port_group(port_group_id)
|
||
|
||
# Delete uplink port
|
||
call_delete_uplink_port(port_id)
|
||
end
|
||
|
||
def exists?
|
||
define_connection(resource[:midonet_api_url])
|
||
|
||
router = call_get_provider_router()
|
||
if router.empty?
|
||
raise 'MidoNet Provider Router does not exist. We cannot create uplink ports'
|
||
end
|
||
|
||
host = call_get_host()
|
||
if host.empty?
|
||
raise 'There is no MidoNet agent running on this host'
|
||
end
|
||
|
||
uplink_port = call_get_uplink_port(router[0]['id'], resource[:bgp_port]['port_address'])
|
||
if uplink_port.empty?
|
||
return false
|
||
end
|
||
|
||
return 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.url "/midonet-api/login"
|
||
end
|
||
return JSON.parse(res.body)['key']
|
||
end
|
||
|
||
def call_get_tenant()
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/tenants"
|
||
end
|
||
return JSON.parse(res.body)[0]['id']
|
||
end
|
||
|
||
def call_get_provider_router()
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/routers"
|
||
end
|
||
output = JSON.parse(res.body)
|
||
return output.select { |name| name['name'] == resource[:router]}
|
||
end
|
||
|
||
def call_get_stateful_port_group()
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/port_groups"
|
||
end
|
||
output = JSON.parse(res.body)
|
||
return output.select { |name| name['name'] == 'uplink-spg'}
|
||
|
||
end
|
||
|
||
def call_get_uplink_port(router_id, port_address)
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/routers/#{router_id}/ports"
|
||
end
|
||
output = JSON.parse(res.body)
|
||
return output.select { |port| port['portAddress'] == port_address }
|
||
|
||
end
|
||
|
||
def call_get_host()
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/hosts"
|
||
end
|
||
output = JSON.parse(res.body)
|
||
return output.select{ |host| host['name'] == resource[:hostname].to_s }
|
||
end
|
||
|
||
def call_create_uplink_port(router_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/routers/#{router_id}/ports"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.Port-v2+json"
|
||
req.body = message.to_json
|
||
end
|
||
return call_get_uplink_port(router_id, message["portAddress"])
|
||
end
|
||
|
||
def call_delete_uplink_port(port_id)
|
||
res = @connection.delete do |req|
|
||
req.url "/midonet-api/ports/#{port_id}"
|
||
end
|
||
end
|
||
|
||
def call_add_bgp_to_port(port_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/ports/#{port_id}/bgps"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.Bgp-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
end
|
||
|
||
def call_add_route_for_uplink_port(router_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/routers/#{router_id}/routes"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.Route-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
end
|
||
|
||
def call_get_bgp_connections(port_id)
|
||
res = @connection.get do |req|
|
||
req.url "/midonet-api/ports/#{port_id}/bgps"
|
||
end
|
||
output = JSON.parse(res.body)
|
||
return output
|
||
end
|
||
|
||
def call_advertise_route_to_bgp(bgp_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/bgps/#{bgp_id}/ad_routes"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.AdRoute-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
end
|
||
|
||
def call_bind_port_to_interface(host_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/hosts/#{host_id}/ports"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.HostInterfacePort-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
end
|
||
|
||
def call_create_stateful_port_group(message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/port_groups"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.PortGroup-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
return call_get_stateful_port_group()
|
||
end
|
||
|
||
def call_add_ports_to_port_group(port_group_id, message)
|
||
res = @connection.post do |req|
|
||
req.url "/midonet-api/port_groups/#{port_group_id}/ports"
|
||
req.headers['Content-Type'] = "application/vnd.org.midonet.PortGroupPort-v1+json"
|
||
req.body = message.to_json
|
||
end
|
||
end
|
||
|
||
def call_delete_stateful_port_group(port_group_id)
|
||
res = @connection.delete do |req|
|
||
req.url "/midonet-api/port_groups/#{port_group_id}"
|
||
end
|
||
end
|
||
|
||
private :call_add_bgp_to_port
|
||
:call_add_ports_to_port_group
|
||
:call_add_route_for_uplink_port
|
||
:call_advertise_route_to_bgp
|
||
:call_bind_port_to_interface
|
||
:call_create_stateful_port_group
|
||
:call_create_uplink_port
|
||
:call_delete_stateful_port_group
|
||
:call_delete_uplink_port
|
||
:call_get_bgp_connections
|
||
:call_get_host
|
||
:call_get_stateful_port_group
|
||
:call_get_provider_router
|
||
:call_get_tenant
|
||
:call_get_uplink_port
|
||
:define_connection
|
||
end
|