vcloud-network-configurator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +4 -0
  3. data/README.md +116 -0
  4. data/Rakefile +25 -0
  5. data/bin/vcloud_configure_edge_gateway +5 -0
  6. data/docs/find_network_url.md +56 -0
  7. data/docs/find_organisation_edgegateway_uuid.md +58 -0
  8. data/jenkins.sh +6 -0
  9. data/lib/component/firewall.rb +82 -0
  10. data/lib/component/load_balancer.rb +181 -0
  11. data/lib/component/nat.rb +73 -0
  12. data/lib/vcloud_network_configurator.rb +64 -0
  13. data/lib/vcloud_network_configurator/configure_task.rb +22 -0
  14. data/lib/vcloud_network_configurator/edge_gateway.rb +51 -0
  15. data/lib/vcloud_network_configurator/vcloud_auth_request.rb +39 -0
  16. data/lib/vcloud_network_configurator/vcloud_check_for_configure_task_request.rb +26 -0
  17. data/lib/vcloud_network_configurator/vcloud_configure_request.rb +51 -0
  18. data/lib/vcloud_network_configurator/vcloud_settings.rb +22 -0
  19. data/lib/vcloud_network_configurator/version.rb +1 -0
  20. data/spec/component/firewall.xml +45 -0
  21. data/spec/component/firewall_spec.rb +115 -0
  22. data/spec/component/lb.xml +567 -0
  23. data/spec/component/load_balancer_spec.rb +67 -0
  24. data/spec/component/nat.xml +146 -0
  25. data/spec/component/nat_spec.rb +28 -0
  26. data/spec/integration/authorization_failed_spec.rb +26 -0
  27. data/spec/integration/happy_path_firewall_spec.rb +74 -0
  28. data/spec/integration/happy_path_loadbalancer_spec.rb +173 -0
  29. data/spec/integration/happy_path_nat_spec.rb +78 -0
  30. data/spec/integration/test_data/happy_path_auth_response.xml +30 -0
  31. data/spec/integration/test_data/rules_dir/common_firewall.rb +6 -0
  32. data/spec/integration/test_data/rules_dir/common_lb.rb +10 -0
  33. data/spec/integration/test_data/rules_dir/common_nat.rb +0 -0
  34. data/spec/integration/test_data/rules_dir/preview/firewall.rb +0 -0
  35. data/spec/integration/test_data/rules_dir/preview/interfaces.yaml +2 -0
  36. data/spec/integration/test_data/rules_dir/preview/lb.rb +0 -0
  37. data/spec/integration/test_data/rules_dir/preview/nat.rb +4 -0
  38. data/spec/spec_helper.rb +9 -0
  39. data/spec/vcloud_network_configurator/configure_task_spec.rb +59 -0
  40. data/spec/vcloud_network_configurator/edge_gateway_spec.rb +41 -0
  41. data/spec/vcloud_network_configurator/vcloud_auth_request_spec.rb +20 -0
  42. data/spec/vcloud_network_configurator/vcloud_settings_spec.rb +19 -0
  43. data/vcloud-network-configurator.gemspec +33 -0
  44. metadata +212 -0
@@ -0,0 +1,2 @@
1
+ .bundle/
2
+ Gemfile.lock
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,116 @@
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-network-configurator
10
+
11
+ * Note: It is work in progress, and currently you would have to build
12
+ them gem locally using the following commands
13
+
14
+ git clone git@github.com:alphagov/vcloud-network-configurator.git
15
+ gem build vcloud-network-configurator.gemspec
16
+ gem install ./vcloud-network-configurator-0.1.0.gem
17
+
18
+ ## Usage
19
+
20
+ Usage: vcloud_configure_edge_gateway [options] API_URL
21
+ -u, --username=U Vcloud Username
22
+ -p, --password=P Vcloud Password
23
+ -e, --env=E Environment: preview | staging | production
24
+ -U, --organization-edgegateway-uuid=U UID: This is required to configure edgegateway services. For more info refer to
25
+ docs/find_organisation_edgegateway_uuid
26
+ -c, --component=c Environment: lb|firewall|nat
27
+ -o, --organization=o Organization: optional. Will default to environment
28
+ -d, --rule-directory=d Rules Directory: From where to read the NAT/Firewal/LB rules
29
+
30
+ Note: organization maps to the organization name in vcloud. Whereas,
31
+ environment maps to your internal environment reference (e.g.
32
+ preview, qa, staging, production, etc)
33
+
34
+ ### Example
35
+
36
+ vcloud_configure_edge_gateway -u username -p password -e preview -U 1yenz127ynz1872eyz12yz817e -c firewall -o development -d . http://vcloud.vendor.com/api
37
+
38
+ ### Rules Directory
39
+
40
+ A particular rules directory structure could be as follows.
41
+
42
+ .
43
+ ├── Gemfile
44
+ ├── Gemfile.lock
45
+ ├── common_firewall.rb
46
+ ├── common_lb.rb
47
+ ├── common_nat.rb
48
+ ├── env1
49
+ │ ├── firewall.rb
50
+ │ ├── interfaces.yaml
51
+ │ ├── lb.rb
52
+ │ └── nat.rb
53
+ ├── env2
54
+ ├── firewall.rb
55
+ ├── interfaces.yaml
56
+ ├── lb.rb
57
+ └── nat.rb
58
+
59
+ * Here each environment represent a separate organisation with your vcloud
60
+ vendor (eg qa, staging, production). These could have specific rules for nat,
61
+ firewall. Also these can have common firewall rules which could be shared
62
+ across all environments. A common example of such a situation is internal
63
+ network firewall rules are usually shared across environments, whereas
64
+ external network firewall rules would be different for all environment.
65
+
66
+ * Specific network rules => `env1/firewall.rb`, `env1/nat.rb`, `env1/lb.rb`
67
+ * Common network rules => `./common_firewall.rb`, `./common_lb.rb`, `./common_lb.rb`
68
+
69
+ * interfaces.yaml file:
70
+ To find the urls for network, follow the document at
71
+ `docs/find_network_url`
72
+
73
+ interfaces:
74
+ Network-1: "https://localhost:4567/api/admin/network/<vdc-network-uuid>"
75
+ Network-2: "https://localhost:4567/api/admin/network/<vdc-network-uuid>"
76
+
77
+ ### DSL
78
+
79
+ #### Firewall
80
+
81
+ firewall do
82
+ rule "<description>" do
83
+ source :ip => "172.10.0.0/8"
84
+ destination :ip => "172.10.0.5", :port => 4567
85
+ end
86
+ end
87
+
88
+ #### NAT
89
+
90
+ nat do
91
+ snat :interface => "<key-from-interfaces.rb>", :original => { :ip => "internal-ip" }, :translated => { :ip => "external-ip" }, :desc => "description"
92
+ dnat :interface => "<key-from-interfaces.rb>", :original => { :ip => "external-ip", :port => 22 }, :translated => { :ip => "internal-ip", :port => 22 }, :desc => "SSH"
93
+ end
94
+
95
+
96
+ #### Load Balancer
97
+
98
+ load_balancer do
99
+ configure "description-1" do
100
+ pool ["<ip-1>", "<ip-2>"] do
101
+ http
102
+ https
103
+ end
104
+
105
+ virtual_server :name => "description-1", :interface => "<key-from-interfaces.rb>", :ip => "<vse-ip>"
106
+ end
107
+
108
+ configure "description-2" do
109
+ pool ["<ip-1>", "<ip-2>", "<ip-3>"] do
110
+ http :port => 8080, :health_check_path => "</router/healthcheck>"
111
+ https
112
+ end
113
+
114
+ virtual_server :name => "description-2", :interface => "<key-from-interfaces.rb>", :ip => "<vse-ip>"
115
+ end
116
+ 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-network-configurator.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,82 @@
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
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
40
+ 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") {
41
+ xml.FirewallService {
42
+ xml.IsEnabled "true"
43
+ xml.DefaultAction "drop"
44
+ xml.LogDefaultAction "false"
45
+
46
+ Firewall.instance.rules.each do |rule|
47
+ xml.FirewallRule {
48
+ xml.Id rule[:id]
49
+ xml.IsEnabled rule[:enabled]
50
+ xml.MatchOnTranslate "false"
51
+ xml.Description rule[:description]
52
+ xml.Policy "allow"
53
+
54
+ xml.Protocols {
55
+ rule[:protocols].each do |protocol|
56
+ xml.send(protocol.to_s.capitalize, true)
57
+ end
58
+ }
59
+
60
+ if rule[:protocols].first == :icmp
61
+ xml.IcmpSubType "any"
62
+ end
63
+
64
+ xml.Port rule[:destination][:port] == "Any" ? "-1" : rule[:destination][:port]
65
+ xml.DestinationPortRange rule[:destination][:port]
66
+ xml.DestinationIp rule[:destination][:ip]
67
+ xml.SourcePort rule[:source][:port] == "Any" ? "-1" : rule[:source][:port]
68
+ xml.SourcePortRange rule[:source][:port]
69
+ xml.SourceIp rule[:source][:ip]
70
+ xml.EnableLogging "false"
71
+ }
72
+ end
73
+ }
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def firewall (&block)
81
+ Component::Firewall.instance.instance_eval(&block)
82
+ end
@@ -0,0 +1,181 @@
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
+ Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
63
+ 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") {
64
+ xml.LoadBalancerService {
65
+ xml.IsEnabled 'false'
66
+ LoadBalancer.instance.pools.each do |pool|
67
+ xml.Pool {
68
+ xml.Name pool[:name]
69
+
70
+ pool[:ports].each do |port|
71
+ xml.ServicePort {
72
+ xml.IsEnabled port[:enabled]
73
+ xml.Protocol port[:port] == 443 ? "HTTPS" : "HTTP"
74
+ xml.Algorithm 'ROUND_ROBIN'
75
+ xml.Port port[:port]
76
+
77
+ if port[:health_check_port]
78
+ xml.HealthCheckPort port[:health_check_port]
79
+ else
80
+ xml.HealthCheckPort
81
+ end
82
+
83
+ xml.HealthCheck {
84
+ xml.Mode port[:health_check_mode]
85
+ xml.Uri port[:health_check_path]
86
+ xml.HealthThreshold "2"
87
+ xml.UnhealthThreshold "3"
88
+ xml.Interval "5"
89
+ xml.Timeout "15"
90
+ }
91
+ }
92
+ end
93
+
94
+ xml.ServicePort {
95
+ xml.IsEnabled 'false'
96
+ xml.Protocol "TCP"
97
+ xml.Algorithm 'ROUND_ROBIN'
98
+ xml.Port
99
+ xml.HealthCheckPort
100
+ xml.HealthCheck {
101
+ xml.Mode "TCP"
102
+ xml.HealthThreshold "2"
103
+ xml.UnhealthThreshold "3"
104
+ xml.Interval "5"
105
+ xml.Timeout "15"
106
+ }
107
+ }
108
+
109
+ pool[:nodes].each do |node|
110
+ xml.Member {
111
+ xml.IpAddress node
112
+ xml.Weight "1"
113
+
114
+ ["HTTP", "HTTPS"].each do |protocol|
115
+ xml.ServicePort {
116
+ xml.Protocol protocol
117
+ xml.Port pool[:ports].find { |port| port[:type] == protocol.downcase.to_sym }[:port]
118
+ xml.HealthCheckPort
119
+ }
120
+ end
121
+
122
+ xml.ServicePort {
123
+ xml.Protocol "TCP"
124
+ xml.Port
125
+ xml.HealthCheckPort
126
+ }
127
+
128
+ }
129
+ end
130
+ xml.Operational "false"
131
+ }
132
+ end
133
+
134
+ LoadBalancer.instance.configurations.each do |configuration|
135
+ configuration[:virtual_servers].each do |virtual_server|
136
+ xml.VirtualServer {
137
+ xml.IsEnabled "true"
138
+ xml.Name virtual_server[:name]
139
+ xml.Interface('type' => "application/vnd.vmware.vcloud.orgVdcNetwork+xml", :name => virtual_server[:interface], :href => interfaces[virtual_server[:interface]])
140
+ xml.IpAddress virtual_server[:ip]
141
+
142
+ configuration[:pool][:ports].each do |port|
143
+ xml.ServiceProfile {
144
+ xml.IsEnabled port[:enabled]
145
+ xml.Protocol port[:type].to_s.upcase
146
+ xml.Port port[:port]
147
+ xml.Persistence {
148
+ if port[:type] == :https
149
+ xml.Method
150
+ else
151
+ xml.Method
152
+ end
153
+ }
154
+ }
155
+ end
156
+
157
+ xml.ServiceProfile {
158
+ xml.IsEnabled "false"
159
+ xml.Protocol "TCP"
160
+ xml.Port
161
+ xml.Persistence {
162
+ xml.Method
163
+ }
164
+ }
165
+ xml.Logging "false"
166
+ xml.Pool configuration[:pool][:name]
167
+
168
+ }
169
+ end
170
+ end
171
+ }
172
+ }
173
+ end
174
+ end
175
+
176
+ end
177
+ end
178
+
179
+ def load_balancer (&block)
180
+ Component::LoadBalancer.instance.instance_eval(&block)
181
+ end