From 9e7b767feac5c39c422786ae92fa91d3c515caeb Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Fri, 22 Feb 2013 16:47:22 +0900 Subject: [PATCH 01/23] supported OpenStack Quantum Router Operation. not include mock code. --- lib/fog/openstack/models/network/router.rb | 53 +++++++++++++++++++ lib/fog/openstack/models/network/routers.rb | 34 ++++++++++++ lib/fog/openstack/network.rb | 10 ++++ .../requests/network/add_router_interface.rb | 47 ++++++++++++++++ .../requests/network/create_router.rb | 46 ++++++++++++++++ .../requests/network/delete_router.rb | 30 +++++++++++ .../openstack/requests/network/get_router.rb | 48 +++++++++++++++++ .../requests/network/list_routers.rb | 27 ++++++++++ .../network/remove_router_interface.rb | 47 ++++++++++++++++ .../requests/network/update_router.rb | 46 ++++++++++++++++ 10 files changed, 388 insertions(+) create mode 100644 lib/fog/openstack/models/network/router.rb create mode 100644 lib/fog/openstack/models/network/routers.rb create mode 100644 lib/fog/openstack/requests/network/add_router_interface.rb create mode 100644 lib/fog/openstack/requests/network/create_router.rb create mode 100644 lib/fog/openstack/requests/network/delete_router.rb create mode 100644 lib/fog/openstack/requests/network/get_router.rb create mode 100644 lib/fog/openstack/requests/network/list_routers.rb create mode 100644 lib/fog/openstack/requests/network/remove_router_interface.rb create mode 100644 lib/fog/openstack/requests/network/update_router.rb diff --git a/lib/fog/openstack/models/network/router.rb b/lib/fog/openstack/models/network/router.rb new file mode 100644 index 000000000..2a19cad69 --- /dev/null +++ b/lib/fog/openstack/models/network/router.rb @@ -0,0 +1,53 @@ +require 'fog/core/model' + +module Fog + module Network + class OpenStack + class Router < Fog::Model + identity :id + + attribute :name + attribute :network_id + attribute :fixed_ips + attribute :mac_address + attribute :status + attribute :admin_state_up + attribute :device_owner + attribute :device_id + attribute :tenant_id + + def initialize(attributes) + # Old 'connection' is renamed as service and should be used instead + prepare_service_value(attributes) + super + end + + def save + requires :name + identity ? update : create + end + + def create + requires :name + merge_attributes(service.create_router(self.name, + self.attributes).body['router']) + self + end + + def update + requires :id + merge_attributes(service.update_router(self.id, + self.attributes).body['router']) + self + end + + def destroy + requires :id + service.delete_router(self.id) + true + end + + end + end + end +end diff --git a/lib/fog/openstack/models/network/routers.rb b/lib/fog/openstack/models/network/routers.rb new file mode 100644 index 000000000..79892a00c --- /dev/null +++ b/lib/fog/openstack/models/network/routers.rb @@ -0,0 +1,34 @@ +require 'fog/core/collection' +require 'fog/openstack/models/network/router' + +module Fog + module Network + class OpenStack + class Routers < Fog::Collection + + attribute :filters + + model Fog::Network::OpenStack::Router + + def initialize(attributes) + self.filters ||= {} + super + end + + def all(filters = filters) + self.filters = filters + load(service.list_routers(filters).body['routers']) + end + + def get(router_id) + if router = service.get_router(router_id).body['router'] + new(router) + end + rescue Fog::Network::OpenStack::NotFound + nil + end + + end + end + end +end diff --git a/lib/fog/openstack/network.rb b/lib/fog/openstack/network.rb index 2d84c0574..a9ee2afa0 100644 --- a/lib/fog/openstack/network.rb +++ b/lib/fog/openstack/network.rb @@ -40,6 +40,15 @@ module Fog request :get_port request :update_port + # Router CRUD + request :list_routers + request :create_router + request :delete_router + request :get_router + request :update_router + request :add_router_interface + request :remove_router_interface + # Subnet CRUD request :list_subnets request :create_subnet @@ -66,6 +75,7 @@ module Fog :ports => {}, :subnets => {}, :floating_ips => {}, + :routers => {}, } end end diff --git a/lib/fog/openstack/requests/network/add_router_interface.rb b/lib/fog/openstack/requests/network/add_router_interface.rb new file mode 100644 index 000000000..88bc7d0d5 --- /dev/null +++ b/lib/fog/openstack/requests/network/add_router_interface.rb @@ -0,0 +1,47 @@ +module Fog + module Network + class OpenStack + + class Real + def add_router_interface(router_id, subnet_id, options = {}) + data = { + 'subnet_id' => subnet_id, + } + + vanilla_options = [:name] + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['subnet_id'][key] = options[key] + end + + request( + :body => Fog::JSON.encode(data), + :expects => [200], + :method => 'PUT', + :path => "routers/#{router_id}/add_router_interface" + ) + end + end + + class Mock + def add_router_interface(floating_ip_id, port_id, options = {}) + response = Excon::Response.new + response.status = 201 + data = { + 'id' => '00000000-0000-0000-0000-000000000000', + 'router_id' => '00000000-0000-0000-0000-000000000000', + 'tenant_id' => options["tenant_id"], + 'floating_network_id' => options["floating_network_id"], + 'fixed_ip_address' => options["fixed_ip_address"], + 'floating_ip_address' => options["floating_ip_address"], + 'port_id' => port_id, + } + + self.data[:floating_ips][data['floating_ip_id']] = data + response.body = { 'floating_ip' => data } + response + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb new file mode 100644 index 000000000..1bf5d2416 --- /dev/null +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -0,0 +1,46 @@ +module Fog + module Network + class OpenStack + + class Real + def create_router(name, options = {}) + data = { + 'router' => { + 'name' => name, + } + } + + vanilla_options = [:admin_state_up, :tenand_id] + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['router'][key] = options[key] + end + + request( + :body => Fog::JSON.encode(data), + :expects => [201], + :method => 'POST', + :path => 'routers' + ) + end + end + + class Mock + def create_router(name, options = {}) + response = Excon::Response.new + response.status = 201 + data = { + 'id' => Fog::Mock.random_numbers(6).to_s, + 'name' => options[:name], + 'status' => 'ACTIVE', + 'admin_state_up' => options[:admin_state_up], + 'tenant_id' => options[:tenant_id], + } + self.data[:routers][data['id']] = data + response.body = { 'router' => data } + response + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/delete_router.rb b/lib/fog/openstack/requests/network/delete_router.rb new file mode 100644 index 000000000..5f957aab3 --- /dev/null +++ b/lib/fog/openstack/requests/network/delete_router.rb @@ -0,0 +1,30 @@ +module Fog + module Network + class OpenStack + + class Real + def delete_router(router_id) + request( + :expects => 204, + :method => 'DELETE', + :path => "routers/#{router_id}" + ) + end + end + + class Mock + def delete_router(router_id) + response = Excon::Response.new + if list_routers.body['routers'].map { |r| r['id'] }.include? router_id + self.data[:routers].delete(router_id) + response.status = 204 + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/get_router.rb b/lib/fog/openstack/requests/network/get_router.rb new file mode 100644 index 000000000..a0f720529 --- /dev/null +++ b/lib/fog/openstack/requests/network/get_router.rb @@ -0,0 +1,48 @@ +module Fog + module Network + class OpenStack + + class Real + def get_router(router_id) + request( + :expects => [200], + :method => 'GET', + :path => "routers/#{router_id}" + ) + end + end + + class Mock + def get_router(router_id) + response = Excon::Response.new + if data = self.data[:routers][router_id] + response.status = 200 + response.body = { + 'router' => { + 'id' => '5c81d975-5fea-4674-9c1f-b8aa10bf9a79', + 'name' => 'router_1', + 'network_id' => 'e624a36d-762b-481f-9b50-4154ceb78bbb', + 'fixed_ips' => [ + { + 'ip_address' => '10.2.2.2', + 'subnet_id' => '2e4ec6a4-0150-47f5-8523-e899ac03026e', + } + ], + 'mac_address' => 'fa:16:3e:62:91:7f', + 'status' => 'ACTIVE', + 'admin_state_up' => true, + 'device_id' => 'dhcp724fc160-2b2e-597e-b9ed-7f65313cd73f-e624a36d-762b-481f-9b50-4154ceb78bbb', + 'device_owner' => 'network:dhcp', + 'tenant_id' => 'f8b26a6032bc47718a7702233ac708b9', + } + } + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/list_routers.rb b/lib/fog/openstack/requests/network/list_routers.rb new file mode 100644 index 000000000..3f692c369 --- /dev/null +++ b/lib/fog/openstack/requests/network/list_routers.rb @@ -0,0 +1,27 @@ +module Fog + module Network + class OpenStack + + class Real + def list_routers(filters = {}) + request( + :expects => 200, + :method => 'GET', + :path => 'routers', + :query => filters + ) + end + end + + class Mock + def list_routers(filters = {}) + Excon::Response.new( + :body => { 'routers' => self.data[:routers].values }, + :status => 200 + ) + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/remove_router_interface.rb b/lib/fog/openstack/requests/network/remove_router_interface.rb new file mode 100644 index 000000000..92857dd24 --- /dev/null +++ b/lib/fog/openstack/requests/network/remove_router_interface.rb @@ -0,0 +1,47 @@ +module Fog + module Network + class OpenStack + + class Real + def remove_router_interface(router_id, subnet_id, options = {}) + data = { + 'subnet_id' => subnet_id, + } + + vanilla_options = [:name] + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['subnet_id'][key] = options[key] + end + + request( + :body => Fog::JSON.encode(data), + :expects => [200], + :method => 'PUT', + :path => "routers/#{router_id}/remove_router_interface" + ) + end + end + + class Mock + def remove_router_interface(floating_ip_id, port_id, options = {}) + response = Excon::Response.new + response.status = 201 + data = { + 'id' => '00000000-0000-0000-0000-000000000000', + 'router_id' => '00000000-0000-0000-0000-000000000000', + 'tenant_id' => options["tenant_id"], + 'floating_network_id' => options["floating_network_id"], + 'fixed_ip_address' => options["fixed_ip_address"], + 'floating_ip_address' => options["floating_ip_address"], + 'port_id' => port_id, + } + + self.data[:floating_ips][data['floating_ip_id']] = data + response.body = { 'floating_ip' => data } + response + end + end + + end + end +end diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb new file mode 100644 index 000000000..74316b896 --- /dev/null +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -0,0 +1,46 @@ +module Fog + module Network + class OpenStack + + class Real + def update_router(router_id, network_id, options = {}) + data = { + 'router' => { + 'external_gateway_info' => { + 'network_id' => network_id, + } + } + } + vanilla_options = [:name, :admin_state_up, :tenand_id] + vanilla_options.select{ |o| options.has_key?(o) }.each do |key| + data['router'][key] = options[key] + end + + request( + :body => Fog::JSON.encode(data), + :expects => 200, + :method => 'PUT', + :path => "routers/#{router_id}.json" + ) + end + end + + class Mock + def update_router(router_id, options = {}) + response = Excon::Response.new + if router = list_routers.body['routers'].detect { |_| _['id'] == router_id } + router['name'] = options[:name] + router['admin_state_up'] = options[:admin_state_up] + router['tenant_id'] = options[:tenant_id] + response.body = { 'router' => router } + response.status = 200 + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + + end + end +end From 81c67e79c1f7be849df01c72738cd9464c66e7a1 Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Fri, 22 Feb 2013 18:35:15 +0900 Subject: [PATCH 02/23] added mock code for router operation. --- lib/fog/openstack/models/network/router.rb | 6 +---- lib/fog/openstack/network.rb | 18 ++++++------- .../requests/network/add_router_interface.rb | 26 ++++++++++++------- .../requests/network/create_router.rb | 13 ++++++---- .../openstack/requests/network/get_router.rb | 21 +++++---------- .../network/remove_router_interface.rb | 14 +++------- .../requests/network/update_router.rb | 26 +++++++++++-------- 7 files changed, 60 insertions(+), 64 deletions(-) diff --git a/lib/fog/openstack/models/network/router.rb b/lib/fog/openstack/models/network/router.rb index 2a19cad69..7d87dc6cc 100644 --- a/lib/fog/openstack/models/network/router.rb +++ b/lib/fog/openstack/models/network/router.rb @@ -8,12 +8,8 @@ module Fog attribute :name attribute :network_id - attribute :fixed_ips - attribute :mac_address - attribute :status + attribute :subnet_id attribute :admin_state_up - attribute :device_owner - attribute :device_id attribute :tenant_id def initialize(attributes) diff --git a/lib/fog/openstack/network.rb b/lib/fog/openstack/network.rb index a9ee2afa0..16e3699cb 100644 --- a/lib/fog/openstack/network.rb +++ b/lib/fog/openstack/network.rb @@ -40,15 +40,6 @@ module Fog request :get_port request :update_port - # Router CRUD - request :list_routers - request :create_router - request :delete_router - request :get_router - request :update_router - request :add_router_interface - request :remove_router_interface - # Subnet CRUD request :list_subnets request :create_subnet @@ -64,6 +55,15 @@ module Fog request :associate_floating_ip request :disassociate_floating_ip + # Router CRUD + request :list_routers + request :create_router + request :delete_router + request :get_router + request :update_router + request :add_router_interface + request :remove_router_interface + # Tenant request :set_tenant diff --git a/lib/fog/openstack/requests/network/add_router_interface.rb b/lib/fog/openstack/requests/network/add_router_interface.rb index 88bc7d0d5..ac24ffe46 100644 --- a/lib/fog/openstack/requests/network/add_router_interface.rb +++ b/lib/fog/openstack/requests/network/add_router_interface.rb @@ -23,21 +23,27 @@ module Fog end class Mock - def add_router_interface(floating_ip_id, port_id, options = {}) + def add_router_interface(router_id, subnet_id, options = {}) response = Excon::Response.new response.status = 201 data = { - 'id' => '00000000-0000-0000-0000-000000000000', - 'router_id' => '00000000-0000-0000-0000-000000000000', - 'tenant_id' => options["tenant_id"], - 'floating_network_id' => options["floating_network_id"], - 'fixed_ip_address' => options["fixed_ip_address"], - 'floating_ip_address' => options["floating_ip_address"], - 'port_id' => port_id, + 'status' => 'ACTIVE', + 'name' => '', + 'admin_state_up' => true, + 'network_id' => '5307648b-e836-4658-8f1a-ff7536870c64', + 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', + 'device_owner' => 'network:router_interface', + 'mac_address' => 'fa:16:3e:f7:d1:9c', + 'fixed_ips' => { + 'subnet_id' => 'a2f1f29d-571b-4533-907f-5803ab96ead1', + 'ip_address' => '10.1.1.1' + }, + 'id' => '3a44f4e5-1694-493a-a1fb-393881c673a4', + 'device_id' => '7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b' } - self.data[:floating_ips][data['floating_ip_id']] = data - response.body = { 'floating_ip' => data } + self.data[:routers][data['router_id']] = data + response.body = { 'router' => data } response end end diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb index 1bf5d2416..d7c48af9d 100644 --- a/lib/fog/openstack/requests/network/create_router.rb +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -29,11 +29,14 @@ module Fog response = Excon::Response.new response.status = 201 data = { - 'id' => Fog::Mock.random_numbers(6).to_s, - 'name' => options[:name], - 'status' => 'ACTIVE', - 'admin_state_up' => options[:admin_state_up], - 'tenant_id' => options[:tenant_id], + 'router' => { + 'status' => 'ACTIVE', + 'external_gateway_info' => null, + 'name' => 'another_router', + 'admin_state_up' => true, + 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', + 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' + } } self.data[:routers][data['id']] = data response.body = { 'router' => data } diff --git a/lib/fog/openstack/requests/network/get_router.rb b/lib/fog/openstack/requests/network/get_router.rb index a0f720529..8e86817cc 100644 --- a/lib/fog/openstack/requests/network/get_router.rb +++ b/lib/fog/openstack/requests/network/get_router.rb @@ -18,22 +18,15 @@ module Fog if data = self.data[:routers][router_id] response.status = 200 response.body = { - 'router' => { - 'id' => '5c81d975-5fea-4674-9c1f-b8aa10bf9a79', - 'name' => 'router_1', - 'network_id' => 'e624a36d-762b-481f-9b50-4154ceb78bbb', - 'fixed_ips' => [ - { - 'ip_address' => '10.2.2.2', - 'subnet_id' => '2e4ec6a4-0150-47f5-8523-e899ac03026e', - } - ], - 'mac_address' => 'fa:16:3e:62:91:7f', + 'routers' => { 'status' => 'ACTIVE', + 'external_gateway_info' => { + 'network_id' => '3c5bcddd-6af9-4e6b-9c3e-c153e521cab8' + }, + 'name' => 'router1', 'admin_state_up' => true, - 'device_id' => 'dhcp724fc160-2b2e-597e-b9ed-7f65313cd73f-e624a36d-762b-481f-9b50-4154ceb78bbb', - 'device_owner' => 'network:dhcp', - 'tenant_id' => 'f8b26a6032bc47718a7702233ac708b9', + 'tenant_id' => '33a40233088643acb66ff6eb0ebea679', + 'id' => 'a9254bdb-2613-4a13-ac4c-adc581fba50d' } } response diff --git a/lib/fog/openstack/requests/network/remove_router_interface.rb b/lib/fog/openstack/requests/network/remove_router_interface.rb index 92857dd24..d90f83ca6 100644 --- a/lib/fog/openstack/requests/network/remove_router_interface.rb +++ b/lib/fog/openstack/requests/network/remove_router_interface.rb @@ -23,21 +23,15 @@ module Fog end class Mock - def remove_router_interface(floating_ip_id, port_id, options = {}) + def remove_router_interface(router_id, subnet_id, options = {}) response = Excon::Response.new response.status = 201 data = { - 'id' => '00000000-0000-0000-0000-000000000000', - 'router_id' => '00000000-0000-0000-0000-000000000000', - 'tenant_id' => options["tenant_id"], - 'floating_network_id' => options["floating_network_id"], - 'fixed_ip_address' => options["fixed_ip_address"], - 'floating_ip_address' => options["floating_ip_address"], - 'port_id' => port_id, + 'subnet_id' => 'a2f1f29d-571b-4533-907f-5803ab96ead1' } - self.data[:floating_ips][data['floating_ip_id']] = data - response.body = { 'floating_ip' => data } + self.data[:routers][data['router_id']] = data + response.body = { 'router' => data } response end end diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb index 74316b896..c19463cb2 100644 --- a/lib/fog/openstack/requests/network/update_router.rb +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -26,18 +26,22 @@ module Fog end class Mock - def update_router(router_id, options = {}) + def update_router(router_id, network_id, options = {}) response = Excon::Response.new - if router = list_routers.body['routers'].detect { |_| _['id'] == router_id } - router['name'] = options[:name] - router['admin_state_up'] = options[:admin_state_up] - router['tenant_id'] = options[:tenant_id] - response.body = { 'router' => router } - response.status = 200 - response - else - raise Fog::Network::OpenStack::NotFound - end + response.status = 201 + data = { + 'status' => 'ACTIVE', + 'external_gateway_info' => { + 'network_id' => '8ca37218-28ff-41cb-9b10-039601ea7e6b' + }, + 'name' => 'another_router', + 'admin_state_up' => true, + 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', + 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' + } + self.data[:router_id][data['router_id']] = data + response.body = { 'router_id' => data } + response end end From 0f3f3994abc7bc78adbc15a6f68483bb6350bf0a Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Fri, 22 Feb 2013 19:11:13 +0900 Subject: [PATCH 03/23] fixed responce data from mock and removed vanilla options reject code. --- lib/fog/openstack/requests/network/add_router_interface.rb | 5 ----- lib/fog/openstack/requests/network/create_router.rb | 5 ----- .../openstack/requests/network/remove_router_interface.rb | 5 ----- lib/fog/openstack/requests/network/update_router.rb | 6 +----- 4 files changed, 1 insertion(+), 20 deletions(-) diff --git a/lib/fog/openstack/requests/network/add_router_interface.rb b/lib/fog/openstack/requests/network/add_router_interface.rb index ac24ffe46..afa4ca6ae 100644 --- a/lib/fog/openstack/requests/network/add_router_interface.rb +++ b/lib/fog/openstack/requests/network/add_router_interface.rb @@ -8,11 +8,6 @@ module Fog 'subnet_id' => subnet_id, } - vanilla_options = [:name] - vanilla_options.reject{ |o| options[o].nil? }.each do |key| - data['subnet_id'][key] = options[key] - end - request( :body => Fog::JSON.encode(data), :expects => [200], diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb index d7c48af9d..31d589475 100644 --- a/lib/fog/openstack/requests/network/create_router.rb +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -10,11 +10,6 @@ module Fog } } - vanilla_options = [:admin_state_up, :tenand_id] - vanilla_options.reject{ |o| options[o].nil? }.each do |key| - data['router'][key] = options[key] - end - request( :body => Fog::JSON.encode(data), :expects => [201], diff --git a/lib/fog/openstack/requests/network/remove_router_interface.rb b/lib/fog/openstack/requests/network/remove_router_interface.rb index d90f83ca6..c822ab1c4 100644 --- a/lib/fog/openstack/requests/network/remove_router_interface.rb +++ b/lib/fog/openstack/requests/network/remove_router_interface.rb @@ -8,11 +8,6 @@ module Fog 'subnet_id' => subnet_id, } - vanilla_options = [:name] - vanilla_options.reject{ |o| options[o].nil? }.each do |key| - data['subnet_id'][key] = options[key] - end - request( :body => Fog::JSON.encode(data), :expects => [200], diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb index c19463cb2..64c235824 100644 --- a/lib/fog/openstack/requests/network/update_router.rb +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -11,10 +11,6 @@ module Fog } } } - vanilla_options = [:name, :admin_state_up, :tenand_id] - vanilla_options.select{ |o| options.has_key?(o) }.each do |key| - data['router'][key] = options[key] - end request( :body => Fog::JSON.encode(data), @@ -40,7 +36,7 @@ module Fog 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' } self.data[:router_id][data['router_id']] = data - response.body = { 'router_id' => data } + response.body = { 'router' => data } response end end From 12923ffc4d09272ff863cb576a11d9cf9bd807b1 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 14:51:28 +0100 Subject: [PATCH 04/23] [openstack|network] create_network provider extensions Implements provider extensions when creating networks. See: http://docs.openstack.org/trunk/openstack-network/admin/content/provider_attributes.html Complements #1581 (Added missing Network model attributes) --- .../requests/network/create_network.rb | 28 +++++++- .../openstack/models/network/network_tests.rb | 17 +++++ .../requests/network/network_tests.rb | 66 ++++++++++++++++--- 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/lib/fog/openstack/requests/network/create_network.rb b/lib/fog/openstack/requests/network/create_network.rb index 77968b8a5..de0084b60 100644 --- a/lib/fog/openstack/requests/network/create_network.rb +++ b/lib/fog/openstack/requests/network/create_network.rb @@ -6,9 +6,31 @@ module Fog def create_network(options = {}) data = { 'network' => {} } - vanilla_options = [:name, :shared, :admin_state_up, :tenant_id] + vanilla_options = [ + :name, + :shared, + :admin_state_up, + :tenant_id, + :router_external, + :provider_network_type, + :provider_segmentation_id, + :provider_physical_network + ] + + # Advanced Features through API Extensions + # + # @see http://docs.openstack.org/trunk/openstack-network/admin/content/provider_attributes.html + aliases = { + :provider_network_type => 'provider:network_type', + # Not applicable to the "local" or "gre" network types + :provider_physical_network => 'provider:physical_network', + :provider_segmentation_id => 'provider:segmentation_id', + :router_external => 'router:external' + } + vanilla_options.reject{ |o| options[o].nil? }.each do |key| - data['network'][key] = options[key] + aliased_key = aliases[key] || key + data['network'][aliased_key] = options[key] end request( @@ -41,4 +63,4 @@ module Fog end end -end \ No newline at end of file +end diff --git a/tests/openstack/models/network/network_tests.rb b/tests/openstack/models/network/network_tests.rb index 28491f9f2..9aa05bafb 100644 --- a/tests/openstack/models/network/network_tests.rb +++ b/tests/openstack/models/network/network_tests.rb @@ -10,6 +10,23 @@ Shindo.tests("Fog::Network[:openstack] | network", ['openstack']) do !@instance.id.nil? end + tests('#create+extensions').succeeds do + net = Fog::Network[:openstack].networks.create( + :name => 'net_name', + :shared => false, + :admin_state_up => true, + :tenant_id => 'tenant_id', + :router_external => true, + # local, gre, vlan. Depends on the provider. + # May rise an exception if the network_type isn't valid: + # QuantumError: "Invalid input for operation: provider:physical_network" + :provider_network_type => 'gre', + :provider_segmentation_id => 22, + ) + net.destroy + net.provider_network_type == 'gre' + end + tests('have attributes') do attributes = [ :name, diff --git a/tests/openstack/requests/network/network_tests.rb b/tests/openstack/requests/network/network_tests.rb index cb6f4a890..adb9425f4 100644 --- a/tests/openstack/requests/network/network_tests.rb +++ b/tests/openstack/requests/network/network_tests.rb @@ -1,19 +1,44 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do @network_format = { - 'id' => String, - 'name' => String, - 'subnets' => Array, - 'shared' => Fog::Boolean, - 'status' => String, - 'admin_state_up' => Fog::Boolean, - 'tenant_id' => String, + 'id' => String, + 'name' => String, + 'subnets' => Array, + 'shared' => Fog::Boolean, + 'status' => String, + 'admin_state_up' => Fog::Boolean, + 'tenant_id' => String, + 'router:external' => Fog::Boolean, + 'provider:network_type' => String, + 'provider:physical_network' => Fog::Nullable::String, + 'provider:segmentation_id' => Integer, } tests('success') do tests('#create_network').formats({'network' => @network_format}) do - attributes = {:name => 'net_name', :shared => false, - :admin_state_up => true, :tenant_id => 'tenant_id'} + attributes = { + :name => 'net_name', + :shared => false, + :admin_state_up => true, + :tenant_id => 'tenant_id' + } + Fog::Network[:openstack].create_network(attributes).body + end + tests('#create_network+provider extensions').formats( + {'network' => @network_format} + ) do + attributes = { + :name => 'net_name', + :shared => false, + :admin_state_up => true, + :tenant_id => 'tenant_id', + :router_external => true, + # local, gre, vlan. Depends on the provider. + # May rise an exception if the network_type isn't valid: + # QuantumError: "Invalid input for operation: provider:physical_network" + :provider_network_type => 'gre', + :provider_segmentation_id => 22, + } Fog::Network[:openstack].create_network(attributes).body end @@ -40,6 +65,22 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do end tests('failure') do + tests('#create_network+provider extensions').raises( + Excon::Errors::BadRequest + ) do + attributes = { + :name => 'net_name', + :shared => false, + :admin_state_up => true, + :tenant_id => 'tenant_id', + :router_external => true, + # QuantumError: "Invalid input for operation: provider:physical_network" + :provider_network_type => 'foobar', + :provider_segmentation_id => 22, + } + Fog::Network[:openstack].create_network(attributes) + end + tests('#get_network').raises(Fog::Network::OpenStack::NotFound) do Fog::Network[:openstack].get_network(0) end @@ -52,5 +93,10 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do Fog::Network[:openstack].delete_network(0) end end + + # Cleaning up the mess + Fog::Network[:openstack].networks.each do |n| + Fog::Network[:openstack].delete_network(n.id) + end -end \ No newline at end of file +end From 9ae44ffd463021726200f6225b209e1ee61d57b9 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 17:09:43 +0100 Subject: [PATCH 05/23] [openstack|network] Added missing router model/collection --- lib/fog/openstack/network.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/fog/openstack/network.rb b/lib/fog/openstack/network.rb index 16e3699cb..3e35eff81 100644 --- a/lib/fog/openstack/network.rb +++ b/lib/fog/openstack/network.rb @@ -21,6 +21,8 @@ module Fog collection :subnets model :floating_ip collection :floating_ips + model :router + collection :routers ## REQUESTS # From bc6c35b49081f49c452c8ac7cc2b991a2e65a90c Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 17:10:47 +0100 Subject: [PATCH 06/23] [openstack|network] update_router request updates - Filter out invalid options - Add support for additional options: * name * admin_state_up - external_gateway_info can be either a Hash or a Fog::Network::OpenStack::Network (see docs) - Added documentation --- .../requests/network/update_router.rb | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb index 64c235824..bdcd74a55 100644 --- a/lib/fog/openstack/requests/network/update_router.rb +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -3,14 +3,44 @@ module Fog class OpenStack class Real - def update_router(router_id, network_id, options = {}) - data = { - 'router' => { - 'external_gateway_info' => { - 'network_id' => network_id, - } - } - } + + # Update Router + # + # Beyond the name and the administrative state, the only + # parameter which can be updated with this operation is + # the external gateway. + # + # router = Fog::Network[:openstack].routers.first + # net = Fog::Network[:openstack].networks.first + # + # # :external_gateway_info can be either a + # # Fog::Network::OpenStack::Network or a Hash + # # like { 'network_id' => network.id } + # Fog::Network[:openstack].update_router router.id, + # :name => 'foo', + # :external_gateway_info => net, + # :admin_state_up => true + # + # @see http://docs.openstack.org/api/openstack-network/2.0/content/router_update.html + def update_router(router_id, options = {}) + data = { 'router' => {} } + + vanilla_options = [:name, :admin_state_up] + + egi = options[:external_gateway_info] + if egi + if egi.is_a?(Fog::Network::OpenStack::Network) + data['router']['external_gateway_info'] = { 'network_id' => egi.id } + elsif egi.is_a?(Hash) and egi['network_id'] + data['router']['external_gateway_info'] = egi + else + raise ArgumentError.new('Invalid external_gateway_info attribute') + end + end + + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['router'][key] = options[key] + end request( :body => Fog::JSON.encode(data), From 8476de7f52901248575db7aca1afc0be1859bb8a Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 17:13:43 +0100 Subject: [PATCH 07/23] [openstack|network] router model updates - Added missing attributes - Added documentation --- lib/fog/openstack/models/network/router.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/fog/openstack/models/network/router.rb b/lib/fog/openstack/models/network/router.rb index 7d87dc6cc..6f4f2bcb5 100644 --- a/lib/fog/openstack/models/network/router.rb +++ b/lib/fog/openstack/models/network/router.rb @@ -3,6 +3,13 @@ require 'fog/core/model' module Fog module Network class OpenStack + # The Layer-3 Networking Extensions (router) + # + # A logical entity for forwarding packets across internal + # subnets and NATting them on external networks through + # an appropriate external gateway. + # + # @see http://docs.openstack.org/api/openstack-network/2.0/content/router_ext.html class Router < Fog::Model identity :id @@ -11,6 +18,8 @@ module Fog attribute :subnet_id attribute :admin_state_up attribute :tenant_id + attribute :external_gateway_info + attribute :status def initialize(attributes) # Old 'connection' is renamed as service and should be used instead From 596e54fec2ec50418786004a3b7fbf411f624b19 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 17:14:33 +0100 Subject: [PATCH 08/23] [openstack|network] create_router request updates - Filter out invalid options --- lib/fog/openstack/requests/network/create_router.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb index 31d589475..ca8694d9b 100644 --- a/lib/fog/openstack/requests/network/create_router.rb +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -10,6 +10,19 @@ module Fog } } + vanilla_options = [ + :admin_state_up, + :tenant_id, + :network_id, + :external_gateway_info, + :status, + :subnet_id + ] + + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['router'][key] = options[key] + end + request( :body => Fog::JSON.encode(data), :expects => [201], From 55cffa7ad05b7d4621d7c3c7db78f395aa92238c Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Tue, 26 Feb 2013 17:16:55 +0100 Subject: [PATCH 09/23] [openstack|network] Added missing router related tests --- .../openstack/models/network/router_tests.rb | 38 ++++++++++ .../openstack/models/network/routers_tests.rb | 21 ++++++ .../requests/network/router_tests.rb | 75 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/openstack/models/network/router_tests.rb create mode 100644 tests/openstack/models/network/routers_tests.rb create mode 100644 tests/openstack/requests/network/router_tests.rb diff --git a/tests/openstack/models/network/router_tests.rb b/tests/openstack/models/network/router_tests.rb new file mode 100644 index 000000000..faad48a76 --- /dev/null +++ b/tests/openstack/models/network/router_tests.rb @@ -0,0 +1,38 @@ +Shindo.tests("Fog::Network[:openstack] | router", ['openstack']) do + + tests('success') do + + tests('#create').succeeds do + @instance = Fog::Network[:openstack].routers.create( + :name => 'router_name', + :admin_state_up => true, + ) + !@instance.id.nil? + end + + tests('#update') do + test 'router name' do + @instance.name = 'new_name' + @instance.update.name == 'new_name' + end + # Needs code from issue #1598 + #test 'external_gateway_info' do + # net = Fog::Network[:openstack].networks.create( + # :name => 'net_name', + # :shared => false, + # :admin_state_up => true, + # :tenant_id => 'tenant_id', + # :router_external => true, + # ) + # @instance.external_gateway_info = net + # @instance.update + #end + end + + tests('#destroy').succeeds do + @instance.destroy == true + end + + end + +end diff --git a/tests/openstack/models/network/routers_tests.rb b/tests/openstack/models/network/routers_tests.rb new file mode 100644 index 000000000..9aca47d2c --- /dev/null +++ b/tests/openstack/models/network/routers_tests.rb @@ -0,0 +1,21 @@ +Shindo.tests("Fog::Network[:openstack] | routers", ['openstack']) do + @router = Fog::Network[:openstack].routers.create( + :name => 'router_name', + :admin_state_up => true, + ) + @routers = Fog::Network[:openstack].routers + + tests('success') do + + tests('#all').succeeds do + @routers.all + end + + tests('#get').succeeds do + @routers.get @router.id + end + + end + + @router.destroy +end diff --git a/tests/openstack/requests/network/router_tests.rb b/tests/openstack/requests/network/router_tests.rb new file mode 100644 index 000000000..a0df1a6e2 --- /dev/null +++ b/tests/openstack/requests/network/router_tests.rb @@ -0,0 +1,75 @@ +Shindo.tests('Fog::Network[:openstack] | router requests', ['openstack']) do + + @router_format = { + 'id' => String, + 'name' => String, + 'status' => String, + 'admin_state_up' => Fog::Boolean, + 'tenant_id' => String, + 'external_gateway_info' => Fog::Nullable::Hash, + } + + tests('success') do + tests('#create_router').formats({'router' => @router_format}) do + attributes = { + :admin_state_up => true, + :tenant_id => 'tenant_id' + } + Fog::Network[:openstack].create_router('router_name', attributes).body + end + + tests('#list_routers').formats({'routers' => [@router_format]}) do + Fog::Network[:openstack].list_routers.body + end + + tests('#get_router').formats({'router' => @router_format}) do + router_id = Fog::Network[:openstack].routers.all.first.id + Fog::Network[:openstack].get_router(router_id).body + end + + tests('#update_router').formats({'router' => @router_format}) do + router_id = Fog::Network[:openstack].routers.all.first.id + attributes = {} + { + :name => 'net_name', + :external_gateway_info => { :network_id => 'net_id' }, + :status => 'ACTIVE', + :admin_state_up => 'true' + } + Fog::Network[:openstack].update_router(router_id, attributes).body + end + + tests('#update_router_with_network').formats({'router' => @router_format}) do + router_id = Fog::Network[:openstack].routers.all.first.id + net = Fog::Network[:openstack].networks.first + attributes = {} + { + :name => 'net_name', + :external_gateway_info => net, + :status => 'ACTIVE', + :admin_state_up => 'true' + } + Fog::Network[:openstack].update_router(router_id, attributes).body + end + + tests('#delete_router').succeeds do + router_id = Fog::Network[:openstack].routers.all.last.id + Fog::Network[:openstack].delete_router(router_id) + end + end + + tests('failure') do + tests('#get_router').raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].get_router(0) + end + + tests('#update_router').raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].update_router(0, {}) + end + + tests('#delete_router').raises(Fog::Network::OpenStack::NotFound) do + Fog::Network[:openstack].delete_router(0) + end + end + +end From 54453be5642a8eb4c90fe5c5941211af12588da1 Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Thu, 28 Feb 2013 10:44:56 +0900 Subject: [PATCH 10/23] @rubiojr wrote mock code for openstack routers. --- lib/fog/openstack/requests/network/create_router.rb | 6 +++--- lib/fog/openstack/requests/network/get_router.rb | 4 ++-- lib/fog/openstack/requests/network/list_routers.rb | 2 +- lib/fog/openstack/requests/network/update_router.rb | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb index ca8694d9b..dd1386324 100644 --- a/lib/fog/openstack/requests/network/create_router.rb +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -39,15 +39,15 @@ module Fog data = { 'router' => { 'status' => 'ACTIVE', - 'external_gateway_info' => null, + 'external_gateway_info' => nil, 'name' => 'another_router', 'admin_state_up' => true, 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' } } - self.data[:routers][data['id']] = data - response.body = { 'router' => data } + self.data[:routers] = [] + self.data[:routers] << data['router'] response end end diff --git a/lib/fog/openstack/requests/network/get_router.rb b/lib/fog/openstack/requests/network/get_router.rb index 8e86817cc..d489e69c8 100644 --- a/lib/fog/openstack/requests/network/get_router.rb +++ b/lib/fog/openstack/requests/network/get_router.rb @@ -15,10 +15,10 @@ module Fog class Mock def get_router(router_id) response = Excon::Response.new - if data = self.data[:routers][router_id] + if data = (self.data[:routers].find { |r| r['id'] == router_id }) response.status = 200 response.body = { - 'routers' => { + 'router' => { 'status' => 'ACTIVE', 'external_gateway_info' => { 'network_id' => '3c5bcddd-6af9-4e6b-9c3e-c153e521cab8' diff --git a/lib/fog/openstack/requests/network/list_routers.rb b/lib/fog/openstack/requests/network/list_routers.rb index 3f692c369..de575cb31 100644 --- a/lib/fog/openstack/requests/network/list_routers.rb +++ b/lib/fog/openstack/requests/network/list_routers.rb @@ -16,7 +16,7 @@ module Fog class Mock def list_routers(filters = {}) Excon::Response.new( - :body => { 'routers' => self.data[:routers].values }, + :body => { 'routers' => (self.data[:routers] || []) }, :status => 200 ) end diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb index bdcd74a55..af25c7768 100644 --- a/lib/fog/openstack/requests/network/update_router.rb +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -52,7 +52,8 @@ module Fog end class Mock - def update_router(router_id, network_id, options = {}) + def update_router(router_id, options = {}) + raise Fog::Network::OpenStack::NotFound if router_id == 0 response = Excon::Response.new response.status = 201 data = { @@ -65,7 +66,6 @@ module Fog 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' } - self.data[:router_id][data['router_id']] = data response.body = { 'router' => data } response end From b9b237b2fcd94647683f48394043d44d6bd9a17a Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Mon, 4 Mar 2013 10:03:46 +0900 Subject: [PATCH 11/23] @rubiojr fixed mock test failure. --- lib/fog/openstack/requests/network/create_router.rb | 5 +++-- lib/fog/openstack/requests/network/get_router.rb | 2 +- lib/fog/openstack/requests/network/list_routers.rb | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/fog/openstack/requests/network/create_router.rb b/lib/fog/openstack/requests/network/create_router.rb index dd1386324..1b9a8dbdc 100644 --- a/lib/fog/openstack/requests/network/create_router.rb +++ b/lib/fog/openstack/requests/network/create_router.rb @@ -46,8 +46,9 @@ module Fog 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' } } - self.data[:routers] = [] - self.data[:routers] << data['router'] + self.data['routers'] ||= [] + self.data['routers'] << data['router'] + response.body = data response end end diff --git a/lib/fog/openstack/requests/network/get_router.rb b/lib/fog/openstack/requests/network/get_router.rb index d489e69c8..7e58a7514 100644 --- a/lib/fog/openstack/requests/network/get_router.rb +++ b/lib/fog/openstack/requests/network/get_router.rb @@ -15,7 +15,7 @@ module Fog class Mock def get_router(router_id) response = Excon::Response.new - if data = (self.data[:routers].find { |r| r['id'] == router_id }) + if data = (self.data['routers'].find { |r| r['id'] == router_id }) response.status = 200 response.body = { 'router' => { diff --git a/lib/fog/openstack/requests/network/list_routers.rb b/lib/fog/openstack/requests/network/list_routers.rb index de575cb31..18172f81b 100644 --- a/lib/fog/openstack/requests/network/list_routers.rb +++ b/lib/fog/openstack/requests/network/list_routers.rb @@ -16,7 +16,7 @@ module Fog class Mock def list_routers(filters = {}) Excon::Response.new( - :body => { 'routers' => (self.data[:routers] || []) }, + :body => { 'routers' => self.data['routers'] }, :status => 200 ) end From 0533db7f1e8a958f24bf9c0c832924524f82b877 Mon Sep 17 00:00:00 2001 From: Tomokazu Hirai Date: Tue, 5 Mar 2013 12:36:27 +0900 Subject: [PATCH 12/23] @rubiojr fixed mock faulure for router(s)_tests.rb --- .../requests/network/update_router.rb | 33 ++++++++++++------- .../openstack/models/network/router_tests.rb | 2 +- .../openstack/models/network/routers_tests.rb | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/fog/openstack/requests/network/update_router.rb b/lib/fog/openstack/requests/network/update_router.rb index af25c7768..19d5cda47 100644 --- a/lib/fog/openstack/requests/network/update_router.rb +++ b/lib/fog/openstack/requests/network/update_router.rb @@ -53,20 +53,29 @@ module Fog class Mock def update_router(router_id, options = {}) - raise Fog::Network::OpenStack::NotFound if router_id == 0 + router = self.data['routers'].find { |r| r['id'] == router_id } + raise Fog::Network::OpenStack::NotFound unless router + data = { 'router' => router } + + vanilla_options = [:name, :admin_state_up] + + egi = options[:external_gateway_info] + if egi + if egi.is_a?(Fog::Network::OpenStack::Network) + data['router']['external_gateway_info'] = { 'network_id' => egi.id } + elsif egi.is_a?(Hash) and egi['network_id'] + data['router']['external_gateway_info'] = egi + else + raise ArgumentError.new('Invalid external_gateway_info attribute') + end + end + + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['router'][key] = options[key] + end response = Excon::Response.new response.status = 201 - data = { - 'status' => 'ACTIVE', - 'external_gateway_info' => { - 'network_id' => '8ca37218-28ff-41cb-9b10-039601ea7e6b' - }, - 'name' => 'another_router', - 'admin_state_up' => true, - 'tenant_id' => '6b96ff0cb17a4b859e1e575d221683d3', - 'id' => '8604a0de-7f6b-409a-a47c-a1cc7bc77b2e' - } - response.body = { 'router' => data } + response.body = data response end end diff --git a/tests/openstack/models/network/router_tests.rb b/tests/openstack/models/network/router_tests.rb index faad48a76..9390fe8ee 100644 --- a/tests/openstack/models/network/router_tests.rb +++ b/tests/openstack/models/network/router_tests.rb @@ -5,7 +5,7 @@ Shindo.tests("Fog::Network[:openstack] | router", ['openstack']) do tests('#create').succeeds do @instance = Fog::Network[:openstack].routers.create( :name => 'router_name', - :admin_state_up => true, + :admin_state_up => true ) !@instance.id.nil? end diff --git a/tests/openstack/models/network/routers_tests.rb b/tests/openstack/models/network/routers_tests.rb index 9aca47d2c..f21014a1d 100644 --- a/tests/openstack/models/network/routers_tests.rb +++ b/tests/openstack/models/network/routers_tests.rb @@ -1,7 +1,7 @@ Shindo.tests("Fog::Network[:openstack] | routers", ['openstack']) do @router = Fog::Network[:openstack].routers.create( :name => 'router_name', - :admin_state_up => true, + :admin_state_up => true ) @routers = Fog::Network[:openstack].routers From 0ce5a9b0ce264e73057161a9a5a72c519003ac13 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Mon, 11 Mar 2013 21:20:09 +0100 Subject: [PATCH 13/23] [openstack|network] create_network provider extensions reworked - Differenciate provider and vanilla options - Fixed mocks --- .../requests/network/create_network.rb | 45 ++++++++++++++++--- .../requests/network/network_tests.rb | 11 +++-- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/lib/fog/openstack/requests/network/create_network.rb b/lib/fog/openstack/requests/network/create_network.rb index de0084b60..08902d2fd 100644 --- a/lib/fog/openstack/requests/network/create_network.rb +++ b/lib/fog/openstack/requests/network/create_network.rb @@ -10,16 +10,28 @@ module Fog :name, :shared, :admin_state_up, - :tenant_id, - :router_external, - :provider_network_type, - :provider_segmentation_id, - :provider_physical_network + :tenant_id ] + vanilla_options.reject{ |o| options[o].nil? }.each do |key| + data['network'][key] = options[key] + end + # Advanced Features through API Extensions # + # Not strictly required but commonly found in OpenStack + # installs with Quantum networking. + # # @see http://docs.openstack.org/trunk/openstack-network/admin/content/provider_attributes.html + provider_options = [ + :router_external, + :provider_network_type, + :provider_segmentation_id, + :provider_physical_network + ] + + # Map Fog::Network::OpenStack::Network + # model attributes to OpenStack provider attributes aliases = { :provider_network_type => 'provider:network_type', # Not applicable to the "local" or "gre" network types @@ -28,7 +40,7 @@ module Fog :router_external => 'router:external' } - vanilla_options.reject{ |o| options[o].nil? }.each do |key| + provider_options.reject{ |o| options[o].nil? }.each do |key| aliased_key = aliases[key] || key data['network'][aliased_key] = options[key] end @@ -55,6 +67,27 @@ module Fog 'admin_state_up' => options[:admin_state_up], 'tenant_id' => options[:tenant_id], } + + # Add provider specific attributes when found + # + provider_options = [ + :router_external, + :provider_network_type, + :provider_segmentation_id, + :provider_physical_network + ] + aliases = { + :provider_network_type => 'provider:network_type', + # Not applicable to the "local" or "gre" network types + :provider_physical_network => 'provider:physical_network', + :provider_segmentation_id => 'provider:segmentation_id', + :router_external => 'router:external' + } + provider_options.reject{ |o| options[o].nil? }.each do |key| + aliased_key = aliases[key] || key + data[aliased_key] = options[key] + end + self.data[:networks][data['id']] = data response.body = { 'network' => data } response diff --git a/tests/openstack/requests/network/network_tests.rb b/tests/openstack/requests/network/network_tests.rb index adb9425f4..ad1c32337 100644 --- a/tests/openstack/requests/network/network_tests.rb +++ b/tests/openstack/requests/network/network_tests.rb @@ -7,11 +7,14 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do 'shared' => Fog::Boolean, 'status' => String, 'admin_state_up' => Fog::Boolean, - 'tenant_id' => String, + 'tenant_id' => String + } + + @network_format_extensions = { 'router:external' => Fog::Boolean, 'provider:network_type' => String, 'provider:physical_network' => Fog::Nullable::String, - 'provider:segmentation_id' => Integer, + 'provider:segmentation_id' => Integer } tests('success') do @@ -25,7 +28,7 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do Fog::Network[:openstack].create_network(attributes).body end tests('#create_network+provider extensions').formats( - {'network' => @network_format} + {'network' => @network_format.merge(@network_format_extensions)} ) do attributes = { :name => 'net_name', @@ -68,6 +71,8 @@ Shindo.tests('Fog::Network[:openstack] | network requests', ['openstack']) do tests('#create_network+provider extensions').raises( Excon::Errors::BadRequest ) do + pending if Fog.mocking? + attributes = { :name => 'net_name', :shared => false, From e56043a2fc75fa82ea30cd7faaedbb19661aae37 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Mon, 11 Mar 2013 21:49:33 +0100 Subject: [PATCH 14/23] [openstack|network] remove extra trailing comma --- tests/openstack/models/network/network_tests.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/openstack/models/network/network_tests.rb b/tests/openstack/models/network/network_tests.rb index 9aa05bafb..4dca50d2a 100644 --- a/tests/openstack/models/network/network_tests.rb +++ b/tests/openstack/models/network/network_tests.rb @@ -21,7 +21,7 @@ Shindo.tests("Fog::Network[:openstack] | network", ['openstack']) do # May rise an exception if the network_type isn't valid: # QuantumError: "Invalid input for operation: provider:physical_network" :provider_network_type => 'gre', - :provider_segmentation_id => 22, + :provider_segmentation_id => 22 ) net.destroy net.provider_network_type == 'gre' From a70615cfe4d12c23c61fb2ea99e24b986ac53dd3 Mon Sep 17 00:00:00 2001 From: Ferran Rodenas Date: Thu, 14 Mar 2013 23:40:26 +0100 Subject: [PATCH 15/23] [openstack|compute] Allow booting a VM with NICs (net_id, port_id, fixed_ip) --- lib/fog/openstack/models/compute/server.rb | 8 +++++++- lib/fog/openstack/requests/compute/create_server.rb | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/fog/openstack/models/compute/server.rb b/lib/fog/openstack/models/compute/server.rb index 9f2433007..a19004e1f 100644 --- a/lib/fog/openstack/models/compute/server.rb +++ b/lib/fog/openstack/models/compute/server.rb @@ -50,6 +50,7 @@ module Fog self.security_groups = attributes.delete(:security_groups) self.min_count = attributes.delete(:min_count) self.max_count = attributes.delete(:max_count) + self.nics = attributes.delete(:nics) self.os_scheduler_hints = attributes.delete(:os_scheduler_hints) super @@ -238,6 +239,10 @@ module Fog @max_count = new_max_count end + def nics=(new_nics) + @nics = new_nics + end + def networks service.networks(:server => self) end @@ -256,7 +261,8 @@ module Fog 'security_groups' => @security_groups, 'min_count' => @min_count, 'max_count' => @max_count, - 'os:scheduler_hints' => @os_scheduler_hints + 'nics' => @nics, + 'os:scheduler_hints' => @os_scheduler_hints, } options['metadata'] = metadata.to_hash unless @metadata.nil? options = options.reject {|key, value| value.nil?} diff --git a/lib/fog/openstack/requests/compute/create_server.rb b/lib/fog/openstack/requests/compute/create_server.rb index 467bbaec9..4e701196d 100644 --- a/lib/fog/openstack/requests/compute/create_server.rb +++ b/lib/fog/openstack/requests/compute/create_server.rb @@ -41,6 +41,17 @@ module Fog end end + if options['nics'] + data['server']['networks'] = + Array(options['nics']).map do |nic| + { + 'uuid' => nic['net_id'], + 'fixed_ip' => nic['v4_fixed_ip'], + 'port' => nic['port_id'] + } + end + end + if options['os:scheduler_hints'] data['os:scheduler_hints'] = options['os:scheduler_hints'] end From 6c36ac14bc4538250d5474ca111c6abc9ebdf131 Mon Sep 17 00:00:00 2001 From: Ferran Rodenas Date: Fri, 15 Mar 2013 11:37:24 +0100 Subject: [PATCH 16/23] [openstack|compute] Use attribute accessor for nics --- lib/fog/openstack/models/compute/server.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/fog/openstack/models/compute/server.rb b/lib/fog/openstack/models/compute/server.rb index a19004e1f..67aa855ec 100644 --- a/lib/fog/openstack/models/compute/server.rb +++ b/lib/fog/openstack/models/compute/server.rb @@ -40,7 +40,7 @@ module Fog attribute :os_ext_sts_vm_state, :aliases => 'OS-EXT-STS:vm_state' attr_reader :password - attr_writer :image_ref, :flavor_ref, :os_scheduler_hints + attr_writer :image_ref, :flavor_ref, :nics, :os_scheduler_hints def initialize(attributes={}) @@ -239,10 +239,6 @@ module Fog @max_count = new_max_count end - def nics=(new_nics) - @nics = new_nics - end - def networks service.networks(:server => self) end From 99e7a09f785f0d880c359e5c2978372133be55f9 Mon Sep 17 00:00:00 2001 From: Mick Pollard Date: Mon, 18 Mar 2013 08:28:31 +1100 Subject: [PATCH 17/23] fix bug where servers.all was ignoring filters due to hash merging in the wrong direction. --- lib/fog/vsphere/models/compute/servers.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/fog/vsphere/models/compute/servers.rb b/lib/fog/vsphere/models/compute/servers.rb index 46672e4b5..727b873f2 100644 --- a/lib/fog/vsphere/models/compute/servers.rb +++ b/lib/fog/vsphere/models/compute/servers.rb @@ -17,13 +17,15 @@ module Fog # 'folder' => '/Datacenters/vm/Jeff/Templates' will be MUCH faster. # than simply listing everything. def all(filters = { }) - load service.list_virtual_machines(filters.merge( - :datacenter => datacenter, - :cluster => cluster, - :network => network, - :resource_pool => resource_pool, - :folder => folder - )) + f = { + :datacenter => datacenter, + :cluster => cluster, + :network => network, + :resource_pool => resource_pool, + :folder => folder + }.merge(filters) + + load service.list_virtual_machines(f) end def get(id, datacenter = nil) @@ -31,9 +33,7 @@ module Fog rescue Fog::Compute::Vsphere::NotFound nil end - end - end end end From 34f49feade45398383efb4fac250e8126d382b45 Mon Sep 17 00:00:00 2001 From: Dominic Cleal Date: Tue, 19 Mar 2013 15:55:48 +0000 Subject: [PATCH 18/23] [libvirt|compute] handle missing tag in libvirt node info Fixes #1652: libvirt provider requires a field that libvirt specifies as optional --- lib/fog/libvirt/requests/compute/get_node_info.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/libvirt/requests/compute/get_node_info.rb b/lib/fog/libvirt/requests/compute/get_node_info.rb index 1d1d037da..9903d7673 100644 --- a/lib/fog/libvirt/requests/compute/get_node_info.rb +++ b/lib/fog/libvirt/requests/compute/get_node_info.rb @@ -14,7 +14,7 @@ module Fog node_hash[:uri] = client.uri xml = client.sys_info rescue nil [:uuid, :manufacturer, :product, :serial].each do |attr| - node_hash[attr] = node_attr(attr, xml) + node_hash[attr] = node_attr(attr, xml) rescue nil end if xml node_hash[:hostname] = client.hostname From 14b09e82d803e8905c25ff5d8c687631b57aa20e Mon Sep 17 00:00:00 2001 From: Kyle Rames Date: Wed, 20 Mar 2013 09:06:35 -0500 Subject: [PATCH 19/23] [core] Updated to make ssh timeout user configurable. --- lib/fog/core/ssh.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/core/ssh.rb b/lib/fog/core/ssh.rb index 4945416fb..ec5d9ed74 100644 --- a/lib/fog/core/ssh.rb +++ b/lib/fog/core/ssh.rb @@ -46,7 +46,7 @@ module Fog raise ArgumentError.new(':key_data, :keys, :password or a loaded ssh-agent is required to initialize SSH') end - options[:timeout] = 30 + options[:timeout] ||= 30 if options[:key_data] || options[:keys] options[:keys_only] = true #Explicitly set these so net-ssh doesn't add the default keys From 987f6abc8377455e3aa44395951839b625ac8b1b Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Wed, 13 Mar 2013 16:56:55 +0100 Subject: [PATCH 20/23] [openstack|glance] Added image service example Download CirrOS 0.3.0 image from launchpad (~6.5MB) to /tmp and upload it to Glance (the OpenStack Image Service). --- .../examples/image/upload-test-image.rb | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lib/fog/openstack/examples/image/upload-test-image.rb diff --git a/lib/fog/openstack/examples/image/upload-test-image.rb b/lib/fog/openstack/examples/image/upload-test-image.rb new file mode 100644 index 000000000..7f7dc1850 --- /dev/null +++ b/lib/fog/openstack/examples/image/upload-test-image.rb @@ -0,0 +1,77 @@ +require 'securerandom' +require 'rubygems/package' +require 'zlib' +require 'fog' + +# +# Download CirrOS 0.3.0 image from launchpad (~6.5MB) to /tmp +# and upload it to Glance (the OpenStack Image Service). +# +# You will need to source OpenStack credentials since the script +# reads the following envionment variables: +# +# OS_PASSWORD +# OS_USERNAME +# OS_AUTH_URL +# OS_TENANT_NAME +# +# Should work with Fog >= 1.9, ruby 1.8.7 and 2.0 +# +image_url = "https://launchpadlibrarian.net/83305869/cirros-0.3.0-x86_64-uec.tar.gz" +image_out = File.open("/tmp/cirros-image-#{SecureRandom.hex}", 'wb') +extract_path = "/tmp/cirros-#{SecureRandom.hex}-dir" +ami = "#{extract_path}/cirros-0.3.0-x86_64-blank.img" +aki = "#{extract_path}/cirros-0.3.0-x86_64-vmlinuz" +ari = "#{extract_path}/cirros-0.3.0-x86_64-initrd" + +FileUtils.mkdir_p extract_path + +# Efficient image write +puts "Downloading Cirros image..." +streamer = lambda do |chunk, remaining_bytes, total_bytes| + image_out.write chunk +end +Excon.get image_url, :response_block => streamer +image_out.close +puts "Image downloaded to #{image_out.path}" + +puts "Extracting image contents to #{extract_path}..." +Gem::Package::TarReader.new(Zlib::GzipReader.open(image_out.path)).each do |entry| + FileUtils.mkdir_p "#{extract_path}/#{File.dirname(entry.full_name)}" + File.open "#{extract_path}/#{entry.full_name}", 'w' do |f| + f.write entry.read + end +end + +image_service = Fog::Image.new({ + :provider => 'OpenStack', + :openstack_api_key => ENV['OS_PASSWORD'], + :openstack_username => ENV["OS_USERNAME"], + :openstack_auth_url => ENV["OS_AUTH_URL"] + "/tokens", + :openstack_tenant => ENV["OS_TENANT_NAME"] +}) + +puts "Uploading AKI..." +aki = image_service.images.create :name => 'cirros-0.3.0-amd64-aki', + :size => File.size(aki), + :disk_format => 'aki', + :container_format => 'aki', + :location => aki + +puts "Uploading ARI..." +ari = image_service.images.create :name => 'cirros-0.3.0-amd64-ari', + :size => File.size(ari), + :disk_format => 'ari', + :container_format => 'ari', + :location => ari + +puts "Uploading AMI..." +image_service.images.create :name => 'cirros-0.3.0-amd64', + :size => File.size(ami), + :disk_format => 'ami', + :container_format => 'ami', + :location => ami, + :properties => { + 'kernel_id' => aki.id, + 'ramdisk_id' => ari.id + } From 09d50c0d33f24a4fe359b6e0996f27d6609692c8 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Wed, 20 Mar 2013 17:50:31 +0100 Subject: [PATCH 21/23] [openstack|network] remove superfluous Router model attributes See #1603 --- lib/fog/openstack/models/network/router.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/fog/openstack/models/network/router.rb b/lib/fog/openstack/models/network/router.rb index 6f4f2bcb5..047320e83 100644 --- a/lib/fog/openstack/models/network/router.rb +++ b/lib/fog/openstack/models/network/router.rb @@ -14,8 +14,6 @@ module Fog identity :id attribute :name - attribute :network_id - attribute :subnet_id attribute :admin_state_up attribute :tenant_id attribute :external_gateway_info From 426037e87d74aaea6194bc3a4a2d64edb9b19fb4 Mon Sep 17 00:00:00 2001 From: Josh Lane & Ines Sombra Date: Wed, 20 Mar 2013 10:24:11 -0700 Subject: [PATCH 22/23] [aws] mock update_server_certificate --- .../requests/iam/update_server_certificate.rb | 27 ++++++++++++++++ .../requests/iam/server_certificate_tests.rb | 32 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lib/fog/aws/requests/iam/update_server_certificate.rb b/lib/fog/aws/requests/iam/update_server_certificate.rb index d7bc6e04e..0b6a9ec2f 100644 --- a/lib/fog/aws/requests/iam/update_server_certificate.rb +++ b/lib/fog/aws/requests/iam/update_server_certificate.rb @@ -32,6 +32,33 @@ module Fog end end + + class Mock + def update_server_certificate(server_certificate_name, options = {}) + new_server_certificate_name = options['NewServerCertificateName'] + if self.data[:server_certificates][new_server_certificate_name] + raise Fog::AWS::IAM::EntityAlreadyExists.new("The Server Certificate with name #{server_certificate_name} already exists.") + end + unless certificate = self.data[:server_certificates].delete(server_certificate_name) + raise Fog::AWS::IAM::NotFound.new("The Server Certificate with name #{server_certificate_name} cannot be found.") + end + + if new_server_certificate_name + certificate['ServerCertificateName'] = new_server_certificate_name + end + + if new_path = options['NewPath'] + certificate['Path'] = new_path + end + + self.data[:server_certificates][certificate['ServerCertificateName']] = certificate + + Excon::Response.new.tap do |response| + response.body = { 'RequestId' => Fog::AWS::Mock.request_id } + response.status = 200 + end + end + end end end end diff --git a/tests/aws/requests/iam/server_certificate_tests.rb b/tests/aws/requests/iam/server_certificate_tests.rb index 6f835863d..aec71b3db 100644 --- a/tests/aws/requests/iam/server_certificate_tests.rb +++ b/tests/aws/requests/iam/server_certificate_tests.rb @@ -13,6 +13,9 @@ Shindo.tests('AWS::IAM | server certificate requests', ['aws']) do 'Certificate' => @certificate_format, 'RequestId' => String } + @update_format = { + 'RequestId' => String + } @get_server_certificate_format = { 'Certificate' => @certificate_format, 'RequestId' => String @@ -64,6 +67,35 @@ Shindo.tests('AWS::IAM | server certificate requests', ['aws']) do end end + tests('#update_server_certificate') do + public_key = AWS::IAM::SERVER_CERT_PUBLIC_KEY + private_key = AWS::IAM::SERVER_CERT_PRIVATE_KEY + key_name = "update-key" + + Fog::AWS::IAM.new.upload_server_certificate(public_key, private_key, key_name) + + tests('duplicate name').raises(Fog::AWS::IAM::EntityAlreadyExists) do + other_key_name = "other-key-name" + Fog::AWS::IAM.new.upload_server_certificate(public_key, private_key, other_key_name) + + Fog::AWS::IAM.new.update_server_certificate(key_name, {'NewServerCertificateName' => other_key_name}) + end + + tests('unknown name').raises(Fog::AWS::IAM::NotFound) do + Fog::AWS::IAM.new.update_server_certificate("unknown-key-name", {'NewServerCertificateName' => "other-keyname"}) + end + + tests('format').formats(@update_format) do + Fog::AWS::IAM.new.update_server_certificate(key_name).body + end + + tests('updates name') do + other_key_name = "successful-update-key-name" + Fog::AWS::IAM.new.update_server_certificate(key_name, {'NewServerCertificateName' => other_key_name}) + returns(true) { Fog::AWS::IAM.new.get_server_certificate(other_key_name).body['Certificate']['ServerCertificateName'] == other_key_name } + end + end + tests('#get_server_certificate').formats(@get_server_certificate_format) do tests('raises NotFound').raises(Fog::AWS::IAM::NotFound) do Fog::AWS::IAM.new.get_server_certificate("#{@key_name}fake") From 7da4fb405fb4a71e51a35aeb022a7f3655fdc8f2 Mon Sep 17 00:00:00 2001 From: Sergio Rubio Date: Thu, 21 Mar 2013 13:42:14 +0100 Subject: [PATCH 23/23] [openstack|network] Fix #connection deprecation replacing it with #service --- lib/fog/openstack/models/network/floating_ip.rb | 4 ++-- lib/fog/openstack/models/network/floating_ips.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fog/openstack/models/network/floating_ip.rb b/lib/fog/openstack/models/network/floating_ip.rb index b38fc512e..40e2600f3 100644 --- a/lib/fog/openstack/models/network/floating_ip.rb +++ b/lib/fog/openstack/models/network/floating_ip.rb @@ -29,7 +29,7 @@ module Fog def create requires :floating_network_id - merge_attributes(connection.create_floating_ip(self.floating_network_id, + merge_attributes(service.create_floating_ip(self.floating_network_id, self.attributes).body['floatingip']) @@ -42,7 +42,7 @@ module Fog def destroy requires :id - connection.delete_floating_ip(self.id) + service.delete_floating_ip(self.id) true end diff --git a/lib/fog/openstack/models/network/floating_ips.rb b/lib/fog/openstack/models/network/floating_ips.rb index a7e081a65..9a827f015 100644 --- a/lib/fog/openstack/models/network/floating_ips.rb +++ b/lib/fog/openstack/models/network/floating_ips.rb @@ -17,7 +17,7 @@ module Fog def all(filters = filters) self.filters = filters - load(connection.list_floating_ips(filters).body['floatingips']) + load(service.list_floating_ips(filters).body['floatingips']) end def get(floating_network_id)