vcloud-net-spinner 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +7 -0
  3. data/CHANGELOG +12 -0
  4. data/Gemfile +4 -0
  5. data/README.md +109 -0
  6. data/Rakefile +25 -0
  7. data/bin/vcloud-net-spinner +5 -0
  8. data/docs/find_network_url.md +56 -0
  9. data/docs/find_organisation_edgegateway_uuid.md +58 -0
  10. data/jenkins.sh +6 -0
  11. data/lib/component/firewall.rb +83 -0
  12. data/lib/component/load_balancer.rb +182 -0
  13. data/lib/component/nat.rb +78 -0
  14. data/lib/vcloud_network_configurator.rb +64 -0
  15. data/lib/vcloud_network_configurator/configure_task.rb +22 -0
  16. data/lib/vcloud_network_configurator/edge_gateway.rb +51 -0
  17. data/lib/vcloud_network_configurator/vcloud_auth_request.rb +39 -0
  18. data/lib/vcloud_network_configurator/vcloud_check_for_configure_task_request.rb +26 -0
  19. data/lib/vcloud_network_configurator/vcloud_configure_request.rb +58 -0
  20. data/lib/vcloud_network_configurator/vcloud_settings.rb +22 -0
  21. data/lib/vcloud_network_configurator/version.rb +1 -0
  22. data/spec/component/firewall.xml +45 -0
  23. data/spec/component/firewall_spec.rb +120 -0
  24. data/spec/component/lb.xml +567 -0
  25. data/spec/component/load_balancer_spec.rb +73 -0
  26. data/spec/component/nat.xml +146 -0
  27. data/spec/component/nat_spec.rb +35 -0
  28. data/spec/integration/authorization_failed_spec.rb +26 -0
  29. data/spec/integration/happy_path_firewall_spec.rb +74 -0
  30. data/spec/integration/happy_path_loadbalancer_spec.rb +173 -0
  31. data/spec/integration/happy_path_nat_spec.rb +78 -0
  32. data/spec/integration/test_data/happy_path_auth_response.xml +30 -0
  33. data/spec/integration/test_data/rules_dir/common_firewall.rb +6 -0
  34. data/spec/integration/test_data/rules_dir/common_lb.rb +10 -0
  35. data/spec/integration/test_data/rules_dir/common_nat.rb +0 -0
  36. data/spec/integration/test_data/rules_dir/preview/firewall.rb +0 -0
  37. data/spec/integration/test_data/rules_dir/preview/interfaces.yaml +2 -0
  38. data/spec/integration/test_data/rules_dir/preview/lb.rb +0 -0
  39. data/spec/integration/test_data/rules_dir/preview/nat.rb +4 -0
  40. data/spec/spec_helper.rb +9 -0
  41. data/spec/vcloud_network_configurator/configure_task_spec.rb +59 -0
  42. data/spec/vcloud_network_configurator/edge_gateway_spec.rb +41 -0
  43. data/spec/vcloud_network_configurator/vcloud_auth_request_spec.rb +20 -0
  44. data/spec/vcloud_network_configurator/vcloud_configure_request_spec.rb +22 -0
  45. data/spec/vcloud_network_configurator/vcloud_settings_spec.rb +19 -0
  46. data/vcloud-net-spinner.gemspec +33 -0
  47. metadata +215 -0
@@ -0,0 +1,2 @@
1
+ .bundle/
2
+ Gemfile.lock
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_script: bundle install
5
+ script:
6
+ - bundle exec rake spec
7
+ - bundle exec rake integration
@@ -0,0 +1,12 @@
1
+ 0.1.2 2013-08-13
2
+
3
+ - Exit when no rules provided
4
+ - Made the presence of files in directory tree as optional
5
+
6
+ 0.1.1 2013-08-13
7
+
8
+ - Renaming the gem to vcloud-net-spinner
9
+
10
+ 0.1.0 2013-08-07
11
+
12
+ - Introucing vcloud-network-configurator
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gds-provisioning.gemspec
4
+ gemspec
@@ -0,0 +1,109 @@
1
+ # Vcloud Network Configurator
2
+
3
+ This is ruby gem which provides a dsl to configure firewall, nat and
4
+ loadbalancer rules. It is a wrapper around the network components of
5
+ vcloud api.
6
+
7
+ ## Installation
8
+
9
+ gem install vcloud-net-spinner
10
+
11
+ ## Usage
12
+
13
+ Usage: vcloud-net-spinner [options] API_URL
14
+ -u, --username=U Vcloud Username
15
+ -p, --password=P Vcloud Password
16
+ -e, --env=E Environment: preview | staging | production
17
+ -U, --organization-edgegateway-uuid=U UID: This is required to configure edgegateway services. For more info refer to
18
+ docs/find_organisation_edgegateway_uuid
19
+ -c, --component=c Environment: lb|firewall|nat
20
+ -o, --organization=o Organization: optional. Will default to environment
21
+ -d, --rule-directory=d Rules Directory: From where to read the NAT/Firewal/LB rules
22
+
23
+ Note: organization maps to the organization name in vcloud. Whereas,
24
+ environment maps to your internal environment reference (e.g.
25
+ preview, qa, staging, production, etc)
26
+
27
+ ### Example
28
+
29
+ vcloud-net-spinner -u username -p password -e preview -U 1yenz127ynz1872eyz12yz817e -c firewall -o development -d . http://vcloud.vendor.com/api
30
+
31
+ ### Rules Directory
32
+
33
+ A particular rules directory structure could be as follows.
34
+
35
+ .
36
+ ├── Gemfile
37
+ ├── Gemfile.lock
38
+ ├── common_firewall.rb
39
+ ├── common_lb.rb
40
+ ├── common_nat.rb
41
+ ├── env1
42
+ │ ├── firewall.rb
43
+ │ ├── interfaces.yaml
44
+ │ ├── lb.rb
45
+ │ └── nat.rb
46
+ ├── env2
47
+ ├── firewall.rb
48
+ ├── interfaces.yaml
49
+ ├── lb.rb
50
+ └── nat.rb
51
+
52
+ * Here each environment represent a separate organisation with your vcloud
53
+ vendor (eg qa, staging, production). These could have specific rules for nat,
54
+ firewall. Also these can have common firewall rules which could be shared
55
+ across all environments. A common example of such a situation is internal
56
+ network firewall rules are usually shared across environments, whereas
57
+ external network firewall rules would be different for all environment.
58
+
59
+ * Specific network rules => `env1/firewall.rb`, `env1/nat.rb`, `env1/lb.rb`
60
+ * Common network rules => `./common_firewall.rb`, `./common_lb.rb`, `./common_lb.rb`
61
+
62
+ * interfaces.yaml file:
63
+ To find the urls for network, follow the document at
64
+ `docs/find_network_url`
65
+
66
+ interfaces:
67
+ Network-1: "https://localhost:4567/api/admin/network/<vdc-network-uuid>"
68
+ Network-2: "https://localhost:4567/api/admin/network/<vdc-network-uuid>"
69
+
70
+ ### DSL
71
+
72
+ #### Firewall
73
+
74
+ firewall do
75
+ rule "<description>" do
76
+ source :ip => "172.10.0.0/8"
77
+ destination :ip => "172.10.0.5", :port => 4567
78
+ end
79
+ end
80
+
81
+ #### NAT
82
+
83
+ nat do
84
+ snat :interface => "<key-from-interfaces.rb>", :original => { :ip => "internal-ip" }, :translated => { :ip => "external-ip" }, :desc => "description"
85
+ dnat :interface => "<key-from-interfaces.rb>", :original => { :ip => "external-ip", :port => 22 }, :translated => { :ip => "internal-ip", :port => 22 }, :desc => "SSH"
86
+ end
87
+
88
+
89
+ #### Load Balancer
90
+
91
+ load_balancer do
92
+ configure "description-1" do
93
+ pool ["<ip-1>", "<ip-2>"] do
94
+ http
95
+ https
96
+ end
97
+
98
+ virtual_server :name => "description-1", :interface => "<key-from-interfaces.rb>", :ip => "<vse-ip>"
99
+ end
100
+
101
+ configure "description-2" do
102
+ pool ["<ip-1>", "<ip-2>", "<ip-3>"] do
103
+ http :port => 8080, :health_check_path => "</router/healthcheck>"
104
+ https
105
+ end
106
+
107
+ virtual_server :name => "description-2", :interface => "<key-from-interfaces.rb>", :ip => "<vse-ip>"
108
+ end
109
+ end
@@ -0,0 +1,25 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+ require 'rspec/core/rake_task'
4
+ require "gem_publisher"
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.pattern = FileList.new('spec/**/*_spec.rb') do |file|
8
+ file.exclude(/integration/)
9
+ end
10
+ task.rspec_opts = ['--color']
11
+ end
12
+
13
+ RSpec::Core::RakeTask.new(:integration) do |task|
14
+ task.pattern = FileList['spec/integration/*_spec.rb']
15
+ task.rspec_opts = ['--color']
16
+ end
17
+
18
+ task :default => [:spec]
19
+
20
+ desc "Publish gem to RubyGems.org"
21
+ task :publish_gem do |t|
22
+ gem = GemPublisher.publish_if_updated("vcloud-net-spinner.gemspec", :rubygems)
23
+ puts "Published #{gem}" if gem
24
+ end
25
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+ require 'vcloud_network_configurator'
4
+
5
+ VcloudNetworkConfigurator.new(ARGV).execute
@@ -0,0 +1,56 @@
1
+ # How to find Network UUID for interfaces.yaml
2
+
3
+ ## Steps
4
+
5
+ * vcloud authorization
6
+
7
+ curl -v -X POST -d '' -H "Accept: application/*+xml;version=5.1"
8
+ -u "{username}@vcloud-org-name:**********"
9
+ https://vendor-api-url.net/sessions
10
+
11
+
12
+ The above returns the following information in response
13
+ `x-cloud-authorization` and
14
+ `<Link rel="down" type="application/vnd.vmware.vcloud.orgList+xml" href="https://vendor-api-url.net/org/"/>`
15
+
16
+
17
+ * List organisations
18
+
19
+ curl -v --insecure
20
+ -H "x-vcloud-authorization: {x-vcloud-auth-code}"
21
+ -H "Accept: application/*+xml;version=5.1"
22
+ "https://vendor-api-url.net/org/"
23
+
24
+
25
+ This gives the list of organizations you have access to, and you can choose the one you need by using the name attribute `<Org type="application/vnd.vmware.vcloud.org+xml" name="ORG-NAME" href="https://vendor-api-url.net/org/{org-code}"/>`
26
+
27
+ * Get details of the organisation
28
+
29
+ curl -v --insecure -H "x-vcloud-authorization: {x-vcloud-auth-code}"
30
+ -H "Accept: application/*+xml;version=5.1"
31
+ "https://vendor-api-url.net/org/{org-code}"
32
+
33
+ * This also gives details about various vdc. We would need the one for management vdc:
34
+
35
+ <Link rel="down" type="application/vnd.vmware.vcloud.vdc+xml"
36
+ name="Management - GDS Development (SL1)"
37
+ href="https://vendor-api-url.net/vdc/{vdc-uuid}"/>
38
+
39
+ * Get vdc details
40
+
41
+ curl -v --insecure -H "x-vcloud-authorization: {x-vcloud-auth-code}"
42
+ -H "Accept: application/*+xml;version=5.1"
43
+ "https://vendor-api-url.net/vdc/{vdc-uuid}
44
+
45
+ * This would provide you with available networks. From which you
46
+ can use the name and href attributes for adding to your
47
+ interfaces.yaml
48
+
49
+ <AvailableNetworks>
50
+ <Network type="application/vnd.vmware.vcloud.network+xml" name="NetworkTest2"
51
+ href="https:///vendor-api-url.net/network/{network-uuid-2}"/>
52
+ <Network type="application/vnd.vmware.vcloud.network+xml" name="NetworkTest"
53
+ href="https:///vendor-api-url.net/network/{network-uuid-1}"/>
54
+ </AvailableNetworks>
55
+
56
+
@@ -0,0 +1,58 @@
1
+ # How to find Organisation Edgegateway UUID
2
+
3
+ ##Steps:
4
+
5
+ * vcloud authorization
6
+
7
+ curl -v -X POST -d '' -H "Accept: application/*+xml;version=5.1"
8
+ -u "{username}@vcloud-org-name:**********"
9
+ https://vendor-api-url.net/sessions
10
+
11
+
12
+ The above returns the following information in response
13
+ `x-cloud-authorization` and
14
+ `<Link rel="down" type="application/vnd.vmware.vcloud.orgList+xml" href="https://vendor-api-url.net/org/"/>`
15
+
16
+
17
+ * List organisations
18
+
19
+ curl -v --insecure
20
+ -H "x-vcloud-authorization: {x-vcloud-auth-code}"
21
+ -H "Accept: application/*+xml;version=5.1"
22
+ "https://vendor-api-url.net/org/"
23
+
24
+
25
+ This gives the list of organizations you have access to, and you can choose the one you need by using the name attribute `<Org type="application/vnd.vmware.vcloud.org+xml" name="ORG-NAME" href="https://vendor-api-url.net/org/{org-code}"/>`
26
+
27
+ * Get details of the organisation
28
+
29
+ curl -v --insecure -H "x-vcloud-authorization: {x-vcloud-auth-code}"
30
+ -H "Accept: application/*+xml;version=5.1"
31
+ "https://vendor-api-url.net/org/{org-code}"
32
+
33
+ * This also gives details about various vdc. We would need the one for management vdc:
34
+
35
+ <Link rel="down" type="application/vnd.vmware.vcloud.vdc+xml"
36
+ name="Management - GDS Development (SL1)"
37
+ href="https://vendor-api-url.net/vdc/{org-code}"/>
38
+
39
+ * Retrieve edgegateway record
40
+
41
+ curl -v --insecure -H "x-vcloud-authorization: {x-vcloud-auth-code}="
42
+ -H "Accept: application/*+xml;version=5.1"
43
+ "https://vendor-api-url.net/admin/vdc/{management-edgegateway-uuid}/edgeGateways"
44
+
45
+ * Response of the above is (from which you would need the id in the href attribute):
46
+
47
+ <EdgeGatewayRecord vdc="https://vendor-api-url.net/vdc/{management-edgegateway-uuid}"
48
+ numberOfOrgNetworks="8" numberOfExtNetworks="1"
49
+ name="GDS Development Gateway" isBusy="false" haStatus="UP" gatewayStatus="READY"
50
+ href="https://vendor-api-url.net/admin/edgeGateway/{id}"
51
+ isSyslogServerSettingInSync="true" taskStatus="success"
52
+ taskOperation="networkConfigureEdgeGatewayServices"
53
+ task="https://vendor-api-url.net/task/***" taskDetails=" "/>
54
+
55
+ *e.g. https://vendor-api-url.net/admin/edgeGateway/{id}*
56
+
57
+
58
+
@@ -0,0 +1,6 @@
1
+ #!/bin/bash -x
2
+ set -e
3
+ bundle install --path "${HOME}/bundles/${JOB_NAME}"
4
+ bundle exec rake spec
5
+ bundle exec rake integration
6
+ bundle exec rake publish_gem --trace
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+
4
+ module Component
5
+ class Firewall
6
+ attr_reader :rules
7
+
8
+ def initialize
9
+ @rules = []
10
+ @count = 0
11
+ end
12
+
13
+ def rule(description, options = {}, &block)
14
+ defaults = { :enabled => true, :protocols => [:tcp], :id => @count+=1, :description => description}
15
+ @current_rule = defaults.merge(options)
16
+ rules << @current_rule
17
+ yield
18
+ ensure
19
+ @current_rule = nil
20
+ end
21
+
22
+ def source(options)
23
+ @current_rule[:source] = { :port => options[:port] || "Any", :ip => options[:ip] }
24
+ end
25
+
26
+ def destination(options)
27
+ @current_rule[:destination] = { :port => options[:port], :ip => options[:ip] }
28
+ end
29
+
30
+ def self.reset
31
+ @firewall = nil
32
+ end
33
+
34
+ def self.instance
35
+ @firewall ||= Firewall.new
36
+ end
37
+
38
+ def self.generate_xml interfaces
39
+ return if Firewall.instance.rules.nil? or Firewall.instance.rules.empty?
40
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
41
+ xml.EdgeGatewayServiceConfiguration('xmlns' => "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xsi:schemaLocation' => "http://www.vmware.com/vcloud/v1.5 http://vendor-api-url.net/v1.5/schema/master.xsd") {
42
+ xml.FirewallService {
43
+ xml.IsEnabled "true"
44
+ xml.DefaultAction "drop"
45
+ xml.LogDefaultAction "false"
46
+
47
+ Firewall.instance.rules.each do |rule|
48
+ xml.FirewallRule {
49
+ xml.Id rule[:id]
50
+ xml.IsEnabled rule[:enabled]
51
+ xml.MatchOnTranslate "false"
52
+ xml.Description rule[:description]
53
+ xml.Policy "allow"
54
+
55
+ xml.Protocols {
56
+ rule[:protocols].each do |protocol|
57
+ xml.send(protocol.to_s.capitalize, true)
58
+ end
59
+ }
60
+
61
+ if rule[:protocols].first == :icmp
62
+ xml.IcmpSubType "any"
63
+ end
64
+
65
+ xml.Port rule[:destination][:port] == "Any" ? "-1" : rule[:destination][:port]
66
+ xml.DestinationPortRange rule[:destination][:port]
67
+ xml.DestinationIp rule[:destination][:ip]
68
+ xml.SourcePort rule[:source][:port] == "Any" ? "-1" : rule[:source][:port]
69
+ xml.SourcePortRange rule[:source][:port]
70
+ xml.SourceIp rule[:source][:ip]
71
+ xml.EnableLogging "false"
72
+ }
73
+ end
74
+ }
75
+ }
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def firewall (&block)
82
+ Component::Firewall.instance.instance_eval(&block)
83
+ end
@@ -0,0 +1,182 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+
4
+ module Component
5
+ class LoadBalancer
6
+ attr_reader :pools, :configurations
7
+
8
+ def initialize
9
+ @pools = []
10
+ @configurations = []
11
+ end
12
+
13
+ def configure(name, &block)
14
+ @current_configuration = { :name => name, :virtual_servers => [], :pool => nil }
15
+ @configurations << @current_configuration
16
+ yield
17
+ ensure
18
+ @current_pool = nil
19
+ end
20
+
21
+ def virtual_server(options = {})
22
+ raise "Can't add a virtual server without first having defined a pool" if @current_pool.nil?
23
+ virtual_server = { :name => options[:name], :pool => @current_pool[:name], :ip => options[:ip], :interface => options[:interface] }
24
+ @current_configuration[:virtual_servers] << virtual_server
25
+ end
26
+
27
+ def pool(nodes, &block)
28
+ @current_pool = { :name => "#{@current_configuration[:name]} pool", :ports => [], :nodes => nodes }
29
+ @current_configuration[:pool] = @current_pool
30
+ @pools << @current_pool
31
+ yield
32
+ end
33
+
34
+ def http(options = {})
35
+ defaults = { :enabled => true, :health_check_path => "/", :port => 80, :health_check_mode => "HTTP" }
36
+ options = defaults.merge(options)
37
+ @current_pool[:ports] << { :port => options[:port], :health_check_port => options[:health_check_port],
38
+ :health_check_path => options[:health_check_path], :enabled => options[:enabled],
39
+ :type => :http, :health_check_mode=>options[:health_check_mode] }
40
+ end
41
+
42
+ def https(options = {})
43
+ defaults = { :enabled => true, :health_check_path => "/", :port => 443, :health_check_mode => "SSL" }
44
+ options = defaults.merge(options)
45
+ @current_pool[:ports] << { :port => options[:port], :health_check_port => options[:health_check_port],
46
+ :health_check_path => options[:health_check_path], :enabled => options[:enabled],
47
+ :type => :https, :health_check_mode => options[:health_check_mode] }
48
+ end
49
+
50
+ def load_balances(port, options = {})
51
+ defaults = { :enabled => true, :health_check_path => "/" }
52
+ options = defaults.merge(options)
53
+ @current_pool[:ports] << { :port => port, :health_check_port => options[:health_check_port], :health_check_path => options[:health_check_path],
54
+ :enabled => options[:enabled], :type => options[:type] }
55
+ end
56
+
57
+ def self.instance
58
+ @lb ||= LoadBalancer.new
59
+ end
60
+
61
+ def self.generate_xml interfaces
62
+ return if LoadBalancer.instance.pools.nil? or LoadBalancer.instance.pools.empty?
63
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
64
+ xml.EdgeGatewayServiceConfiguration('xmlns' => "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xsi:schemaLocation' => "http://www.vmware.com/vcloud/v1.5 http://vendor-api-url.net/v1.5/schema/master.xsd") {
65
+ xml.LoadBalancerService {
66
+ xml.IsEnabled 'false'
67
+ LoadBalancer.instance.pools.each do |pool|
68
+ xml.Pool {
69
+ xml.Name pool[:name]
70
+
71
+ pool[:ports].each do |port|
72
+ xml.ServicePort {
73
+ xml.IsEnabled port[:enabled]
74
+ xml.Protocol port[:port] == 443 ? "HTTPS" : "HTTP"
75
+ xml.Algorithm 'ROUND_ROBIN'
76
+ xml.Port port[:port]
77
+
78
+ if port[:health_check_port]
79
+ xml.HealthCheckPort port[:health_check_port]
80
+ else
81
+ xml.HealthCheckPort
82
+ end
83
+
84
+ xml.HealthCheck {
85
+ xml.Mode port[:health_check_mode]
86
+ xml.Uri port[:health_check_path]
87
+ xml.HealthThreshold "2"
88
+ xml.UnhealthThreshold "3"
89
+ xml.Interval "5"
90
+ xml.Timeout "15"
91
+ }
92
+ }
93
+ end
94
+
95
+ xml.ServicePort {
96
+ xml.IsEnabled 'false'
97
+ xml.Protocol "TCP"
98
+ xml.Algorithm 'ROUND_ROBIN'
99
+ xml.Port
100
+ xml.HealthCheckPort
101
+ xml.HealthCheck {
102
+ xml.Mode "TCP"
103
+ xml.HealthThreshold "2"
104
+ xml.UnhealthThreshold "3"
105
+ xml.Interval "5"
106
+ xml.Timeout "15"
107
+ }
108
+ }
109
+
110
+ pool[:nodes].each do |node|
111
+ xml.Member {
112
+ xml.IpAddress node
113
+ xml.Weight "1"
114
+
115
+ ["HTTP", "HTTPS"].each do |protocol|
116
+ xml.ServicePort {
117
+ xml.Protocol protocol
118
+ xml.Port pool[:ports].find { |port| port[:type] == protocol.downcase.to_sym }[:port]
119
+ xml.HealthCheckPort
120
+ }
121
+ end
122
+
123
+ xml.ServicePort {
124
+ xml.Protocol "TCP"
125
+ xml.Port
126
+ xml.HealthCheckPort
127
+ }
128
+
129
+ }
130
+ end
131
+ xml.Operational "false"
132
+ }
133
+ end
134
+
135
+ LoadBalancer.instance.configurations.each do |configuration|
136
+ configuration[:virtual_servers].each do |virtual_server|
137
+ xml.VirtualServer {
138
+ xml.IsEnabled "true"
139
+ xml.Name virtual_server[:name]
140
+ xml.Interface('type' => "application/vnd.vmware.vcloud.orgVdcNetwork+xml", :name => virtual_server[:interface], :href => interfaces[virtual_server[:interface]])
141
+ xml.IpAddress virtual_server[:ip]
142
+
143
+ configuration[:pool][:ports].each do |port|
144
+ xml.ServiceProfile {
145
+ xml.IsEnabled port[:enabled]
146
+ xml.Protocol port[:type].to_s.upcase
147
+ xml.Port port[:port]
148
+ xml.Persistence {
149
+ if port[:type] == :https
150
+ xml.Method
151
+ else
152
+ xml.Method
153
+ end
154
+ }
155
+ }
156
+ end
157
+
158
+ xml.ServiceProfile {
159
+ xml.IsEnabled "false"
160
+ xml.Protocol "TCP"
161
+ xml.Port
162
+ xml.Persistence {
163
+ xml.Method
164
+ }
165
+ }
166
+ xml.Logging "false"
167
+ xml.Pool configuration[:pool][:name]
168
+
169
+ }
170
+ end
171
+ end
172
+ }
173
+ }
174
+ end
175
+ end
176
+
177
+ end
178
+ end
179
+
180
+ def load_balancer (&block)
181
+ Component::LoadBalancer.instance.instance_eval(&block)
182
+ end