From 22718d615b45fa75c3091ee1ccb38251dcbdb4b0 Mon Sep 17 00:00:00 2001 From: Matt Darby Date: Thu, 11 Dec 2014 12:48:16 -0500 Subject: [PATCH] Rackspace Neutron (Networking) Support --- lib/fog/bin/rackspace.rb | 4 + lib/fog/rackspace.rb | 1 + lib/fog/rackspace/core.rb | 1 + lib/fog/rackspace/docs/networking.md | 315 ------------- lib/fog/rackspace/docs/networking_v2.md | 422 ++++++++++++++++++ .../rackspace/models/networking_v2/network.rb | 36 ++ .../models/networking_v2/networks.rb | 23 + .../rackspace/models/networking_v2/port.rb | 39 ++ .../rackspace/models/networking_v2/ports.rb | 23 + .../rackspace/models/networking_v2/subnet.rb | 38 ++ .../rackspace/models/networking_v2/subnets.rb | 23 + lib/fog/rackspace/networking_v2.rb | 205 +++++++++ .../requests/identity/create_token.rb | 3 + .../requests/networking_v2/create_network.rb | 18 + .../requests/networking_v2/create_port.rb | 18 + .../requests/networking_v2/create_subnet.rb | 18 + .../requests/networking_v2/delete_network.rb | 11 + .../requests/networking_v2/delete_port.rb | 11 + .../requests/networking_v2/delete_subnet.rb | 11 + .../requests/networking_v2/list_networks.rb | 11 + .../requests/networking_v2/list_ports.rb | 11 + .../requests/networking_v2/list_subnets.rb | 11 + .../requests/networking_v2/show_network.rb | 11 + .../requests/networking_v2/show_port.rb | 11 + .../requests/networking_v2/show_subnet.rb | 11 + .../requests/networking_v2/update_network.rb | 18 + .../requests/networking_v2/update_port.rb | 18 + .../requests/networking_v2/update_subnet.rb | 23 + 28 files changed, 1030 insertions(+), 315 deletions(-) delete mode 100644 lib/fog/rackspace/docs/networking.md create mode 100644 lib/fog/rackspace/docs/networking_v2.md create mode 100644 lib/fog/rackspace/models/networking_v2/network.rb create mode 100644 lib/fog/rackspace/models/networking_v2/networks.rb create mode 100644 lib/fog/rackspace/models/networking_v2/port.rb create mode 100644 lib/fog/rackspace/models/networking_v2/ports.rb create mode 100644 lib/fog/rackspace/models/networking_v2/subnet.rb create mode 100644 lib/fog/rackspace/models/networking_v2/subnets.rb create mode 100644 lib/fog/rackspace/networking_v2.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/create_network.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/create_port.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/create_subnet.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/delete_network.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/delete_port.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/delete_subnet.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/list_networks.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/list_ports.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/list_subnets.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/show_network.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/show_port.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/show_subnet.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/update_network.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/update_port.rb create mode 100644 lib/fog/rackspace/requests/networking_v2/update_subnet.rb diff --git a/lib/fog/bin/rackspace.rb b/lib/fog/bin/rackspace.rb index 99fb9f4c0..30352a1c8 100644 --- a/lib/fog/bin/rackspace.rb +++ b/lib/fog/bin/rackspace.rb @@ -28,6 +28,8 @@ class Rackspace < Fog::Bin Fog::Rackspace::Queues when :networking Fog::Rackspace::Networking + when :networking_v2 + Fog::Rackspace::NetworkingV2 else raise ArgumentError, "Unrecognized service: #{key}" end @@ -67,6 +69,8 @@ class Rackspace < Fog::Bin Fog::Rackspace::Queues.new when :networking Fog::Rackspace::Networking.new + when :networking_v2 + Fog::Rackspace::NetworkingV2.new else raise ArgumentError, "Unrecognized service: #{key.inspect}" end diff --git a/lib/fog/rackspace.rb b/lib/fog/rackspace.rb index 600bf721a..bf189e331 100644 --- a/lib/fog/rackspace.rb +++ b/lib/fog/rackspace.rb @@ -12,3 +12,4 @@ require 'fog/rackspace/queues' require 'fog/rackspace/storage' require 'fog/rackspace/networking' require 'fog/rackspace/orchestration' +require 'fog/rackspace/networking_v2' diff --git a/lib/fog/rackspace/core.rb b/lib/fog/rackspace/core.rb index 03bc32160..7a91314e1 100644 --- a/lib/fog/rackspace/core.rb +++ b/lib/fog/rackspace/core.rb @@ -99,6 +99,7 @@ module Fog service(:queues, 'Queues') service(:networking, 'Networking') service(:orchestration, 'Orchestration') + service(:networkingV2, 'NetworkingV2') def self.authenticate(options, connection_options = {}) rackspace_auth_url = options[:rackspace_auth_url] diff --git a/lib/fog/rackspace/docs/networking.md b/lib/fog/rackspace/docs/networking.md deleted file mode 100644 index 2af77d673..000000000 --- a/lib/fog/rackspace/docs/networking.md +++ /dev/null @@ -1,315 +0,0 @@ -#Networking (neutron) - -This document explains how to get started using Networking with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document. - -## Starting irb console - -Start by executing the following command: - - irb - -Once `irb` has launched you need to require the Fog library. - -If using Ruby 1.8.x execute: - - require 'rubygems' - require 'fog' - -If using Ruby 1.9.x execute: - - require 'fog' - -## Create Service - -Next, create a connection to Rackspace's Networking API: - -Using a US-based account: - - service = Fog::Rackspace::Networking.new({ - :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username - :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key - :rackspace_region => :ord, # Defaults to :dfw - }) - -Using a UK-based account: - - service = Fog::Compute.new({ - :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username - :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key - :rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT, - :rackspace_region => :lon, - }) - -To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document. - -By default `Fog::Rackspace::Networking` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints. - -Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Servers can be found by executing the following: - - identity_service = Fog::Identity({ - :provider => 'Rackspace', # Rackspace Fog provider - :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username - :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key - :rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud - }) - - identity_service.service_catalog.display_service_regions :cloudServersOpenStack - -### Optional Connection Parameters - -Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyDescription
:connect_timeoutConnection timeout (default: 60 seconds)
:read_timeoutRead timeout for connection (default: 60 seconds)
:write_timeoutWrite timeout for connection (default: 60 seconds)
:proxyProxy for HTTP and HTTPS connections
:ssl_ca_pathPath to SSL certificate authorities
:ssl_ca_fileSSL certificate authority file
:ssl_verify_peerSSL verify peer (default: true)
- - -## Fog Abstractions - -Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface. - -### Request Layer - -The request abstraction maps directly to the [Networking API](http://docs.rackspace.com/networks/api/v2/cn-gettingstarted/content/ch_overview.html). It provides the most efficient interface to the Rackspace Networking - -To see a list of requests supported by the service: - - service.requests - -This returns: - - [:list_networks, :get_network, :create_network, :delete_network, :list_virtual_interfaces, :create_virtual_interface, :delete_virtual_interface] - -#### Example Request - -To request a list of flavors: - - response = service.list_networks - -This returns in the following `Excon::Response`: - - {"networks"=>[{"cidr"=>"192.168.0.0/24", "id"=>"08df79ae-b714-425c-ba25-91b0a8a78b9e", "label"=>"something"}, {"cidr"=>"192.168.0.0/24", "id"=>"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c", "label"=>"something"}, {"id"=>"00000000-0000-0000-0000-000000000000", "label"=>"public"}, {"id"=>"11111111-1111-1111-1111-111111111111", "label"=>"private"}]}, :headers=>{"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"341", "Date"=>"Thu, 23 Oct 2014 20:53:41 GMT", "x-compute-request-id"=>"req-d34ab53c-45ed-433f-8a9d-b3341896b7e5", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, :status=>200, :remote_ip=>"162.209.116.128", :local_port=>60153, :local_address=>"192.168.1.65"}, @body="{\"networks\": [{\"cidr\": \"192.168.0.0/24\", \"id\": \"08df79ae-b714-425c-ba25-91b0a8a78b9e\", \"label\": \"something\"}, {\"cidr\": \"192.168.0.0/24\", \"id\": \"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c\", \"label\": \"something\"}, {\"id\": \"00000000-0000-0000-0000-000000000000\", \"label\": \"public\"}, {\"id\": \"11111111-1111-1111-1111-111111111111\", \"label\": \"private\"}]}", @headers={"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"341", "Date"=>"Thu, 23 Oct 2014 20:53:41 GMT", "x-compute-request-id"=>"req-d34ab53c-45ed-433f-8a9d-b3341896b7e5", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, @status=200, @remote_ip="162.209.116.128", @local_port=60153, @local_address="192.168.1.65"> - -To view the status of the response: - - response.status - -**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception. - -To view response body: - - response.body - -This will return: - - {"networks"=>[{"cidr"=>"192.168.0.0/24", "id"=>"08df79ae-b714-425c-ba25-91b0a8a78b9e", "label"=>"something"}, {"cidr"=>"192.168.0.0/24", "id"=>"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c", "label"=>"something"}, {"id"=>"00000000-0000-0000-0000-000000000000", "label"=>"public"}, {"id"=>"11111111-1111-1111-1111-111111111111", "label"=>"private"}]} - -To learn more about Networking request methods refer to [rdoc](http://www.rubydoc.info/gems/fog/Fog/Rackspace/Networking/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon). - -### Model Layer - -Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors. - -Here is a summary of common model methods: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MethodDescription
create - Accepts hash of attributes and creates object.
- Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object. -
saveSaves object.
- Note: not all objects support updating object.
persisted?Returns true if the object has been persisted.
destroy - Destroys object.
- Note: this is a non-blocking call and object deletion might not be instantaneous. -
reloadUpdates object with latest state from service.
ready?Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.
attributesReturns a hash containing the list of model attributes and values.
identity - Returns the identity of the object.
- Note: This might not always be equal to object.id. -
wait_forThis method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.
- -The remainder of this document details the model abstraction. - -## List Networks - -To retrieve a list of available networks: - - service.networks - -This returns a collection of `Fog::Rackspace::Networking::Network` models: - - , - , - , - - ] - > - -## Create Network - -Create a network: - - service.networks.create(label: "new_network", cidr: "192.168.0.0/24") - - -## Get Network - -To retrieve individual network: - - service.networks.get "8a3a9f96-b997-46fd-b7a8-a9e740796ffd" - -This returns an `Fog::Rackspace::Networking::Network` instance: - - - -## Delete Network - -To delete a network: - - network.destroy - -**Note**: The network is not immediately destroyed, but it does occur shortly there after. - -## List Virtual Interfaces - -To retrieve a list of available virtual interfaces: - - service.virtual_interfaces.all(server: ) - -This returns a collection of `Fog::Rackspace::Networking::VirtualInterface` models: - - "11111111-1111-1111-1111-111111111111", "network_label"=>"private", "address"=>"10.176.12.249"}] - >, - "08df79ae-b714-425c-ba25-91b0a8a78b9e", "network_label"=>"new_network", "address"=>"192.168.0.1"}] - > - ] - > - -## Create Virtual Interface - -Create a virtual interface: - - service.virtual_interfaces.create(network: , server: ) - -## Delete Virtual Interface - -To delete a virtual interface: - - vis = service.virtual_interfaces.all(server: ) - vis.first.destroy - -**Note**: The virtual interface is not immediately destroyed, but it does occur shortly there after. - -## Examples - -Example code using Networking can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples). - -## Additional Resources - -* [fog.io](http://fog.io/) -* [Fog rdoc](http://rubydoc.info/gems/fog/) -* [Fog Github repo](https://github.com/fog/fog) -* [Fog Github Issues](https://github.com/fog/fog/issues) -* [Excon Github repo](https://github.com/geemus/excon) -* [Rackspace Networking API](http://docs.rackspace.com/networking/api/v2/cs-devguide/content/ch_preface.html) - -## Support and Feedback - -Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues). - -For general feedback and support requests, send an email to: . - diff --git a/lib/fog/rackspace/docs/networking_v2.md b/lib/fog/rackspace/docs/networking_v2.md new file mode 100644 index 000000000..8723548b1 --- /dev/null +++ b/lib/fog/rackspace/docs/networking_v2.md @@ -0,0 +1,422 @@ +#NetworkingV2 (neutron) + +This document explains how to get started using NetworkingV2 with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document. + +## Starting irb console + +Start by executing the following command: + + irb + +Once `irb` has launched you need to require the Fog library. + +If using Ruby 1.8.x execute: + + require 'rubygems' + require 'fog' + +If using Ruby 1.9.x execute: + + require 'fog' + +## Create Service + +Next, create a connection to Rackspace's NetworkingV2 API: + +Using a US-based account: + + service = Fog::Rackspace::NetworkingV2.new({ + :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username + :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key + :rackspace_region => :ord, # Defaults to :dfw + }) + +Using a UK-based account: + + service = Fog::Compute.new({ + :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username + :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key + :rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT, + :rackspace_region => :lon, + }) + +To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document. + +By default `Fog::Rackspace::NetworkingV2` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints. + +Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Servers can be found by executing the following: + + identity_service = Fog::Identity({ + :provider => 'Rackspace', # Rackspace Fog provider + :rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username + :rackspace_api_key => RACKSPACE_API, # Your Rackspace API key + :rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud + }) + + identity_service.service_catalog.display_service_regions :cloudServersOpenStack + +### Optional Connection Parameters + +Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescription
:connect_timeoutConnection timeout (default: 60 seconds)
:read_timeoutRead timeout for connection (default: 60 seconds)
:write_timeoutWrite timeout for connection (default: 60 seconds)
:proxyProxy for HTTP and HTTPS connections
:ssl_ca_pathPath to SSL certificate authorities
:ssl_ca_fileSSL certificate authority file
:ssl_verify_peerSSL verify peer (default: true)
+ + +## Fog Abstractions + +Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface. + +### Request Layer + +The request abstraction maps directly to the [NetworkingV2 API](http://docs.rackspace.com/networks/api/v2/cn-devguide/content/ch_overview.html). It provides the most efficient interface to the Rackspace NetworkingV2 + +To see a list of requests supported by the service: + + service.requests + +This returns: + + [:list_networks, :create_network, :show_network, :update_network, :delete_network, :list_subnets, :create_subnet, :show_subnet, :update_subnet, :delete_subnet, :list_ports, :create_port, :show_port, :update_port, :delete_port] + +#### Example Request + +To request a list of flavors: + + response = service.list_networks + +This returns in the following `Excon::Response`: + + #{"networks"=>[{"status"=>"ACTIVE", "subnets"=>["79a2a078-84bd-4ffd-8e68-67f7854bb772"], "name"=>"Testing", "admin_state_up"=>true, "tenant_id"=>"000000", "shared"=>false, "id"=>"eff4da21-e006-4468-b9ce-798eb2fed3e8"}]}, :headers=>{"Content-Type"=>"application/json; charset=UTF-8", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"218", "Date"=>"Wed, 17 Dec 2014 19:37:49 GMT", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, :status=>200, :reason_phrase=>"OK", :remote_ip=>"69.20.65.143", :local_port=>63382, :local_address=>"192.168.1.80"}, @body="{\"networks\": [{\"status\": \"ACTIVE\", \"subnets\": [\"79a2a078-84bd-4ffd-8e68-67f7854bb772\"], \"name\": \"Testing\", \"admin_state_up\": true, \"tenant_id\": \"000000\", \"shared\": false, \"id\": \"eff4da21-e006-4468-b9ce-798eb2fed3e8\"}]}", @headers={"Content-Type"=>"application/json; charset=UTF-8", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"218", "Date"=>"Wed, 17 Dec 2014 19:37:49 GMT", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, @status=200, @remote_ip="69.20.0.0", @local_port=63382, @local_address="192.168.1.80"> + +To view the status of the response: + + response.status + +**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception. + +To view response body: + + response.body + +This will return: + + {"networks"=>[{"status"=>"ACTIVE", "subnets"=>["79a2a078-84bd-4ffd-8e68-67f7854bb772"], "name"=>"Testing", "admin_state_up"=>true, "tenant_id"=>"000000", "shared"=>false, "id"=>"eff4da21-e006-4468-b9ce-798eb2fed3e8"}]} + +To learn more about NetworkingV2 request methods refer to [rdoc](http://www.rubydoc.info/gems/fog/Fog/Rackspace/NetworkingV2/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon). + +### Model Layer + +Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors. + +Here is a summary of common model methods: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodDescription
create + Accepts hash of attributes and creates object.
+ Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object. +
saveSaves object.
+ Note: not all objects support updating object.
persisted?Returns true if the object has been persisted.
destroy + Destroys object.
+ Note: this is a non-blocking call and object deletion might not be instantaneous. +
reloadUpdates object with latest state from service.
ready?Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.
attributesReturns a hash containing the list of model attributes and values.
identity + Returns the identity of the object.
+ Note: This might not always be equal to object.id. +
wait_forThis method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.
+ +The remainder of this document details the model abstraction. + +## List Networks + +To retrieve a list of available networks: + + service.networks + +This returns a collection of `Fog::Rackspace::NetworkingV2::Network` models: + + + ] + > + +## Create Network + +Create a network: + + service.networks.create(label: "new_network", cidr: "192.168.0.0/24") + +## Get Network + +To retrieve individual network: + + service.networks.get "eff4da21-e006-4468-b9ce-798eb2fed3e8" + +This returns an `Fog::Rackspace::NetworkingV2::Network` instance: + + + +## Delete Network + +To delete a network: + + network.destroy + +**Note**: The network is not immediately destroyed, but it does occur shortly there after. + + +## List Subnets + +To retrieve a list of available subnets: + + service.subnets + +This returns a collection of `Fog::Rackspace::NetworkingV2::Subnet` models: + + "192.168.3.1", "end"=>"192.168.3.254"}], + host_routes=[], + ip_version=4, + gateway_ip=nil, + cidr="192.168.3.0/24" + > + ] + > + +## Create Subnet + +Create a subnet: + + subnet = service.subnets.new({ + :name => "ANewsubnet", + :cidr => "192.168.101.1/24", + :network_id => "79a2a078-84bd-4ffd-8e68-67f7854bb772", + :ip_version => "4" + }).save + +## Get Subnet + +To retrieve individual subnet: + + service.subnets.get "79a2a078-84bd-4ffd-8e68-67f7854bb772" + +This returns an `Fog::Rackspace::NetworkingV2::Subnet` instance: + + "192.168.3.1", "end"=>"192.168.3.254"}], + host_routes=[], + ip_version=4, + gateway_ip=nil, + cidr="192.168.3.0/24" + > + +## Delete Subnet + +To delete a subnet: + + subnet.destroy + +**Note**: The subnet is not immediately destroyed, but it does occur shortly there after. + + +## List Ports + +To retrieve a list of available ports: + + service.ports + +This returns a collection of `Fog::Rackspace::NetworkingV2::Port` models: + + "192.168.3.1", "end"=>"192.168.3.254"}], + host_routes=[], + ip_version=4, + gateway_ip=nil, + cidr="192.168.3.0/24" + > + ] + > + +## Create Port + +Create a port: + + s.ports.new({name: "something", network_id: network.id}).save + + "79a2a078-84bd-4ffd-8e68-67f7854bb772", "ip_address"=>"192.168.3.1"}], + mac_address="BC:76:4E:20:CB:0D", + name="something", + network_id="eff4da21-e006-4468-b9ce-798eb2fed3e8", + security_groups=[], + status="ACTIVE", + tenant_id="000000" + > + ] + > + +## Get Port + +To retrieve individual port: + + service.ports.get "f90c5970-1bce-4403-82ee-7713854de7c7" + +This returns an `Fog::Rackspace::NetworkingV2::Port` instance: + + "79a2a078-84bd-4ffd-8e68-67f7854bb772", "ip_address"=>"192.168.3.1"}], + mac_address="BC:76:4E:20:CB:0D", + name="something", + network_id="eff4da21-e006-4468-b9ce-798eb2fed3e8", + security_groups=[], + status="ACTIVE", + tenant_id="000000" + > + +## Delete Port + +To delete a port: + + port.destroy + +**Note**: The port is not immediately destroyed, but it does occur shortly there after. + + + + +## Examples + +Example code using Networking can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples). + +## Additional Resources + +* [fog.io](http://fog.io/) +* [Fog rdoc](http://rubydoc.info/gems/fog/) +* [Fog Github repo](https://github.com/fog/fog) +* [Fog Github Issues](https://github.com/fog/fog/issues) +* [Excon Github repo](https://github.com/geemus/excon) +* [Rackspace Networking API](http://docs.rackspace.com/networking/api/v2/cs-devguide/content/ch_preface.html) + +## Support and Feedback + +Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues). + +For general feedback and support requests, send an email to: . diff --git a/lib/fog/rackspace/models/networking_v2/network.rb b/lib/fog/rackspace/models/networking_v2/network.rb new file mode 100644 index 000000000..fe4114b74 --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/network.rb @@ -0,0 +1,36 @@ +module Fog + module Rackspace + class NetworkingV2 + class Network < Fog::Model + + identity :id + + attribute :admin_state_up + attribute :label + attribute :name + attribute :shared + attribute :status + attribute :subnets + attribute :tenant_id + + def save + data = unless self.id.nil? + service.update_network(self) + else + service.create_network(self) + end + + merge_attributes(data.body['network']) + true + end + + def destroy + requires :identity + + service.delete_network(identity) + true + end + end + end + end +end diff --git a/lib/fog/rackspace/models/networking_v2/networks.rb b/lib/fog/rackspace/models/networking_v2/networks.rb new file mode 100644 index 000000000..ff4c2e65c --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/networks.rb @@ -0,0 +1,23 @@ +require 'fog/rackspace/models/networking_v2/network' + +module Fog + module Rackspace + class NetworkingV2 + class Networks < Fog::Collection + model Fog::Rackspace::NetworkingV2::Network + + def all + data = service.list_networks.body['networks'] + load(data) + end + + def get(id) + data = service.show_network(id).body['network'] + new(data) + rescue Fog::Rackspace::NetworkingV2::NotFound + nil + end + end + end + end +end diff --git a/lib/fog/rackspace/models/networking_v2/port.rb b/lib/fog/rackspace/models/networking_v2/port.rb new file mode 100644 index 000000000..72dbc8f64 --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/port.rb @@ -0,0 +1,39 @@ +module Fog + module Rackspace + class NetworkingV2 + class Port < Fog::Model + + identity :id + + attribute :admin_state_up + attribute :device_id + attribute :device_owner + attribute :fixed_ips + attribute :mac_address + attribute :name + attribute :network_id + attribute :security_groups + attribute :status + attribute :tenant_id + + def save + data = unless self.id.nil? + service.update_port(self) + else + service.create_port(self) + end + + merge_attributes(data.body['port']) + true + end + + def destroy + requires :identity + + service.delete_port(identity) + true + end + end + end + end +end diff --git a/lib/fog/rackspace/models/networking_v2/ports.rb b/lib/fog/rackspace/models/networking_v2/ports.rb new file mode 100644 index 000000000..1650e0a2f --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/ports.rb @@ -0,0 +1,23 @@ +require 'fog/rackspace/models/networking_v2/port' + +module Fog + module Rackspace + class NetworkingV2 + class Ports < Fog::Collection + model Fog::Rackspace::NetworkingV2::Port + + def all + data = service.list_ports.body['ports'] + load(data) + end + + def get(id) + data = service.show_port(id).body['port'] + new(data) + rescue Fog::Rackspace::NetworkingV2::NotFound + nil + end + end + end + end +end diff --git a/lib/fog/rackspace/models/networking_v2/subnet.rb b/lib/fog/rackspace/models/networking_v2/subnet.rb new file mode 100644 index 000000000..a4fe06e82 --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/subnet.rb @@ -0,0 +1,38 @@ +module Fog + module Rackspace + class NetworkingV2 + class Subnet < Fog::Model + + identity :id + + attribute :name + attribute :enable_dhcp + attribute :network_id + attribute :tenant_id + attribute :dns_nameservers + attribute :allocation_pools + attribute :host_routes + attribute :ip_version + attribute :gateway_ip + attribute :cidr + + def save + data = unless self.id.nil? + service.update_subnet(self) + else + service.create_subnet(self) + end + + merge_attributes(data.body['subnet']) + true + end + + def destroy + requires :identity + service.delete_subnet(identity) + true + end + end + end + end +end diff --git a/lib/fog/rackspace/models/networking_v2/subnets.rb b/lib/fog/rackspace/models/networking_v2/subnets.rb new file mode 100644 index 000000000..141ade3c6 --- /dev/null +++ b/lib/fog/rackspace/models/networking_v2/subnets.rb @@ -0,0 +1,23 @@ +require 'fog/rackspace/models/networking_v2/subnet' + +module Fog + module Rackspace + class NetworkingV2 + class Subnets < Fog::Collection + model Fog::Rackspace::NetworkingV2::Subnet + + def all + data = service.list_subnets.body['subnets'] + load(data) + end + + def get(id) + data = service.show_subnet(id).body['subnet'] + new(data) + rescue Fog::Rackspace::NetworkingV2::NotFound + nil + end + end + end + end +end diff --git a/lib/fog/rackspace/networking_v2.rb b/lib/fog/rackspace/networking_v2.rb new file mode 100644 index 000000000..b80c0f31e --- /dev/null +++ b/lib/fog/rackspace/networking_v2.rb @@ -0,0 +1,205 @@ +require 'fog/rackspace/core' + +module Fog + module Rackspace + class NetworkingV2 < Fog::Service + include Fog::Rackspace::Errors + + class ServiceError < Fog::Rackspace::Errors::ServiceError; end + class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end + class BadRequest < Fog::Rackspace::Errors::BadRequest; end + + NETWORKS_DFW_URL = "https://dfw.networks.api.rackspacecloud.com/v2.0" + NETWORKS_LON_URL = "https://lon.networks.api.rackspacecloud.com/v2.0" + NETWORKS_IAD_URL = "https://iad.networks.api.rackspacecloud.com/v2.0" + NETWORKS_ORD_URL = "https://ord.networks.api.rackspacecloud.com/v2.0" + + class InvalidStateException < ::RuntimeError + attr_reader :desired_state + attr_reader :current_state + + def initialize(desired_state, current_state) + @desired_state = desired_state + @current_state = current_state + end + end + + class InvalidServerStateException < InvalidStateException + def to_s + "Server should have transitioned to '#{desired_state}' not '#{current_state}'" + end + end + + class InvalidImageStateException < InvalidStateException + def to_s + "Image should have transitioned to '#{desired_state}' not '#{current_state}'" + end + end + + requires :rackspace_username, :rackspace_api_key + recognizes :rackspace_endpoint + recognizes :rackspace_auth_url + recognizes :rackspace_auth_token + recognizes :rackspace_region + recognizes :rackspace_networking_v2_url + + model_path 'fog/rackspace/models/networking_v2' + + model :network + collection :networks + + model :subnet + collection :subnets + + model :port + collection :ports + + request_path 'fog/rackspace/requests/networking_v2' + request :list_networks + request :create_network + request :show_network + request :update_network + request :delete_network + + request :list_subnets + request :create_subnet + request :show_subnet + request :update_subnet + request :delete_subnet + + request :list_ports + request :create_port + request :show_port + request :update_port + request :delete_port + + class Mock < Fog::Rackspace::Service + include Fog::Rackspace::MockData + + def initialize(options) + @rackspace_api_key = options[:rackspace_api_key] + end + + def request(params) + Fog::Mock.not_implemented + end + + def response(params={}) + body = params[:body] || {} + status = params[:status] || 200 + headers = params[:headers] || {} + + response = Excon::Response.new(:body => body, :headers => headers, :status => status) + if params.key?(:expects) && ![*params[:expects]].include?(response.status) + raise(Excon::Errors.status_error(params, response)) + else response + end + end + end + + class Real < Fog::Rackspace::Service + def initialize(options = {}) + @rackspace_api_key = options[:rackspace_api_key] + @rackspace_username = options[:rackspace_username] + @rackspace_auth_url = options[:rackspace_auth_url] + setup_custom_endpoint(options) + @rackspace_must_reauthenticate = false + @connection_options = options[:connection_options] || {} + + authenticate + + deprecation_warnings(options) + + @persistent = options[:persistent] || false + @connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options) + end + + def request(params, parse_json = true) + super + rescue Excon::Errors::NotFound => error + raise NotFound.slurp(error, self) + rescue Excon::Errors::BadRequest => error + raise BadRequest.slurp(error, self) + rescue Excon::Errors::InternalServerError => error + raise InternalServerError.slurp(error, self) + rescue Excon::Errors::HTTPStatusError => error + raise ServiceError.slurp(error, self) + end + + def authenticate(options={}) + super({ + :rackspace_api_key => @rackspace_api_key, + :rackspace_username => @rackspace_username, + :rackspace_auth_url => @rackspace_auth_url, + :connection_options => @connection_options + }) + end + + def service_name + :cloudNetworks + end + + def request_id_header + "x-networks-request-id" + end + + def region + @rackspace_region + end + + def endpoint_uri(service_endpoint_url=nil) + @uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_networking_v2_url) + end + + private + + def setup_custom_endpoint(options) + @rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_networking_v2_url] || options[:rackspace_endpoint]) + + if v2_authentication? + case @rackspace_endpoint + when NETWORKS_DFW_URL + @rackspace_endpoint = nil + @rackspace_region = :dfw + when NETWORKS_ORD_URL + @rackspace_endpoint = nil + @rackspace_region = :ord + when NETWORKS_LON_URL + @rackspace_endpoint = nil + @rackspace_region = :lon + else + # we are actually using a custom endpoint + @rackspace_region = options[:rackspace_region] + end + else + #if we are using auth1 and the endpoint is not set, default to NETWORKS_DFW_URL for historical reasons + @rackspace_endpoint ||= NETWORKS_DFW_URL + end + end + + def deprecation_warnings(options) + Fog::Logger.deprecation("The :rackspace_endpoint option is deprecated. Please use :rackspace_networking_v2_url for custom endpoints") if options[:rackspace_endpoint] + + if [NETWORKS_DFW_URL, NETWORKS_ORD_URL, NETWORKS_LON_URL].include?(@rackspace_endpoint) && v2_authentication? + regions = @identity_service.service_catalog.display_service_regions(service_name) + Fog::Logger.deprecation("Please specify region using :rackspace_region rather than :rackspace_endpoint. Valid regions for :rackspace_region are #{regions}.") + end + end + + def append_tenant_v1(credentials) + account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1] + + endpoint = @rackspace_endpoint || credentials['X-Server-Management-Url'] || NETWORKS_DFW_URL + @uri = URI.parse(endpoint) + @uri.path = "#{@uri.path}/#{account_id}" + end + + def authenticate_v1(options) + credentials = Fog::Rackspace.authenticate(options, @connection_options) + append_tenant_v1 credentials + @auth_token = credentials['X-Auth-Token'] + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/identity/create_token.rb b/lib/fog/rackspace/requests/identity/create_token.rb index 607d05699..c1eec7342 100644 --- a/lib/fog/rackspace/requests/identity/create_token.rb +++ b/lib/fog/rackspace/requests/identity/create_token.rb @@ -118,6 +118,9 @@ module Fog service_catalog_entry("cloudOrchestration", "orchestration", compute_tenant, :rackspace_api_name => 'orchestration', :rackspace_api_version => '1'), + service_catalog_entry("cloudNetworks", "network", compute_tenant, + :rackspace_api_name => 'networks', :rackspace_api_version => '2.0'), + service_catalog_entry("cloudQueues", "rax:queues", compute_tenant, :internal_url_snet => true, :rackspace_api_name => 'queues', :rackspace_api_version => '1'), diff --git a/lib/fog/rackspace/requests/networking_v2/create_network.rb b/lib/fog/rackspace/requests/networking_v2/create_network.rb new file mode 100644 index 000000000..147d89f9c --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/create_network.rb @@ -0,0 +1,18 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def create_network(network) + data = {:network => network.attributes} + + request( + :method => 'POST', + :body => Fog::JSON.encode(data), + :path => "networks", + :expects => 201 + ) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/create_port.rb b/lib/fog/rackspace/requests/networking_v2/create_port.rb new file mode 100644 index 000000000..048f83250 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/create_port.rb @@ -0,0 +1,18 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def create_port(port) + data = {:port => port.attributes} + + request( + :method => 'POST', + :body => Fog::JSON.encode(data), + :path => "ports", + :expects => 201 + ) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/create_subnet.rb b/lib/fog/rackspace/requests/networking_v2/create_subnet.rb new file mode 100644 index 000000000..170c0d8ba --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/create_subnet.rb @@ -0,0 +1,18 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def create_subnet(subnet) + data = {:subnet => subnet.attributes} + + request( + :method => 'POST', + :body => Fog::JSON.encode(data), + :path => "subnets", + :expects => 201 + ) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/delete_network.rb b/lib/fog/rackspace/requests/networking_v2/delete_network.rb new file mode 100644 index 000000000..235a2d076 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/delete_network.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def delete_network(id) + request(:method => 'DELETE', :path => "networks/#{id}", :expects => 204) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/delete_port.rb b/lib/fog/rackspace/requests/networking_v2/delete_port.rb new file mode 100644 index 000000000..016e5216e --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/delete_port.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def delete_port(id) + request(:method => 'DELETE', :path => "ports/#{id}", :expects => 204) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/delete_subnet.rb b/lib/fog/rackspace/requests/networking_v2/delete_subnet.rb new file mode 100644 index 000000000..13fe5f3d0 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/delete_subnet.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def delete_subnet(id) + request(:method => 'DELETE', :path => "subnets/#{id}", :expects => 204) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/list_networks.rb b/lib/fog/rackspace/requests/networking_v2/list_networks.rb new file mode 100644 index 000000000..c55166314 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/list_networks.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def list_networks + request(:method => 'GET', :path => 'networks', :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/list_ports.rb b/lib/fog/rackspace/requests/networking_v2/list_ports.rb new file mode 100644 index 000000000..0008a0288 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/list_ports.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def list_ports + request(:method => 'GET', :path => 'ports', :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/list_subnets.rb b/lib/fog/rackspace/requests/networking_v2/list_subnets.rb new file mode 100644 index 000000000..047c48afd --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/list_subnets.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def list_subnets + request(:method => 'GET', :path => 'subnets', :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/show_network.rb b/lib/fog/rackspace/requests/networking_v2/show_network.rb new file mode 100644 index 000000000..708f24657 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/show_network.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def show_network(id) + request(:method => 'GET', :path => "networks/#{id}", :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/show_port.rb b/lib/fog/rackspace/requests/networking_v2/show_port.rb new file mode 100644 index 000000000..96fa4edcf --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/show_port.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def show_port(id) + request(:method => 'GET', :path => "ports/#{id}", :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/show_subnet.rb b/lib/fog/rackspace/requests/networking_v2/show_subnet.rb new file mode 100644 index 000000000..2ccec9c34 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/show_subnet.rb @@ -0,0 +1,11 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def show_subnet(id) + request(:method => 'GET', :path => "subnets/#{id}", :expects => 200) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/update_network.rb b/lib/fog/rackspace/requests/networking_v2/update_network.rb new file mode 100644 index 000000000..9dc578c77 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/update_network.rb @@ -0,0 +1,18 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def update_network(network) + data = {:network => {:name => network.name}} + + request( + :method => 'PUT', + :body => Fog::JSON.encode(data), + :path => "networks/#{network.id}", + :expects => 200 + ) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/update_port.rb b/lib/fog/rackspace/requests/networking_v2/update_port.rb new file mode 100644 index 000000000..3c4a8a3b8 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/update_port.rb @@ -0,0 +1,18 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def update_port(port) + data = {:port => {:name => port.name}} + + request( + :method => 'PUT', + :body => Fog::JSON.encode(data), + :path => "ports/#{port.id}", + :expects => 200 + ) + end + end + end + end +end diff --git a/lib/fog/rackspace/requests/networking_v2/update_subnet.rb b/lib/fog/rackspace/requests/networking_v2/update_subnet.rb new file mode 100644 index 000000000..38fd4d085 --- /dev/null +++ b/lib/fog/rackspace/requests/networking_v2/update_subnet.rb @@ -0,0 +1,23 @@ +module Fog + module Rackspace + class NetworkingV2 + class Real + def update_subnet(subnet) + data = { + :subnet => { + :name => subnet.name, + :gateway_ip => subnet.gateway_ip + } + } + + request( + :method => 'PUT', + :body => Fog::JSON.encode(data), + :path => "subnets/#{subnet.id}", + :expects => 200 + ) + end + end + end + end +end