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,80 @@
|
|
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
|
+
# Base class for up/down commands
|
10
|
+
class UpDownCommand < BaseCommand
|
11
|
+
# generic method, calls run_on_project_zones for
|
12
|
+
# all zones in model
|
13
|
+
def run_on_project
|
14
|
+
zones = @project.get_element('zones')
|
15
|
+
|
16
|
+
# iterates all zones, descend into zone
|
17
|
+
# for further checks, mark all those bad
|
18
|
+
# zones, decide upon boolean return flag
|
19
|
+
(run_on_project_zones(zones)
|
20
|
+
.each do |_zone_name, zone_data|
|
21
|
+
# error occured in run_on_zone call. Lets mark this
|
22
|
+
zone_data.store :status, :failed
|
23
|
+
|
24
|
+
end.size > 0)
|
25
|
+
end
|
26
|
+
|
27
|
+
# run on all given +zones+
|
28
|
+
# Returns [Hash] of zones that failed.
|
29
|
+
def run_on_project_zones(zones)
|
30
|
+
zones.select do |zone_name, _|
|
31
|
+
$log.debug("Processing zone #{zone_name} ...")
|
32
|
+
run_on_zone(zone_name) == false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# if dhcp is part of given +network_data+, use
|
37
|
+
# +handler+ to process it.
|
38
|
+
# +zone_name+:: Name of zone
|
39
|
+
# +network_name+:: Name of network
|
40
|
+
def default_handle_dhcp(zone_name, network_name, network_data, handler)
|
41
|
+
dhcp_data = network_data[:dhcp]
|
42
|
+
return true unless dhcp_data
|
43
|
+
|
44
|
+
$log.debug 'Processing dhcp/dnsmasq ...'
|
45
|
+
handler.handle_dhcp(zone_name,
|
46
|
+
network_name, network_data,
|
47
|
+
dhcp_data[:start], dhcp_data[:end])
|
48
|
+
end
|
49
|
+
|
50
|
+
# if host ip is enabled for given network (+network_name+, +network_data+)
|
51
|
+
# use +handler+ to process it
|
52
|
+
def default_handle_hostip(network_name, network_data, handler)
|
53
|
+
hostip = network_data[:hostip]
|
54
|
+
return true unless hostip
|
55
|
+
|
56
|
+
$log.debug "Processing host ip on network #{network_name} ..."
|
57
|
+
|
58
|
+
# if the hostip is not in cidr, take netmask
|
59
|
+
# from network entry, add to hostip
|
60
|
+
hostip = ensure_hostip_netmask(hostip, network_data)
|
61
|
+
|
62
|
+
# forward to handler
|
63
|
+
handler.handle_hostip(network_name, hostip)
|
64
|
+
end
|
65
|
+
|
66
|
+
# returns networks from given +networks+ array that
|
67
|
+
# belong to +zone_name+
|
68
|
+
# params:
|
69
|
+
# +networks+: array of all networks
|
70
|
+
# +zone_name+: name of desired zone
|
71
|
+
# returns:
|
72
|
+
# # => [Array] of networks for given zone
|
73
|
+
def self.get_networks_for_zone(networks, zone_name)
|
74
|
+
# select networks in given zone only
|
75
|
+
networks.select do |_, network_data|
|
76
|
+
network_data[:zone] == zone_name
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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
|
+
# Validate Command reads yaml, parses model elements
|
10
|
+
# and runs a number of consistency checks
|
11
|
+
class ValidateCommand < BaseCommand
|
12
|
+
# array of +errors+
|
13
|
+
attr_accessor :errors
|
14
|
+
|
15
|
+
# array of validations
|
16
|
+
attr_accessor :validations
|
17
|
+
|
18
|
+
# initializes an empty error list
|
19
|
+
def initialize
|
20
|
+
@errors = []
|
21
|
+
@validations = [NetworksValidation, AppGroupValidation]
|
22
|
+
end
|
23
|
+
|
24
|
+
# runs validation on given project
|
25
|
+
# returns
|
26
|
+
# => list of +errors+
|
27
|
+
def run_on_project
|
28
|
+
@errors = []
|
29
|
+
|
30
|
+
# run validations against it
|
31
|
+
# TODO: Move validation classes to class level definition
|
32
|
+
@validations.each do |val_clazz|
|
33
|
+
(@errors << run_validation(@project, val_clazz)).flatten!
|
34
|
+
end
|
35
|
+
|
36
|
+
if @errors.size == 0
|
37
|
+
outputs 'VALIDATE', 'OK, model is consistent.', :ok
|
38
|
+
else
|
39
|
+
outputs 'VALIDATE', 'ERROR, detected inconsistencies:', :error
|
40
|
+
@errors.each do |val_error|
|
41
|
+
outputs 'VALIDATE', val_error.to_s, :error
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@errors
|
46
|
+
end
|
47
|
+
|
48
|
+
# run a validation of given +validation_class+ against
|
49
|
+
# the model
|
50
|
+
#
|
51
|
+
# params:
|
52
|
+
# +project+:: project model object, to validate
|
53
|
+
# +validation_class+:: class object of validation, i.e. NetworksValidation
|
54
|
+
#
|
55
|
+
# returns:
|
56
|
+
# list of errors from validation object
|
57
|
+
def run_validation(project, validation_class)
|
58
|
+
$log.debug "Running validation class #{validation_class}"
|
59
|
+
val_object = validation_class.new(project)
|
60
|
+
val_object.run_validations
|
61
|
+
val_object.errors
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,196 @@
|
|
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
|
+
# Verify Command reads yaml, parses model elements
|
10
|
+
# and checks if given elements are present on the system
|
11
|
+
# rubocop:disable ClassLength
|
12
|
+
class VerifyCommand < BaseCommand
|
13
|
+
# +project+:: to operate upon
|
14
|
+
# +findings+:: is an array of potential errors that occured
|
15
|
+
# during verification run
|
16
|
+
attr_accessor :project, :findings
|
17
|
+
# allow to get access to handler object
|
18
|
+
attr_reader :handler
|
19
|
+
|
20
|
+
# set up with empty findings arraay
|
21
|
+
def initialize
|
22
|
+
@findings = []
|
23
|
+
@handler = VerifyCommandHandler.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# add a finding to the findings array
|
27
|
+
# params:
|
28
|
+
# +msg+:: what went wrong
|
29
|
+
# +type+:: element type, i.e. Network
|
30
|
+
# +element_name+:: element_name
|
31
|
+
# +element_data+:: map of details, from model
|
32
|
+
def mark(msg, type, element_name, element_data)
|
33
|
+
@findings <<
|
34
|
+
VerificationError.new(msg, type,
|
35
|
+
element_name, element_data)
|
36
|
+
end
|
37
|
+
|
38
|
+
# run verification on whole project
|
39
|
+
# iterates all zones, descend into zone
|
40
|
+
# verification
|
41
|
+
# returns:
|
42
|
+
# - [bool] true = verification ok
|
43
|
+
def run_on_project
|
44
|
+
zones = @project.get_element('zones')
|
45
|
+
|
46
|
+
# iterates all zones, descend into zone
|
47
|
+
# for further checks, mark all those bad
|
48
|
+
# zones, decide upon boolean return flag
|
49
|
+
(run_on_project_zones(zones)
|
50
|
+
.each do |zone_name, zone_data|
|
51
|
+
# error occured in run_on_zone call. Lets mark this
|
52
|
+
zone_data.store :status, :failed
|
53
|
+
mark("Not all elements of zone \'#{zone_name}\' are valid.",
|
54
|
+
:zone, zone_name, zone_data)
|
55
|
+
end.size > 0)
|
56
|
+
end
|
57
|
+
|
58
|
+
# run verification on given +zones+
|
59
|
+
def run_on_project_zones(zones)
|
60
|
+
zones.select do |zone_name, _|
|
61
|
+
$log.debug("Verifying zone #{zone_name} ...")
|
62
|
+
b_zone_res = run_on_zone(zone_name)
|
63
|
+
|
64
|
+
if b_zone_res
|
65
|
+
outputs 'VERIFY', "Zone \'#{zone_name}\' verified successfully", :ok
|
66
|
+
else
|
67
|
+
outputs 'VERIFY', "Zone \'#{zone_name}\' NOT verified successfully", :err
|
68
|
+
end
|
69
|
+
|
70
|
+
b_zone_res == false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# run verification for given +zone_name+:
|
75
|
+
# - check if bridges exist for all networks in
|
76
|
+
# this zone
|
77
|
+
def run_on_zone(zone_name)
|
78
|
+
networks = @project.get_element('networks')
|
79
|
+
|
80
|
+
b_verify_ok = true
|
81
|
+
|
82
|
+
# select networks in current zone only
|
83
|
+
networks_in_zone = networks.select do |_, network_data|
|
84
|
+
network_data[:zone] == zone_name
|
85
|
+
end
|
86
|
+
# verify these networks
|
87
|
+
b_verify_ok = false unless verify_networks(networks_in_zone, zone_name)
|
88
|
+
|
89
|
+
# select appgroups in this zone and verify them
|
90
|
+
appgroups_in_zone = objects_in_zone('appgroups', zone_name)
|
91
|
+
b_verify_ok = false unless verify_appgroups(appgroups_in_zone, zone_name)
|
92
|
+
|
93
|
+
b_verify_ok
|
94
|
+
end
|
95
|
+
|
96
|
+
# given an array of network elements (+networks_in_zone+), this
|
97
|
+
# method runs the verification on each network.
|
98
|
+
# It checks the availability of a bridge and
|
99
|
+
# the optional host ip on that bridge.
|
100
|
+
# Params:
|
101
|
+
# +networks_in_zone+:: Array of network data elements in desired zone
|
102
|
+
# +zone_name+:: Name of zone
|
103
|
+
def verify_networks(networks_in_zone, zone_name)
|
104
|
+
b_verify_ok = true
|
105
|
+
networks_in_zone.each do |network_name, network_data|
|
106
|
+
$log.debug("Verifying network \'#{network_name}\'")
|
107
|
+
|
108
|
+
bridge_name = network_name
|
109
|
+
|
110
|
+
$log.debug 'checking bridge ...'
|
111
|
+
# we should have a bridge with that name.
|
112
|
+
if @handler.handle_bridge(bridge_name) == false
|
113
|
+
network_data.store :status, :failed
|
114
|
+
b_verify_ok = false
|
115
|
+
mark("Bridge \'#{bridge_name}\' does not exist.",
|
116
|
+
:network, network_name, network_data)
|
117
|
+
else
|
118
|
+
network_data.store :status, :ok
|
119
|
+
|
120
|
+
hostip = network_data[:hostip]
|
121
|
+
# if we have a host ip, then that bridge should have
|
122
|
+
# this ip
|
123
|
+
if hostip
|
124
|
+
$log.debug 'checking host-ip ...'
|
125
|
+
|
126
|
+
# if the hostip is not in cidr, take netmask
|
127
|
+
# from network entry, add to hostip
|
128
|
+
hostip = ensure_hostip_netmask(hostip, network_data)
|
129
|
+
|
130
|
+
if @handler.handle_hostip(bridge_name, hostip) == false
|
131
|
+
network_data.store :status, :failed
|
132
|
+
b_verify_ok = false
|
133
|
+
mark("Host ip \'#{hostip}\' not up on bridge \'#{bridge_name}\'.",
|
134
|
+
:network, network_name, network_data)
|
135
|
+
else
|
136
|
+
network_data.store :status, :ok
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# if we have dhcp, check this
|
141
|
+
dhcp_data = network_data[:dhcp]
|
142
|
+
if dhcp_data
|
143
|
+
$log.debug 'checking dhcp ...'
|
144
|
+
if @handler.handle_dhcp(zone_name, network_name, network_data,
|
145
|
+
dhcp_data[:start],
|
146
|
+
dhcp_data[:end]) == false
|
147
|
+
network_data.store :status, :failed
|
148
|
+
b_verify_ok = false
|
149
|
+
mark("dnsmasq/dhcp not configured on network \'#{bridge_name}\'.",
|
150
|
+
:network, network_name, network_data)
|
151
|
+
else
|
152
|
+
network_data.store :status, :ok
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
b_verify_ok
|
158
|
+
end
|
159
|
+
|
160
|
+
# Given a +zone_name+ and an array of +appgroups+ entries
|
161
|
+
# this methods verifies if these appgroups are up and running
|
162
|
+
# It also checks container's network attachments
|
163
|
+
def verify_appgroups(appgroups, zone_name)
|
164
|
+
b_verify_ok = true
|
165
|
+
|
166
|
+
appgroups.each do |appgroup_name, appgroup_data|
|
167
|
+
$log.debug("Verifying appgroup \'#{appgroup_name}\'")
|
168
|
+
|
169
|
+
if @handler.handle_appgroup(zone_name, appgroup_name,
|
170
|
+
appgroup_data, @project.target_dir) == false
|
171
|
+
appgroup_data.store :status, :failed
|
172
|
+
b_verify_ok = false
|
173
|
+
mark("Appgroup \'#{appgroup_name}\' does not run correctly.",
|
174
|
+
:appgroup, appgroup_name, appgroup_data)
|
175
|
+
else
|
176
|
+
appgroup_data.store :status, :ok
|
177
|
+
end
|
178
|
+
|
179
|
+
next unless b_verify_ok
|
180
|
+
|
181
|
+
zone_networks = objects_in_zone('networks', zone_name)
|
182
|
+
if @handler.handle_network_attachments(zone_name, zone_networks,
|
183
|
+
appgroup_name, appgroup_data,
|
184
|
+
@project.target_dir) == false
|
185
|
+
appgroup_data.store :status, :failed
|
186
|
+
b_verify_ok = false
|
187
|
+
mark("Appgroup \'#{appgroup_name}\' has missing network attachments",
|
188
|
+
:appgroup, appgroup_name, appgroup_data)
|
189
|
+
else
|
190
|
+
appgroup_data.store :status, :ok
|
191
|
+
end
|
192
|
+
end
|
193
|
+
b_verify_ok
|
194
|
+
end
|
195
|
+
end
|
196
|
+
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
|
+
# handle_xxx methods for VerifyCommand
|
10
|
+
class VerifyCommandHandler < BaseCommand
|
11
|
+
# runs verification for a bridge resource identified by
|
12
|
+
# +bridge_name+
|
13
|
+
# Returns
|
14
|
+
# - [Bool] true if bridge exists
|
15
|
+
def handle_bridge(bridge_name)
|
16
|
+
bridge_resource = Wire::Resource::ResourceFactory.instance.create(:ovsbridge, bridge_name)
|
17
|
+
if bridge_resource.exist?
|
18
|
+
outputs 'VERIFY', "Bridge \'#{bridge_name}\' exists.", :ok
|
19
|
+
state.update(:bridge, bridge_name, :up)
|
20
|
+
return true
|
21
|
+
else
|
22
|
+
outputs 'VERIFY', "Bridge \'#{bridge_name}\' does not exist.", :err
|
23
|
+
state.update(:bridge, bridge_name, :down)
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# runs verification for a ip resource identified by
|
29
|
+
# +bridge_name+ and +host_ip+
|
30
|
+
# Returns
|
31
|
+
# - [Bool] true if hostip if up on bridge
|
32
|
+
def handle_hostip(bridge_name, hostip)
|
33
|
+
hostip_resource = Wire::Resource::ResourceFactory
|
34
|
+
.instance.create(:bridgeip, hostip, bridge_name)
|
35
|
+
if hostip_resource.up?
|
36
|
+
outputs 'VERIFY', "IP \'#{hostip}\' on bridge \'#{bridge_name}\' exists.", :ok
|
37
|
+
state.update(:hostip, hostip, :up)
|
38
|
+
return true
|
39
|
+
else
|
40
|
+
outputs 'VERIFY', "IP \'#{hostip}\' on bridge \'#{bridge_name}\' does not exist.", :err
|
41
|
+
state.update(:hostip, hostip, :down)
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# runs verification for dnsmasqs dhcp resource
|
47
|
+
# Returns
|
48
|
+
# - [Bool] true if dhcp setup is valid
|
49
|
+
def handle_dhcp(zone_name, network_name, network_entry, address_start, address_end)
|
50
|
+
resource = Wire::Resource::ResourceFactory
|
51
|
+
.instance.create(:dhcpconfig, "wire__#{zone_name}", network_name,
|
52
|
+
network_entry, address_start, address_end)
|
53
|
+
if resource.up?
|
54
|
+
outputs 'VERIFY', "dnsmasq/dhcp config on network \'#{network_name}\' is valid.", :ok
|
55
|
+
state.update(:dnsmasq, network_name, :up)
|
56
|
+
return true
|
57
|
+
else
|
58
|
+
outputs 'VERIFY', "dnsmasq/dhcp config on network \'#{network_name}\' is not valid.", :err
|
59
|
+
state.update(:dnsmasq, network_name, :down)
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# runs verification for appgroups
|
65
|
+
# Returns
|
66
|
+
# - [Bool] true if appgroup setup is ok
|
67
|
+
def handle_appgroup(_zone_name, appgroup_name, appgroup_entry, target_dir)
|
68
|
+
# get path
|
69
|
+
controller_entry = appgroup_entry[:controller]
|
70
|
+
|
71
|
+
if controller_entry[:type] == 'fig'
|
72
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
73
|
+
|
74
|
+
resource = Wire::Resource::ResourceFactory
|
75
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
76
|
+
if resource.up?
|
77
|
+
outputs 'VERIFY', "appgroup \'#{appgroup_name}\' is running.", :ok
|
78
|
+
state.update(:appgroup, appgroup_name, :up)
|
79
|
+
return true
|
80
|
+
else
|
81
|
+
outputs 'VERIFY', "appgroup \'#{appgroup_name}\' is not running.", :err
|
82
|
+
state.update(:appgroup, appgroup_name, :down)
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
$log.error "Appgroup not handled, unknown controller type #{controller_entry[:type]}"
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
# runs verification for container network attachment
|
92
|
+
# Params:
|
93
|
+
# ++_zone_name++: Name of zone
|
94
|
+
# ++networks++: Array of networks names, what to attach
|
95
|
+
# ++appgroup_name++: Name of appgroup
|
96
|
+
# ++appgroup_entry++: appgroup hash
|
97
|
+
# ++target_dir++: project target dir
|
98
|
+
# Returns
|
99
|
+
# - [Bool] true if appgroup setup is ok
|
100
|
+
def handle_network_attachments(_zone_name, networks, appgroup_name,
|
101
|
+
appgroup_entry, target_dir)
|
102
|
+
# query container ids of containers running here
|
103
|
+
# get path
|
104
|
+
controller_entry = appgroup_entry[:controller]
|
105
|
+
|
106
|
+
container_ids = []
|
107
|
+
|
108
|
+
if controller_entry[:type] == 'fig'
|
109
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
110
|
+
|
111
|
+
resource = Wire::Resource::ResourceFactory
|
112
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
113
|
+
|
114
|
+
container_ids = resource.up_ids || []
|
115
|
+
$log.debug "Got #{container_ids.size} container id(s) from adapter"
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
resource = Wire::Resource::ResourceFactory
|
120
|
+
.instance.create(:networkinjection, appgroup_name, networks.keys, container_ids)
|
121
|
+
if resource.up?
|
122
|
+
outputs 'VERIFY', "appgroup \'#{appgroup_name}\' has network(s) " \
|
123
|
+
"\'#{networks.keys.join(',')}\' attached.", :ok
|
124
|
+
state.update(:appgroup, appgroup_name, :up)
|
125
|
+
return true
|
126
|
+
else
|
127
|
+
outputs 'VERIFY', "appgroup \'#{appgroup_name}\' does not have " \
|
128
|
+
"all networks \'#{networks.keys.join(',')}\' attached.", :err
|
129
|
+
state.update(:appgroup, appgroup_name, :down)
|
130
|
+
return false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
require_relative 'commands/base_command.rb'
|
8
|
+
require_relative 'commands/init_command.rb'
|
9
|
+
require_relative 'commands/init_interactive.rb'
|
10
|
+
require_relative 'commands/validate_command.rb'
|
11
|
+
require_relative 'commands/verify_command.rb'
|
12
|
+
require_relative 'commands/verify_command_handler.rb'
|
13
|
+
require_relative 'commands/spec_command.rb'
|
14
|
+
require_relative 'commands/spec_templates.rb'
|
15
|
+
require_relative 'commands/updown_command_base.rb'
|
16
|
+
require_relative 'commands/up_command.rb'
|
17
|
+
require_relative 'commands/up_command_handler.rb'
|
18
|
+
require_relative 'commands/down_command.rb'
|
19
|
+
require_relative 'commands/down_command_handler.rb'
|
data/lib/wire/common.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'thor'
|
8
|
+
|
9
|
+
require 'rainbow'
|
10
|
+
require 'rainbow/ext/string'
|
11
|
+
|
12
|
+
require 'yaml'
|
13
|
+
require 'pp'
|
14
|
+
require 'English'
|
15
|
+
require 'erb'
|
16
|
+
require 'tempfile'
|
17
|
+
|
18
|
+
# set up log object
|
19
|
+
require 'logger'
|
20
|
+
|
21
|
+
$log = Logger.new STDOUT
|
22
|
+
# parametrize
|
23
|
+
$log.formatter = proc do |severity, _, _, msg|
|
24
|
+
"#{severity} #{msg}\n"
|
25
|
+
end
|
26
|
+
$log.level = Logger::INFO
|
27
|
+
|
28
|
+
# define exit codes
|
29
|
+
module Wire
|
30
|
+
# central place for exit codes, given by +id+
|
31
|
+
# Params
|
32
|
+
# +id+ i.e. :init_bad_input
|
33
|
+
# Returns
|
34
|
+
# exitcode as [int]
|
35
|
+
def self.cli_exitcode(id)
|
36
|
+
codes = {
|
37
|
+
:init_bad_input => 10,
|
38
|
+
:init_dir_error => 20
|
39
|
+
}
|
40
|
+
codes[id]
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
# Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'singleton'
|
8
|
+
|
9
|
+
# Wire module
|
10
|
+
module Wire
|
11
|
+
# Execution module for executing commands
|
12
|
+
module Execution
|
13
|
+
# return singleton object
|
14
|
+
def self.global_execution_options
|
15
|
+
ExecutionOptions.singleton
|
16
|
+
end
|
17
|
+
|
18
|
+
# Global execution options, such as noop mode etc.
|
19
|
+
class ExecutionOptions
|
20
|
+
include Singleton
|
21
|
+
|
22
|
+
# set default execution options
|
23
|
+
def initialize
|
24
|
+
@options = { :b_noop => false }
|
25
|
+
end
|
26
|
+
|
27
|
+
# returns
|
28
|
+
# - [Boolean] true if no_op mode
|
29
|
+
def noop?
|
30
|
+
@options[:b_noop]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Able to execute commands locally
|
35
|
+
# supports sudo and shell wrapping
|
36
|
+
class LocalExecution
|
37
|
+
# +exitstatus+ the exit status of a command that we ran
|
38
|
+
# +stdout+ stdout from command as [String]
|
39
|
+
# +stderr+ stderr from command as [String]
|
40
|
+
attr_accessor :exitstatus, :stdout, :stderr
|
41
|
+
|
42
|
+
# params:
|
43
|
+
# - command: binary to execute
|
44
|
+
# - args: optional cmd line arguments (exec array)
|
45
|
+
# - options:
|
46
|
+
# - b_shell: if true, run as /bin/sh -c '<command> [args]'
|
47
|
+
# - b_sudo: insert sudo if true
|
48
|
+
def initialize(command, args = nil, options =
|
49
|
+
{ :b_shell => true, :b_sudo => true })
|
50
|
+
@command = command
|
51
|
+
@args = array_or_nil_as_str(args)
|
52
|
+
@options = options
|
53
|
+
end
|
54
|
+
|
55
|
+
# block-style. Creates a LocalExecution object with
|
56
|
+
# given parameters, yields it into a given block.
|
57
|
+
# Params:
|
58
|
+
# +command+ Command string, usually the binary
|
59
|
+
# +args+ argument array
|
60
|
+
# +options+ option map (b_shell, b_sudo flags)
|
61
|
+
# Yields
|
62
|
+
# - LocalExecution object
|
63
|
+
def self.with(command, args = nil, options =
|
64
|
+
{ :b_shell => true, :b_sudo => true })
|
65
|
+
obj = LocalExecution.new command, args, options
|
66
|
+
yield obj
|
67
|
+
end
|
68
|
+
|
69
|
+
# constructs the single command line string from
|
70
|
+
# given parameters.
|
71
|
+
# Returns
|
72
|
+
# - Command line as [String]
|
73
|
+
def construct_command
|
74
|
+
cmd_arr = []
|
75
|
+
command_args = "#{@command} #{@args}".strip
|
76
|
+
sudo_str = (@options[:b_sudo] ? 'sudo ' : '')
|
77
|
+
if @options[:b_shell]
|
78
|
+
cmd_arr << '/bin/sh'
|
79
|
+
cmd_arr << '-c'
|
80
|
+
|
81
|
+
cmd_arr << "'#{sudo_str}#{command_args}'"
|
82
|
+
else
|
83
|
+
cmd_arr << "#{sudo_str}#{command_args}"
|
84
|
+
end
|
85
|
+
|
86
|
+
cmd_arr.join(' ').strip
|
87
|
+
end
|
88
|
+
|
89
|
+
# runs the command
|
90
|
+
# sets instance variables
|
91
|
+
# stdout, stderr, exitstatus
|
92
|
+
def run
|
93
|
+
cmd = construct_command
|
94
|
+
|
95
|
+
$log.debug "Executing #{cmd}"
|
96
|
+
@stdout = `#{cmd}`
|
97
|
+
@stderr = nil
|
98
|
+
@exitstatus = $CHILD_STATUS.exitstatus
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
# converts given +array_or_nil+ object to identity
|
104
|
+
# if array or an empty array if nil
|
105
|
+
def array_or_nil_as_str(array_or_nil)
|
106
|
+
(array_or_nil || []).join(' ')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,45 @@
|
|
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
|
+
# Run validations on appgroup model part
|
10
|
+
class AppGroupValidation < ValidationBase
|
11
|
+
# run validation steps on appgroup elements
|
12
|
+
# returns
|
13
|
+
# - nil, results in errors of ValidationBase
|
14
|
+
def run_validations
|
15
|
+
return unless @project.element?('appgroups')
|
16
|
+
|
17
|
+
appgroups_attached_to_zones?
|
18
|
+
controllers_valid?
|
19
|
+
end
|
20
|
+
|
21
|
+
# ensures that all application groups are attached to a zone
|
22
|
+
def appgroups_attached_to_zones?
|
23
|
+
objects_attached_to_zones? 'appgroups'
|
24
|
+
end
|
25
|
+
|
26
|
+
# ensures that all application groups have a known controller
|
27
|
+
def controllers_valid?
|
28
|
+
@project.get_element('appgroups').each do |appgroup_name, appgroup_data|
|
29
|
+
controller_data = appgroup_data[:controller]
|
30
|
+
type = 'appgroup'
|
31
|
+
name = appgroup_name
|
32
|
+
if !controller_data
|
33
|
+
mark('Appgroup is not attached to a zone', type, name)
|
34
|
+
else
|
35
|
+
type = controller_data[:type]
|
36
|
+
mark('Appgroup controller does not have a type', type, name) unless type && type.size > 0
|
37
|
+
|
38
|
+
known_types = %w(fig)
|
39
|
+
mark('Appgroup controller has an unkown type (#{type})',
|
40
|
+
type, name) unless known_types.include?(type)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|