dewiring 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|