diff --git a/lib/fog/openstack/models/network/security_group.rb b/lib/fog/openstack/models/network/security_group.rb new file mode 100644 index 000000000..a36bf977e --- /dev/null +++ b/lib/fog/openstack/models/network/security_group.rb @@ -0,0 +1,32 @@ +require 'fog/core/model' + +module Fog + module Network + class OpenStack + class SecurityGroup < Fog::Model + identity :id + + attribute :name + attribute :description + attribute :security_group_rules + attribute :tenant_id + + def destroy + requires :id + service.delete_security_group(id) + true + end + + def security_group_rules + Fog::Network::OpenStack::SecurityGroupRules.new(:service => service).load(attributes[:security_group_rules]) + end + + def save + raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? + merge_attributes(service.create_security_group(attributes).body['security_group']) + true + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_group_rule.rb b/lib/fog/openstack/models/network/security_group_rule.rb new file mode 100644 index 000000000..f59d17735 --- /dev/null +++ b/lib/fog/openstack/models/network/security_group_rule.rb @@ -0,0 +1,33 @@ +require 'fog/core/model' + +module Fog + module Network + class OpenStack + class SecurityGroupRule < Fog::Model + identity :id + + attribute :security_group_id + attribute :direction + attribute :protocol + attribute :port_range_min + attribute :port_range_max + attribute :remote_ip_prefix + attribute :ethertype + attribute :remote_group_id + attribute :tenant_id + + def destroy + requires :id + service.delete_security_group_rule(id) + true + end + + def save + raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted? + merge_attributes(service.create_security_group_rule(security_group_id, direction, attributes).body['security_group_rule']) + true + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_group_rules.rb b/lib/fog/openstack/models/network/security_group_rules.rb new file mode 100644 index 000000000..55336363f --- /dev/null +++ b/lib/fog/openstack/models/network/security_group_rules.rb @@ -0,0 +1,33 @@ +require 'fog/core/collection' +require 'fog/openstack/models/network/security_group_rule' + +module Fog + module Network + class OpenStack + class SecurityGroupRules < Fog::Collection + + attribute :filters + + model Fog::Network::OpenStack::SecurityGroupRule + + def initialize(attributes) + self.filters ||= {} + super + end + + def all(filters = filters) + self.filters = filters + load(service.list_security_group_rules(filters).body['security_group_rules']) + end + + def get(sec_group_rule_id) + if sec_group_rule = service.get_security_group_rule(sec_group_rule_id).body['security_group_rule'] + new(sec_group_rule) + end + rescue Fog::Network::OpenStack::NotFound + nil + end + end + end + end +end diff --git a/lib/fog/openstack/models/network/security_groups.rb b/lib/fog/openstack/models/network/security_groups.rb new file mode 100644 index 000000000..7a96ff599 --- /dev/null +++ b/lib/fog/openstack/models/network/security_groups.rb @@ -0,0 +1,34 @@ +require 'fog/core/collection' +require 'fog/openstack/models/network/security_group' + +module Fog + module Network + class OpenStack + class SecurityGroups < Fog::Collection + + attribute :filters + + model Fog::Network::OpenStack::SecurityGroup + + def initialize(attributes) + self.filters ||= {} + super + end + + def all(filters = filters) + self.filters = filters + load(service.list_security_groups(filters).body['security_groups']) + end + + def get(security_group_id) + if security_group = service.get_security_group(security_group_id).body['security_group'] + new(security_group) + 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 1cd6f92f7..6799e4868 100644 --- a/lib/fog/openstack/network.rb +++ b/lib/fog/openstack/network.rb @@ -32,6 +32,10 @@ module Fog collection :lb_health_monitors model :lb_vip collection :lb_vips + model :security_group + collection :security_groups + model :security_group_rule + collection :security_group_rules ## REQUESTS # @@ -106,6 +110,18 @@ module Fog request :get_lb_vip request :update_lb_vip + # Security Group + request :create_security_group + request :delete_security_group + request :get_security_group + request :list_security_groups + + # Security Group Rules + request :create_security_group_rule + request :delete_security_group_rule + request :get_security_group_rule + request :list_security_group_rules + # Tenant request :set_tenant diff --git a/lib/fog/openstack/requests/network/create_security_group.rb b/lib/fog/openstack/requests/network/create_security_group.rb new file mode 100644 index 000000000..39c093231 --- /dev/null +++ b/lib/fog/openstack/requests/network/create_security_group.rb @@ -0,0 +1,94 @@ +module Fog + module Network + class OpenStack + class Real + # Create a new security group + # + # ==== Parameters + # * options<~Hash>: + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - TenantId different than the current user, that should own the security group. Only allowed if user has 'admin' role. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_groups'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def create_security_group(options = {}) + data = {"security_group" => {}} + desired_options = [:name, :description, :tenant_id] + selected_options = desired_options.select{|o| options[o]} + selected_options.each { |key| data["security_group"][key] = options[key] } + + request( + :body => Fog::JSON.encode(data), + :expects => 201, + :method => "POST", + :path => "security-groups" + ) + end + end + + class Mock + def create_security_group(options = {}) + # Spaces are NOT removed from name and description, as in case of compute sec groups + tenant_id = Fog::Mock.random_numbers(14).to_s + sec_group_id = Fog::UUID.uuid + + response = Excon::Response.new + response.status = 201 + # by default every security group will come setup with an egress rule to "allow all out" + data = { + "security_group_rules" => [ + { "remote_group_id" => nil, + "direction" => "egress", + "remote_ip_prefix" => nil, + "protocol" => nil, + "ethertype" => "IPv4", + "tenant_id" => tenant_id, + "port_range_max" => nil, + "port_range_min" => nil, + "id" => Fog::UUID.uuid, + "security_group_id" => sec_group_id + }, + { "remote_group_id" => nil, + "direction" => "egress", + "remote_ip_prefix" => nil, + "protocol" => nil, + "ethertype" => "IPv6", + "tenant_id" => tenant_id, + "port_range_max" => nil, + "port_range_min" => nil, + "id" => Fog::UUID.uuid, + "security_group_id" => sec_group_id + } + ], + "id" => sec_group_id, + "tenant_id" => tenant_id, + "name" => options[:name] || "", + "description" => options[:description] || "" + } + + self.data[:security_groups][data["id"]] = data + response.body = {"security_group" => data} + response + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/create_security_group_rule.rb b/lib/fog/openstack/requests/network/create_security_group_rule.rb new file mode 100644 index 000000000..9aee83a93 --- /dev/null +++ b/lib/fog/openstack/requests/network/create_security_group_rule.rb @@ -0,0 +1,79 @@ +module Fog + module Network + class OpenStack + class Real + # Create a new security group rule + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * options<~Hash>: + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - TenantId different than the current user, that should own the security group. Only allowed if user has 'admin' role. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rule'<~Hash>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~String> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~String> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the source security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def create_security_group_rule(security_group_id, direction, options = {}) + data = {"security_group_rule" => {"security_group_id" => security_group_id, "direction" => direction}} + desired_options = [ + :port_range_min, + :port_range_max, + :protocol, + :ethertype, + :remote_group_id, + :remote_ip_prefix, + :tenant_id + ] + selected_options = desired_options.select{ |o| options[o] } + selected_options.each { |key| data["security_group_rule"][key] = options[key] } + + request( + :body => Fog::JSON.encode(data), + :expects => 201, + :method => "POST", + :path => "security-group-rules" + ) + end + end + + class Mock + def create_security_group_rule(security_group_id, direction, options = {}) + response = Excon::Response.new + data = { + "id" => Fog::UUID.uuid, + "remote_group_id" => options[:remote_group_id], + "direction" => direction, + "remote_ip_prefix" => options[:remote_ip_prefix], + "protocol" => options[:protocol], + "ethertype" => options[:ethertype] || "IPv4", + "tenant_id" => options[:tenant_id] || Fog::Mock.random_numbers(14).to_s, + "port_range_max" => options[:port_range_max], + "port_range_min" => options[:port_range_min], + "security_group_id" => security_group_id + } + self.data[:security_group_rules][data["id"]] = data + response.status = 201 + response.body = {"security_group_rule" => data} + response + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/delete_security_group.rb b/lib/fog/openstack/requests/network/delete_security_group.rb new file mode 100644 index 000000000..895b45235 --- /dev/null +++ b/lib/fog/openstack/requests/network/delete_security_group.rb @@ -0,0 +1,32 @@ +module Fog + module Network + class OpenStack + class Real + # Delete a security group + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the security group to delete + def delete_security_group(security_group_id) + request( + :expects => 204, + :method => 'DELETE', + :path => "security-groups/#{security_group_id}" + ) + end + end + + class Mock + def delete_security_group(security_group_id) + response = Excon::Response.new + if self.data[:security_groups][security_group_id] + self.data[:security_groups].delete(security_group_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/delete_security_group_rule.rb b/lib/fog/openstack/requests/network/delete_security_group_rule.rb new file mode 100644 index 000000000..2b0b02403 --- /dev/null +++ b/lib/fog/openstack/requests/network/delete_security_group_rule.rb @@ -0,0 +1,36 @@ +module Fog + module Network + class OpenStack + class Real + + # Delete a security group rule + # + # ==== Parameters + # * 'security_group_rule_id'<~String> - UUID of the security group rule to delete + def delete_security_group_rule(security_group_rule_id) + request( + :expects => 204, + :method => "DELETE", + :path => "security-group-rules/#{security_group_rule_id}" + ) + end + + end + + class Mock + + def delete_security_group_rule(security_group_rule_id) + response = Excon::Response.new + if self.data[:security_group_rules][security_group_rule_id] + self.data[:security_group_rules].delete(security_group_rule_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_security_group.rb b/lib/fog/openstack/requests/network/get_security_group.rb new file mode 100644 index 000000000..366539d7f --- /dev/null +++ b/lib/fog/openstack/requests/network/get_security_group.rb @@ -0,0 +1,52 @@ +module Fog + module Network + class OpenStack + class Real + # Get details about a security group + # + # ==== Parameters + # * 'security_group_id'<~String> - UUID of the security group + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def get_security_group(security_group_id) + request( + :expects => 200, + :method => "GET", + :path => "security-groups/#{security_group_id}" + ) + end + end + + class Mock + def get_security_group(security_group_id) + response = Excon::Response.new + if sec_group = self.data[:security_groups][security_group_id] + response.status = 200 + response.body = {"security_group" => sec_group} + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/get_security_group_rule.rb b/lib/fog/openstack/requests/network/get_security_group_rule.rb new file mode 100644 index 000000000..1bef89098 --- /dev/null +++ b/lib/fog/openstack/requests/network/get_security_group_rule.rb @@ -0,0 +1,47 @@ +module Fog + module Network + class OpenStack + class Real + # Get details about a security group rule + # + # ==== Parameters + # * 'security_group_rule_id'<~String> - UUID of the security group rule + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rule'<~Hash>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def get_security_group_rule(security_group_rule_id) + request( + :expects => 200, + :method => "GET", + :path => "security-group-rules/#{security_group_rule_id}" + ) + end + end + + class Mock + def get_security_group_rule(security_group_rule_id) + response = Excon::Response.new + if sec_group_rule = self.data[:security_group_rules][security_group_rule_id] + response.status = 200 + response.body = {"security_group_rule" => sec_group_rule} + response + else + raise Fog::Network::OpenStack::NotFound + end + end + end + end + end +end diff --git a/lib/fog/openstack/requests/network/list_networks.rb b/lib/fog/openstack/requests/network/list_networks.rb index bb8df2fba..42c6b8663 100644 --- a/lib/fog/openstack/requests/network/list_networks.rb +++ b/lib/fog/openstack/requests/network/list_networks.rb @@ -1,7 +1,6 @@ module Fog module Network class OpenStack - class Real def list_networks(filters = {}) request( diff --git a/lib/fog/openstack/requests/network/list_security_group_rules.rb b/lib/fog/openstack/requests/network/list_security_group_rules.rb new file mode 100644 index 000000000..4af07fdb6 --- /dev/null +++ b/lib/fog/openstack/requests/network/list_security_group_rules.rb @@ -0,0 +1,52 @@ +module Fog + module Network + class OpenStack + class Real + + # List all security group rules + # + # ==== Parameters + # * options<~Hash>: + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_group_rules'<~Array>: + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def list_security_group_rules(options = {}) + request( + :expects => 200, + :method => 'GET', + :path => 'security-group-rules', + :query => options + ) + end + + end + + class Mock + + def list_security_group_rules(options = {}) + response = Excon::Response.new + + sec_group_rules = [] + sec_group_rules = self.data[:security_group_rules].values unless self.data[:security_group_rules].nil? + + response.status = 200 + response.body = { 'security_group_rules' => sec_group_rules } + response + end + + end + end + end +end diff --git a/lib/fog/openstack/requests/network/list_security_groups.rb b/lib/fog/openstack/requests/network/list_security_groups.rb new file mode 100644 index 000000000..b0bbd2c4b --- /dev/null +++ b/lib/fog/openstack/requests/network/list_security_groups.rb @@ -0,0 +1,57 @@ +module Fog + module Network + class OpenStack + class Real + + # List all security groups + # + # ==== Parameters + # * options<~Hash>: + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'security_groups'<~Array>: + # * 'id'<~String> - UUID of the security group + # * 'name'<~String> - Name of the security group + # * 'description'<~String> - Description of the security group + # * 'tenant_id'<~String> - Tenant id that owns the security group + # * 'security_group_rules'<~Array>: - Array of security group rules + # * 'id'<~String> - UUID of the security group rule + # * 'direction'<~String> - Direction of traffic, must be in ['ingress', 'egress'] + # * 'port_range_min'<~Integer> - Start port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'port_range_max'<~Integer> - End port for rule i.e. 22 (or -1 for ICMP wildcard) + # * 'protocol'<~String> - IP protocol for rule, must be in ['tcp', 'udp', 'icmp'] + # * 'ethertype'<~String> - Type of ethernet support, must be in ['IPv4', 'IPv6'] + # * 'security_group_id'<~String> - UUID of the parent security group + # * 'remote_group_id'<~String> - UUID of the remote security group + # * 'remote_ip_prefix'<~String> - IP cidr range address i.e. '0.0.0.0/0' + # * 'tenant_id'<~String> - Tenant id that owns the security group rule + def list_security_groups(options = {}) + request( + :expects => 200, + :method => 'GET', + :path => 'security-groups', + :query => options + ) + end + + end + + class Mock + + def list_security_groups(options = {}) + response = Excon::Response.new + + sec_groups = [] + sec_groups = self.data[:security_groups].values unless self.data[:security_groups].nil? + + response.status = 200 + response.body = { 'security_groups' => sec_groups } + response + end + + end + end + end +end