dewiring 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/wire +7 -0
- data/bin/wire-network-container.sh +547 -0
- data/lib/test_fig.rb +46 -0
- data/lib/wire/cli/cli_commands.rb +88 -0
- data/lib/wire/cli/main_cli.rb +129 -0
- data/lib/wire/cli.rb +8 -0
- data/lib/wire/commands/base_command.rb +139 -0
- data/lib/wire/commands/down_command.rb +69 -0
- data/lib/wire/commands/down_command_handler.rb +199 -0
- data/lib/wire/commands/init_command.rb +89 -0
- data/lib/wire/commands/init_interactive.rb +75 -0
- data/lib/wire/commands/spec_command.rb +240 -0
- data/lib/wire/commands/spec_templates.rb +134 -0
- data/lib/wire/commands/up_command.rb +69 -0
- data/lib/wire/commands/up_command_handler.rb +193 -0
- data/lib/wire/commands/updown_command_base.rb +80 -0
- data/lib/wire/commands/validate_command.rb +64 -0
- data/lib/wire/commands/verify_command.rb +196 -0
- data/lib/wire/commands/verify_command_handler.rb +134 -0
- data/lib/wire/commands.rb +19 -0
- data/lib/wire/common.rb +42 -0
- data/lib/wire/execution/local_exec.rb +110 -0
- data/lib/wire/execution.rb +7 -0
- data/lib/wire/model/appgroup_validation.rb +45 -0
- data/lib/wire/model/loader.rb +49 -0
- data/lib/wire/model/network_validation.rb +111 -0
- data/lib/wire/model/project.rb +64 -0
- data/lib/wire/model/state.rb +154 -0
- data/lib/wire/model/validation.rb +66 -0
- data/lib/wire/model/verification.rb +37 -0
- data/lib/wire/model.rb +13 -0
- data/lib/wire/resource/bridge.rb +76 -0
- data/lib/wire/resource/dhcp_range_config.rb +135 -0
- data/lib/wire/resource/fig_adapter.rb +127 -0
- data/lib/wire/resource/ip_binary.rb +141 -0
- data/lib/wire/resource/ipaddr_ext.rb +38 -0
- data/lib/wire/resource/ipaddr_on_intf.rb +108 -0
- data/lib/wire/resource/network_injection.rb +138 -0
- data/lib/wire/resource/resource.rb +52 -0
- data/lib/wire/resource.rb +14 -0
- data/lib/wire/version.rb +14 -0
- data/lib/wire.rb +24 -0
- metadata +117 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
# Wire module
|
8
|
+
module Wire
|
9
|
+
# interactive ask_ commands
|
10
|
+
class InitInteractive
|
11
|
+
# ask for a comma separated list of zone names
|
12
|
+
# returns
|
13
|
+
# - [Array] of zone names
|
14
|
+
def self.ask_for_zone_names
|
15
|
+
question = <<-EOF
|
16
|
+
Please enter the names of desired system zones,
|
17
|
+
as a comma-separated list:
|
18
|
+
EOF
|
19
|
+
puts question
|
20
|
+
print '> '
|
21
|
+
|
22
|
+
line = STDIN.gets.chomp
|
23
|
+
|
24
|
+
line.split(',').map { |zone_name| zone_name.strip }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Ask for network names in a zone given by +zone_name+
|
28
|
+
# Returns
|
29
|
+
# - [Array] of network names
|
30
|
+
def self.ask_for_network_in_zone(zone_name)
|
31
|
+
question = <<-EOF
|
32
|
+
- Configuring networks in zone #{zone_name}:
|
33
|
+
Please enter the names of logical networks
|
34
|
+
(or leave empty if no networks desired):
|
35
|
+
EOF
|
36
|
+
puts question
|
37
|
+
print '> '
|
38
|
+
|
39
|
+
line = STDIN.gets.chomp
|
40
|
+
|
41
|
+
line.split(',').map { |network_name| network_name.strip }
|
42
|
+
end
|
43
|
+
|
44
|
+
# For a network given by +network_name+, ask for details
|
45
|
+
# i.e. ipaddress etc.
|
46
|
+
# Returns
|
47
|
+
# - [Hash] of details
|
48
|
+
def self.ask_detail_data_for_network(network_name)
|
49
|
+
question = <<-EOF
|
50
|
+
= Configuring network #{network_name}
|
51
|
+
Please enter network address in cidr (i.e.192.168.1.0/24)
|
52
|
+
EOF
|
53
|
+
puts question
|
54
|
+
print '> '
|
55
|
+
|
56
|
+
line = STDIN.gets.chomp
|
57
|
+
result = {}
|
58
|
+
|
59
|
+
result.store :network, line.chomp.strip
|
60
|
+
|
61
|
+
question = <<-EOF
|
62
|
+
Please enter ip address of this network on host (i.e.192.168.1.1)
|
63
|
+
OR leave empty if not desired.
|
64
|
+
EOF
|
65
|
+
puts question
|
66
|
+
print '> '
|
67
|
+
|
68
|
+
line = STDIN.gets.chomp.strip
|
69
|
+
|
70
|
+
result.store(:hostip, line) if line.size > 0
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
# Wire module
|
8
|
+
module Wire
|
9
|
+
# SpecCommand generates a serverspec output for
|
10
|
+
# given model which tests all model elements.
|
11
|
+
# optionally runs serverspec
|
12
|
+
class SpecCommand < BaseCommand
|
13
|
+
# +project+ to operate on
|
14
|
+
attr_accessor :project
|
15
|
+
# +target_dir+ to read model from (and put specs into)
|
16
|
+
attr_accessor :target_dir
|
17
|
+
|
18
|
+
# spec_code will contain all serverspec
|
19
|
+
# code blocks, ready to be written to file
|
20
|
+
attr_accessor :spec_code
|
21
|
+
|
22
|
+
# initializes empty spec
|
23
|
+
def initialize
|
24
|
+
@spec_code = []
|
25
|
+
end
|
26
|
+
|
27
|
+
# process specification for whole project model
|
28
|
+
def run_on_project
|
29
|
+
@target_dir = @params[:target_dir]
|
30
|
+
zones = @project.get_element('zones')
|
31
|
+
|
32
|
+
# iterates all zones, descend into zone
|
33
|
+
run_on_project_zones(zones)
|
34
|
+
|
35
|
+
# use the specwrite class to write a complete
|
36
|
+
# serverspec example in a subdirectory(serverspec)
|
37
|
+
target_specdir = File.join(@target_dir, 'serverspec')
|
38
|
+
|
39
|
+
begin
|
40
|
+
spec_writer = SpecWriter.new(target_specdir, @spec_code)
|
41
|
+
spec_writer.write
|
42
|
+
|
43
|
+
outputs 'SPEC', "Serverspecs written to #{target_specdir}. Run:"
|
44
|
+
outputs 'SPEC', "( cd #{target_specdir}; sudo rake spec )"
|
45
|
+
outputs 'SPEC', 'To run automatically, use --run'
|
46
|
+
rescue => exception
|
47
|
+
$log.error "Error writing serverspec files, #{exception}"
|
48
|
+
STDERR.puts e.inspect
|
49
|
+
end
|
50
|
+
|
51
|
+
run_serverspec(target_specdir) if @params[:auto_run]
|
52
|
+
end
|
53
|
+
|
54
|
+
# executes serverspec in its target directory
|
55
|
+
# TODO: stream into stdout instead of Kernel.``
|
56
|
+
# params:
|
57
|
+
# +target_dir+ model and output dir
|
58
|
+
def run_serverspec(target_specdir)
|
59
|
+
$log.debug 'Running serverspec'
|
60
|
+
cmd = "cd #{target_specdir} && sudo rake spec"
|
61
|
+
$log.debug "cmd=#{cmd}"
|
62
|
+
result = `#{cmd}`
|
63
|
+
puts result
|
64
|
+
end
|
65
|
+
|
66
|
+
# run verification on +zones+
|
67
|
+
def run_on_project_zones(zones)
|
68
|
+
zones.select do |zone_name, _|
|
69
|
+
$log.debug("Creating specs for zone #{zone_name} ...")
|
70
|
+
run_on_zone(zone_name)
|
71
|
+
$log.debug("Done for zone #{zone_name} ...")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# run spec steps in given +zone_name+
|
76
|
+
def run_on_zone(zone_name)
|
77
|
+
networks = @project.get_element('networks')
|
78
|
+
|
79
|
+
# select networks in current zone only
|
80
|
+
networks_in_zone = networks.select do|_, network_data|
|
81
|
+
network_data[:zone] == zone_name
|
82
|
+
end
|
83
|
+
networks_in_zone.each do |network_name, network_data|
|
84
|
+
run_on_network_in_zone zone_name, network_name, network_data
|
85
|
+
end
|
86
|
+
|
87
|
+
# select application groups in current zone
|
88
|
+
objects_in_zone('appgroups', zone_name).each do |appgroup_name, appgroup_data|
|
89
|
+
run_on_appgroup_in_zone zone_name, appgroup_name, appgroup_data
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# given a network object, this generates spec
|
94
|
+
# for it.
|
95
|
+
# params:
|
96
|
+
# +zone_name+ name of zone (needed for erb context)
|
97
|
+
# +bridge_name+ name of network/bridge (needed for erb context)
|
98
|
+
# +network_data+ network details
|
99
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
100
|
+
# rubocop:disable Lint/UselessAssignment
|
101
|
+
# :reek:UnusedParameters
|
102
|
+
def run_on_network_in_zone(zone_name, bridge_name, network_data)
|
103
|
+
$log.debug("Creating specs for network #{bridge_name}")
|
104
|
+
|
105
|
+
template = SpecTemplates.build_template__bridge_exists
|
106
|
+
erb = ERB.new(template, nil, '%')
|
107
|
+
@spec_code << erb.result(binding)
|
108
|
+
|
109
|
+
# render template for hostip (if any)
|
110
|
+
ip = network_data[:hostip]
|
111
|
+
if ip
|
112
|
+
template = SpecTemplates.build_template__ip_is_up
|
113
|
+
erb = ERB.new(template, nil, '%')
|
114
|
+
@spec_code << erb.result(binding)
|
115
|
+
end
|
116
|
+
|
117
|
+
# render dhcp spec (if any)
|
118
|
+
dhcp_data = network_data[:dhcp]
|
119
|
+
if dhcp_data
|
120
|
+
ip_start = dhcp_data[:start]
|
121
|
+
ip_end = dhcp_data[:end]
|
122
|
+
hostip = ip
|
123
|
+
template = SpecTemplates.build_template__dhcp_is_valid
|
124
|
+
erb = ERB.new(template, nil, '%')
|
125
|
+
@spec_code << erb.result(binding)
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
$log.debug("Done for network #{bridge_name}")
|
130
|
+
end
|
131
|
+
|
132
|
+
# given an appgroup object, this generates spec
|
133
|
+
# for it.
|
134
|
+
# params:
|
135
|
+
# +zone_name+ name of zone (needed for erb context)
|
136
|
+
# +appgroup_name+ name of appgroup (needed for erb context)
|
137
|
+
# +appgroup_data+ appgroup details
|
138
|
+
# rubocop:disable Lint/UnusedMethodArgument Lint/UselessAssignment
|
139
|
+
# :reek:UnusedParameters
|
140
|
+
def run_on_appgroup_in_zone(zone_name, appgroup_name, appgroup_data)
|
141
|
+
$log.debug("Creating specs for appgroup #{appgroup_name}")
|
142
|
+
|
143
|
+
# check controller
|
144
|
+
controller_data = appgroup_data[:controller]
|
145
|
+
if controller_data[:type] == 'fig'
|
146
|
+
# get fig file name
|
147
|
+
figfile_part = controller_data[:file] || "#{zone_name}/fig.yaml"
|
148
|
+
figfile = File.join(File.expand_path(@target_dir), figfile_part)
|
149
|
+
|
150
|
+
template = SpecTemplates.build_template__fig_file_is_valid
|
151
|
+
erb = ERB.new(template, nil, '%')
|
152
|
+
@spec_code << erb.result(binding)
|
153
|
+
|
154
|
+
template = SpecTemplates.build_template__fig_containers_are_up
|
155
|
+
erb = ERB.new(template, nil, '%')
|
156
|
+
@spec_code << erb.result(binding)
|
157
|
+
end
|
158
|
+
|
159
|
+
$log.debug("Done for appgroup #{appgroup_name}")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# SpecWriter is able to create a directory
|
164
|
+
# structure according to basic serverspec
|
165
|
+
# needs and fill in the templates
|
166
|
+
class SpecWriter
|
167
|
+
# create SpecWriter in +target_dir+ directory
|
168
|
+
# with given +spec_contents+
|
169
|
+
def initialize(target_dir, spec_contents)
|
170
|
+
@target_dir = target_dir
|
171
|
+
@spec_contents = spec_contents
|
172
|
+
end
|
173
|
+
|
174
|
+
# writes spec to disk
|
175
|
+
def write
|
176
|
+
ensure_directory_structure
|
177
|
+
ensure_files
|
178
|
+
end
|
179
|
+
|
180
|
+
# make sure that we have a rspec-conformant dir structure
|
181
|
+
def ensure_directory_structure
|
182
|
+
ensure_directory @target_dir
|
183
|
+
ensure_directory File.join(@target_dir, 'spec')
|
184
|
+
ensure_directory File.join(@target_dir, 'spec', 'localhost')
|
185
|
+
end
|
186
|
+
|
187
|
+
# writes erb +template+ to open +file+ object
|
188
|
+
def write_template(template, file)
|
189
|
+
erb = ERB.new(template, nil, '%')
|
190
|
+
file.puts(erb.result(binding))
|
191
|
+
end
|
192
|
+
|
193
|
+
# ensures that all serverspec skeleton files such as
|
194
|
+
# Rakefile, spec_helper etc. exist
|
195
|
+
# Then writes the models specification files into the
|
196
|
+
# skeleton
|
197
|
+
def ensure_files
|
198
|
+
rakefile_name = File.join(@target_dir, 'Rakefile')
|
199
|
+
file?(rakefile_name) || File.open(rakefile_name, 'w') do |file|
|
200
|
+
write_template(SpecTemplates.template_rakefile, file)
|
201
|
+
end
|
202
|
+
|
203
|
+
spechelper_name = File.join(@target_dir, 'spec', 'spec_helper.rb')
|
204
|
+
file?(spechelper_name) || File.open(spechelper_name, 'w') do |file|
|
205
|
+
write_template(SpecTemplates.template_spec_helper, file)
|
206
|
+
end
|
207
|
+
|
208
|
+
specfile_name = File.join(@target_dir, 'spec', 'localhost', 'wire_spec.rb')
|
209
|
+
File.open(specfile_name, 'w') do |file|
|
210
|
+
template = <<ERB
|
211
|
+
require 'spec_helper.rb'
|
212
|
+
|
213
|
+
# begin of generated specs
|
214
|
+
|
215
|
+
<%= @spec_contents.join('\n') %>
|
216
|
+
|
217
|
+
# end of spec file
|
218
|
+
ERB
|
219
|
+
write_template(template, file)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
# make sure that +target_dir+ exists
|
226
|
+
def ensure_directory(target_dir)
|
227
|
+
return if File.exist?(target_dir)
|
228
|
+
begin
|
229
|
+
FileUtils.mkdir_p(target_dir)
|
230
|
+
rescue => excpt
|
231
|
+
$log.error "ERROR: Unable to create #{target_dir}: #{excpt}"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# checks if +target_file+ exists
|
236
|
+
def file?(target_file)
|
237
|
+
File.exist?(target_file) && File.file?(target_file)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
# Wire module
|
8
|
+
module Wire
|
9
|
+
# stateless erb template methods used by spec_command.rb
|
10
|
+
class SpecTemplates
|
11
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
12
|
+
# :reek:UnusedParameters
|
13
|
+
def self.build_template__bridge_exists
|
14
|
+
<<ERB
|
15
|
+
describe 'In zone <%= zone_name %> we should have an ovs bridge named <%= bridge_name %>' do
|
16
|
+
describe command "sudo ovs-vsctl list-br" do
|
17
|
+
its(:stdout) { should match /<%= bridge_name %>/ }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
ERB
|
21
|
+
end
|
22
|
+
|
23
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
24
|
+
# :reek:UnusedParameters
|
25
|
+
def self.build_template__ip_is_up
|
26
|
+
<<ERB
|
27
|
+
describe 'In zone <%= zone_name %> we should have the ip <%= ip %> ' \
|
28
|
+
'on ovs bridge named <%= bridge_name %>' do
|
29
|
+
describe interface "<%= bridge_name %>" do
|
30
|
+
it { should have_ipv4_address '<%= ip %>' }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
ERB
|
34
|
+
end
|
35
|
+
|
36
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
37
|
+
# :reek:UnusedParameters
|
38
|
+
# requires zone_name, hostip, bridge_name, ip_start, ip_end
|
39
|
+
def self.build_template__dhcp_is_valid
|
40
|
+
<<ERB
|
41
|
+
describe 'In zone <%= zone_name %> we should have dhcp service on ip <%= hostip %> ' \
|
42
|
+
'on ovs bridge named <%= bridge_name %>, serving addresses from ' \
|
43
|
+
'<%= ip_start %> to <%= ip_end %>' do
|
44
|
+
|
45
|
+
describe file '/etc/dnsmasq.d/wire__<%= zone_name %>.conf' do
|
46
|
+
it { should be_file }
|
47
|
+
its(:content) { should match /<%= ip_start %>/ }
|
48
|
+
its(:content) { should match /<%= ip_end %>/ }
|
49
|
+
its(:content) { should match /<%= bridge_name %>/ }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe process 'dnsmasq' do
|
53
|
+
it { should be_running }
|
54
|
+
end
|
55
|
+
|
56
|
+
describe port(67) do
|
57
|
+
it { should be_listening.with('udp') }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe command '/bin/netstat -nlup' do
|
61
|
+
its(:stdout) { should match /67.*dnsmasq/ }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
ERB
|
65
|
+
end
|
66
|
+
|
67
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
68
|
+
# :reek:UnusedParameters
|
69
|
+
# requires figfile, appgroup_name
|
70
|
+
def self.build_template__fig_file_is_valid
|
71
|
+
<<ERB
|
72
|
+
describe 'In zone <%= zone_name %> we should have fig model file for '\
|
73
|
+
'appgroup <%= appgroup_name %>' do
|
74
|
+
describe file '<%= figfile %>' do
|
75
|
+
it { should be_file }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
ERB
|
79
|
+
end
|
80
|
+
|
81
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
82
|
+
# :reek:UnusedParameters
|
83
|
+
# requires zone_name, figfile, appgroup_name
|
84
|
+
def self.build_template__fig_containers_are_up
|
85
|
+
<<ERB
|
86
|
+
describe 'In zone <%= zone_name %> we should have containers managed '\
|
87
|
+
'by fig for appgroup <%= appgroup_name %>' do
|
88
|
+
describe command 'sudo fig -p <%= appgroup_name %> -f <%= figfile %> ps' do
|
89
|
+
its(:stdout) { should match /Up/ }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
ERB
|
93
|
+
end
|
94
|
+
|
95
|
+
# generate template part
|
96
|
+
# returns
|
97
|
+
# - erb template for spec_helper.rb file
|
98
|
+
def self.template_spec_helper
|
99
|
+
<<ERB
|
100
|
+
require 'serverspec'
|
101
|
+
require 'rspec/its'
|
102
|
+
|
103
|
+
include SpecInfra::Helper::Exec
|
104
|
+
include SpecInfra::Helper::DetectOS
|
105
|
+
|
106
|
+
RSpec.configure do |c|
|
107
|
+
if ENV['ASK_SUDO_PASSWORD']
|
108
|
+
require 'highline/import'
|
109
|
+
c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false }
|
110
|
+
else
|
111
|
+
c.sudo_password = ENV['SUDO_PASSWORD']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
ERB
|
115
|
+
end
|
116
|
+
|
117
|
+
# generate template part
|
118
|
+
# returns
|
119
|
+
# - erb template for Rakefile
|
120
|
+
def self.template_rakefile
|
121
|
+
<<ERB
|
122
|
+
require 'rake'
|
123
|
+
require 'rspec/core/rake_task'
|
124
|
+
|
125
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
126
|
+
t.pattern = 'spec/*/*_spec.rb'
|
127
|
+
t.rspec_opts = '--format documentation --color'
|
128
|
+
end
|
129
|
+
|
130
|
+
task :default => :spec
|
131
|
+
ERB
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
# Wire module
|
8
|
+
module Wire
|
9
|
+
# UpCommand reads yaml, parses model elements
|
10
|
+
# and brings all defined model elements "up", that is
|
11
|
+
# starting bridges, containers etc.
|
12
|
+
class UpCommand < UpDownCommand
|
13
|
+
# allow to get access to handler object
|
14
|
+
attr_reader :handler
|
15
|
+
|
16
|
+
# initialize
|
17
|
+
def initialize
|
18
|
+
@handler = UpCommandHandler.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# run in given +zone_name+:
|
22
|
+
# returns:
|
23
|
+
# - bool: true if successful, false otherwise
|
24
|
+
# rubocop:disable CyclomaticComplexity
|
25
|
+
def run_on_zone(zone_name)
|
26
|
+
b_result = true
|
27
|
+
|
28
|
+
networks = @project.get_element('networks')
|
29
|
+
|
30
|
+
# select networks in current zone only
|
31
|
+
networks_in_zone = UpDownCommand.get_networks_for_zone(networks, zone_name)
|
32
|
+
networks_in_zone.each do |network_name, network_data|
|
33
|
+
$log.debug("Bringing up network #{network_name}")
|
34
|
+
|
35
|
+
success = @handler.handle_bridge(network_name)
|
36
|
+
b_result &= success
|
37
|
+
if success
|
38
|
+
# if we have a host ip on that bridge, take it down first
|
39
|
+
b_result &= default_handle_hostip(network_name, network_data, @handler)
|
40
|
+
|
41
|
+
# if we have dhcp, configure dnsmasq
|
42
|
+
b_result &= default_handle_dhcp(zone_name, network_name, network_data, @handler)
|
43
|
+
else
|
44
|
+
$log.debug("Will not touch dependant objects of #{network_name} due to previous error(s)")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# select appgroups in this zone and bring them up
|
49
|
+
appgroups_in_zone = objects_in_zone('appgroups', zone_name)
|
50
|
+
appgroups_in_zone.each do |appgroup_name, appgroup_data|
|
51
|
+
$log.debug("Processing appgroup \'#{appgroup_name}\'")
|
52
|
+
|
53
|
+
success = handler.handle_appgroup(zone_name,
|
54
|
+
appgroup_name, appgroup_data,
|
55
|
+
@project.target_dir)
|
56
|
+
b_result &= success
|
57
|
+
|
58
|
+
# process network attachments
|
59
|
+
zone_networks = objects_in_zone('networks', zone_name)
|
60
|
+
success = handler.handle_network_attachments(zone_name, zone_networks,
|
61
|
+
appgroup_name, appgroup_data,
|
62
|
+
@project.target_dir)
|
63
|
+
b_result &= success
|
64
|
+
end
|
65
|
+
|
66
|
+
b_result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
# Wire module
|
8
|
+
module Wire
|
9
|
+
# handle_xxx methods for UpCommand
|
10
|
+
# rubocop:disable ClassLength
|
11
|
+
class UpCommandHandler < BaseCommand
|
12
|
+
# bring bridge resource up, identified by
|
13
|
+
# +bridge_name+
|
14
|
+
# Returns
|
15
|
+
# - [Bool] true if hostip if up on bridge
|
16
|
+
def handle_bridge(bridge_name)
|
17
|
+
b_result = true
|
18
|
+
|
19
|
+
# we should have a bridge with that name.
|
20
|
+
bridge_resource = Wire::Resource::ResourceFactory.instance.create(:ovsbridge, bridge_name)
|
21
|
+
if bridge_resource.up?
|
22
|
+
outputs 'UP', "Bridge #{bridge_name} already up.", :ok2
|
23
|
+
else
|
24
|
+
bridge_resource.up
|
25
|
+
if bridge_resource.up?
|
26
|
+
outputs 'UP', "Bridge #{bridge_name} up.", :ok
|
27
|
+
state.update(:bridge, bridge_name, :up)
|
28
|
+
else
|
29
|
+
outputs 'UP', "Error bringing up bridge #{bridge_name}.", :err
|
30
|
+
b_result = false
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
b_result
|
35
|
+
end
|
36
|
+
|
37
|
+
# bring ip resource up on device identified by
|
38
|
+
# +bridge_name+ and +host_ip+
|
39
|
+
# Returns
|
40
|
+
# - [Bool] true if hostip if up on bridge
|
41
|
+
def handle_hostip(bridge_name, hostip)
|
42
|
+
b_result = true
|
43
|
+
|
44
|
+
# we should have a bridge with that name.
|
45
|
+
hostip_resource = Wire::Resource::ResourceFactory
|
46
|
+
.instance.create(:bridgeip, hostip, bridge_name)
|
47
|
+
if hostip_resource.up?
|
48
|
+
outputs 'UP', "IP #{hostip} on bridge #{bridge_name} already up.", :ok2
|
49
|
+
else
|
50
|
+
hostip_resource.up
|
51
|
+
if hostip_resource.up?
|
52
|
+
outputs 'UP', "IP #{hostip} on bridge #{bridge_name} up.", :ok
|
53
|
+
state.update(:hostip, hostip, :up)
|
54
|
+
else
|
55
|
+
outputs 'UP', "Error bringing up ip #{hostip} on bridge #{bridge_name}.", :err
|
56
|
+
b_result = false
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
b_result
|
61
|
+
end
|
62
|
+
|
63
|
+
# configures dnsmasq for dhcp
|
64
|
+
# +zone_name+ name of zone
|
65
|
+
# +network_name+ name of network (and bridge)
|
66
|
+
# +network+ network entry
|
67
|
+
# +address_start+ start of address range (i.e.192.168.10.10)
|
68
|
+
# +address_end+ end of dhcp address range (i.e.192.168.10.100)
|
69
|
+
# Returns
|
70
|
+
# - [Bool] true if dhcp setup is valid
|
71
|
+
def handle_dhcp(zone_name, network_name, network_entry, address_start, address_end)
|
72
|
+
resource_dhcp = Wire::Resource::ResourceFactory
|
73
|
+
.instance.create(:dhcpconfig, "wire__#{zone_name}", network_name,
|
74
|
+
network_entry, address_start, address_end)
|
75
|
+
if resource_dhcp.up?
|
76
|
+
outputs 'UP', "dnsmasq/dhcp config on network \'#{network_name}\' is already up.", :ok2
|
77
|
+
return true
|
78
|
+
else
|
79
|
+
resource_dhcp.up
|
80
|
+
if resource_dhcp.up?
|
81
|
+
outputs 'UP', "dnsmasq/dhcp config on network \'#{network_name}\' is up.", :ok
|
82
|
+
state.update(:dnsmasq, network_name, :up)
|
83
|
+
return true
|
84
|
+
else
|
85
|
+
outputs 'UP', "Error configuring dnsmasq/dhcp config on network \'#{network_name}\'.",
|
86
|
+
:err
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# take the appgroups' controller and directs methods to
|
93
|
+
# it. First checks if appgroup is up. If so, ok. If not, bring it up
|
94
|
+
# and ensure that it's up
|
95
|
+
# Params:
|
96
|
+
# +zone_name+:: Name of zone
|
97
|
+
# +appgroup_name+:: Name of Appgroup
|
98
|
+
# +appgroup_entry+:: Appgroup data from model
|
99
|
+
def handle_appgroup(zone_name, appgroup_name, appgroup_entry, target_dir)
|
100
|
+
# get path
|
101
|
+
controller_entry = appgroup_entry[:controller]
|
102
|
+
|
103
|
+
if controller_entry[:type] == 'fig'
|
104
|
+
return handle_appgroup__fig(zone_name, appgroup_name, appgroup_entry, target_dir)
|
105
|
+
end
|
106
|
+
|
107
|
+
$log.error "Appgroup not handled, unknown controller type #{controller_entry[:type]}"
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
# implement appgroup handling for fig controller
|
112
|
+
# Params:
|
113
|
+
# +zone_name+:: Name of zone
|
114
|
+
# +appgroup_name+:: Name of Appgroup
|
115
|
+
# +appgroup_entry+:: Appgroup data from model
|
116
|
+
# +target_dir+:: Target directory (where fig file is located)
|
117
|
+
def handle_appgroup__fig(zone_name, appgroup_name, appgroup_entry, target_dir)
|
118
|
+
# get path
|
119
|
+
controller_entry = appgroup_entry[:controller]
|
120
|
+
|
121
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
122
|
+
|
123
|
+
resource_fig = Wire::Resource::ResourceFactory
|
124
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
125
|
+
|
126
|
+
if resource_fig.up?
|
127
|
+
outputs 'UP', "appgroup \'#{appgroup_name}\' in zone #{zone_name} is already up.", :ok2
|
128
|
+
return true
|
129
|
+
else
|
130
|
+
resource_fig.up
|
131
|
+
if resource_fig.up?
|
132
|
+
outputs 'UP', "appgroup \'#{appgroup_name}\' in zone #{zone_name} is up.", :ok
|
133
|
+
state.update(:appgroup, appgroup_name, :up)
|
134
|
+
return true
|
135
|
+
else
|
136
|
+
outputs 'UP', "Error bringing up appgroup \'#{appgroup_name}\' in zone #{zone_name} .",
|
137
|
+
:err
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# attaches networks to containers of appgroup
|
144
|
+
# Params:
|
145
|
+
# ++_zone_name++: Name of zone
|
146
|
+
# ++networks++: Array of networks names, what to attach
|
147
|
+
# ++appgroup_name++: Name of appgroup
|
148
|
+
# ++appgroup_entry++: appgroup hash
|
149
|
+
# ++target_dir++: project target dir
|
150
|
+
# Returns
|
151
|
+
# - [Bool] true if appgroup setup is ok
|
152
|
+
def handle_network_attachments(_zone_name, networks, appgroup_name,
|
153
|
+
appgroup_entry, target_dir)
|
154
|
+
# query container ids of containers running here
|
155
|
+
# get path
|
156
|
+
controller_entry = appgroup_entry[:controller]
|
157
|
+
|
158
|
+
container_ids = []
|
159
|
+
|
160
|
+
if controller_entry[:type] == 'fig'
|
161
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
162
|
+
|
163
|
+
resource_fig = Wire::Resource::ResourceFactory
|
164
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
165
|
+
|
166
|
+
container_ids = resource_fig.up_ids || []
|
167
|
+
$log.debug "Got #{container_ids.size} container id(s) from adapter"
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
resource_nw = Wire::Resource::ResourceFactory
|
172
|
+
.instance.create(:networkinjection, appgroup_name, networks.keys, container_ids)
|
173
|
+
if resource_nw.up?
|
174
|
+
outputs 'UP', "appgroup \'#{appgroup_name}\' already has valid network " \
|
175
|
+
'attachments.', :ok2
|
176
|
+
state.update(:appgroup, appgroup_name, :up)
|
177
|
+
return true
|
178
|
+
else
|
179
|
+
resource_nw.up
|
180
|
+
if resource_nw.up?
|
181
|
+
outputs 'UP', "appgroup \'#{appgroup_name}\' attached " \
|
182
|
+
"networks #{networks.keys.join(',')}.", :ok
|
183
|
+
state.update(:appgroup, appgroup_name, :up)
|
184
|
+
return true
|
185
|
+
else
|
186
|
+
outputs 'UP', "Error attaching networks to appgroup \'#{appgroup_name}\'.",
|
187
|
+
:err
|
188
|
+
return false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|