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,129 @@
|
|
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
|
+
# WireCLI
|
10
|
+
# thor command line class
|
11
|
+
#
|
12
|
+
class WireCLI < Thor
|
13
|
+
# treat as non-thor commands
|
14
|
+
no_commands do
|
15
|
+
# pre-build array of available commands
|
16
|
+
def initialize_commands
|
17
|
+
@wire_commands = Wire::WireCommands.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply_globals
|
21
|
+
options[:nocolor] && Rainbow.enabled = false
|
22
|
+
options[:debug] && $log.level = Logger::DEBUG
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# set global options
|
28
|
+
class_option :nocolor, { :desc => 'Disable coloring in output',
|
29
|
+
:required => false, :banner => '' }
|
30
|
+
class_option :debug, { :desc => 'Show debug output', :banner => '' }
|
31
|
+
|
32
|
+
desc 'init [TARGETDIR]', 'create an inital model in TARGETDIR'
|
33
|
+
long_desc <<-LONGDESC
|
34
|
+
Creates TARGETDIR if necessary, opens an interactive
|
35
|
+
console dialog about the model to be created.
|
36
|
+
|
37
|
+
Writes model files to TARGETDIR.
|
38
|
+
LONGDESC
|
39
|
+
# init method, run init in +target_dir+
|
40
|
+
def init(target_dir = '.')
|
41
|
+
initialize_commands
|
42
|
+
apply_globals
|
43
|
+
@wire_commands.run_init(target_dir)
|
44
|
+
end
|
45
|
+
|
46
|
+
# validate
|
47
|
+
#
|
48
|
+
desc 'validate [TARGETDIR]',
|
49
|
+
'read model in TARGETDIR and validate its consistency'
|
50
|
+
long_desc <<-LONGDESC
|
51
|
+
Given a model in TARGETDIR, the validate commands reads
|
52
|
+
the model and runs consistency checks against the model elements,
|
53
|
+
i.e. if every network is attached to a zone.
|
54
|
+
LONGDESC
|
55
|
+
# validate method, run model validation in +target_dir+
|
56
|
+
def validate(target_dir = '.')
|
57
|
+
initialize_commands
|
58
|
+
apply_globals
|
59
|
+
@wire_commands.run_validate(target_dir)
|
60
|
+
end
|
61
|
+
|
62
|
+
# verify
|
63
|
+
#
|
64
|
+
desc 'verify [TARGETDIR]',
|
65
|
+
'read model in TARGETDIR and verify against current system'
|
66
|
+
long_desc <<-LONGDESC
|
67
|
+
Given a model in TARGETDIR, the verify commands reads
|
68
|
+
the model and runs checks to see if everthing in the model
|
69
|
+
is present in the current system.
|
70
|
+
LONGDESC
|
71
|
+
# verify method, run model verification in +target_dir+
|
72
|
+
def verify(target_dir = '.')
|
73
|
+
initialize_commands
|
74
|
+
apply_globals
|
75
|
+
@wire_commands.run_verify(target_dir)
|
76
|
+
end
|
77
|
+
|
78
|
+
# spec
|
79
|
+
#
|
80
|
+
desc 'spec [TARGETDIR]',
|
81
|
+
'read model in TARGETDIR and create a serverspec' \
|
82
|
+
'specification example in TARGETDIR'
|
83
|
+
long_desc <<-LONGDESC
|
84
|
+
Given a model in TARGETDIR, the verify commands reads
|
85
|
+
the model. For each element it creates a serverspec-conformant
|
86
|
+
describe()-block in a spec file.
|
87
|
+
Writes spec helpers if they do not exist.
|
88
|
+
LONGDESC
|
89
|
+
option :run, { :desc => 'Automatically run serverspec', :banner => '', :type => :boolean }
|
90
|
+
# spec method, generate and optionally run serverspec in +target_dir+
|
91
|
+
def spec(target_dir = '.')
|
92
|
+
initialize_commands
|
93
|
+
apply_globals
|
94
|
+
@wire_commands.run_spec(target_dir, options[:run])
|
95
|
+
end
|
96
|
+
|
97
|
+
# up
|
98
|
+
#
|
99
|
+
desc 'up [TARGETDIR]',
|
100
|
+
'read model in TARGETDIR and bring system up' \
|
101
|
+
'according to model elements in TARGETDIR'
|
102
|
+
long_desc <<-LONGDESC
|
103
|
+
Given a model in TARGETDIR, the up commands reads
|
104
|
+
the model. Each model element is brought to live.
|
105
|
+
LONGDESC
|
106
|
+
# up method, bring model in +target_dir+ up
|
107
|
+
def up(target_dir = '.')
|
108
|
+
initialize_commands
|
109
|
+
apply_globals
|
110
|
+
@wire_commands.run_up(target_dir)
|
111
|
+
end
|
112
|
+
|
113
|
+
# down
|
114
|
+
#
|
115
|
+
desc 'down [TARGETDIR]',
|
116
|
+
'read model in TARGETDIR and bring system down' \
|
117
|
+
'according to model elements in TARGETDIR'
|
118
|
+
long_desc <<-LONGDESC
|
119
|
+
Given a model in TARGETDIR, the up commands reads
|
120
|
+
the model. Each model element is stopped and removed.
|
121
|
+
LONGDESC
|
122
|
+
# down method, bring model in +target_dir+ down
|
123
|
+
def down(target_dir = '.')
|
124
|
+
initialize_commands
|
125
|
+
apply_globals
|
126
|
+
@wire_commands.run_down(target_dir)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/wire/cli.rb
ADDED
@@ -0,0 +1,139 @@
|
|
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
|
+
# (Empty) Base command
|
10
|
+
class BaseCommand
|
11
|
+
# +params+ object and +project+ to operate upon
|
12
|
+
attr_accessor :params, :project
|
13
|
+
|
14
|
+
# returns the state object
|
15
|
+
def state
|
16
|
+
State.instance
|
17
|
+
end
|
18
|
+
|
19
|
+
# debugs a single line state
|
20
|
+
def dump_state
|
21
|
+
$log.debug "State: [#{state.to_pretty_s}]"
|
22
|
+
end
|
23
|
+
|
24
|
+
# +outputs+ writes a message to stdout, in given style
|
25
|
+
#
|
26
|
+
# params:
|
27
|
+
# +type+ 1st column as type, i.e. "model" or "network" or "OK"
|
28
|
+
# +msg+ message to print
|
29
|
+
# +style+ coloring etc, supported:
|
30
|
+
# :plain (default), :err (red), :ok (green)
|
31
|
+
# return
|
32
|
+
# - nil
|
33
|
+
#
|
34
|
+
# :reek:ControlParameter
|
35
|
+
def outputs(type, msg, style = :plain)
|
36
|
+
line = "#{type}> #{msg}"
|
37
|
+
line = line.color(:red) if (style == :err) || (style == :error)
|
38
|
+
line = line.color(:green) if style == :ok
|
39
|
+
line = line.color(:cyan) if style == :ok2
|
40
|
+
|
41
|
+
$stdout.puts line
|
42
|
+
end
|
43
|
+
|
44
|
+
# Issues a warning if we do not run as root.
|
45
|
+
def check_user
|
46
|
+
(ENV['USER'] != 'root') &&
|
47
|
+
$log.warn("Not running as root. Make sure user #{ENV['USER']} has sudo configured.")
|
48
|
+
end
|
49
|
+
|
50
|
+
# retrieve all objects of given +type_name+ in
|
51
|
+
# zone (by +zone_name+)
|
52
|
+
# returns:
|
53
|
+
# [Hash] of model subpart with elements of given type
|
54
|
+
def objects_in_zone(type_name, zone_name)
|
55
|
+
return {} unless @project.element?(type_name)
|
56
|
+
objects = @project.get_element type_name || {}
|
57
|
+
objects.select { |_, data| data[:zone] == zone_name }
|
58
|
+
end
|
59
|
+
|
60
|
+
# runs the command, according to parameters
|
61
|
+
# loads project into @project, calls run_on_project
|
62
|
+
# (to be defined in subclasses)
|
63
|
+
# params
|
64
|
+
# +params+ command parameter map, example key i.e. "target_dir"
|
65
|
+
def run(params = {})
|
66
|
+
check_user
|
67
|
+
|
68
|
+
@params = params
|
69
|
+
target_dir = @params[:target_dir]
|
70
|
+
outputs 'model', "Loading model in #{target_dir}"
|
71
|
+
|
72
|
+
# load it first
|
73
|
+
begin
|
74
|
+
loader = ProjectYamlLoader.new
|
75
|
+
@project = loader.load_project(target_dir)
|
76
|
+
|
77
|
+
# try to load state file.
|
78
|
+
state.project = @project
|
79
|
+
handle_state_load
|
80
|
+
|
81
|
+
run_on_project
|
82
|
+
|
83
|
+
$log.debug? && pp(@project)
|
84
|
+
|
85
|
+
handle_state_save
|
86
|
+
|
87
|
+
rescue => load_execption
|
88
|
+
$stderr.puts "Unable to process project model in #{target_dir}"
|
89
|
+
$log.debug? && puts(load_execption.inspect)
|
90
|
+
$log.debug? && puts(load_execption.backtrace)
|
91
|
+
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
# if the hostip is not in cidr, take netmask
|
98
|
+
# from network entry, add to hostip
|
99
|
+
# params:
|
100
|
+
# +host_ip+ i.e. 192.168.10.1
|
101
|
+
# +network_data+ network data object, to take netmask from :network element
|
102
|
+
def ensure_hostip_netmask(host_ip, network_data)
|
103
|
+
return host_ip if host_ip =~ /[0-9\.]+\/[0-9]+/
|
104
|
+
|
105
|
+
match_data = network_data[:network].match(/[0-9\.]+(\/[0-9]+)/)
|
106
|
+
if match_data && match_data.size >= 2
|
107
|
+
netmask = match_data[1]
|
108
|
+
$log.debug "Adding netmask #{netmask} to host-ip #{host_ip}"
|
109
|
+
return "#{host_ip}#{netmask}"
|
110
|
+
else
|
111
|
+
$log.error "host-ip #{host_ip} is missing netmask, and none given in network."
|
112
|
+
return host_ip
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# Save state to state file
|
119
|
+
def handle_state_save
|
120
|
+
# dump state
|
121
|
+
$log.debug? && dump_state
|
122
|
+
state.save
|
123
|
+
rescue => save_exception
|
124
|
+
$stderr.puts "Error saving state, #{save_exception}"
|
125
|
+
$log.debug? && puts(save_exception.inspect)
|
126
|
+
$log.debug? && puts(save_exception.backtrace)
|
127
|
+
end
|
128
|
+
|
129
|
+
def handle_state_load
|
130
|
+
state.load
|
131
|
+
# dump state
|
132
|
+
$log.debug? && dump_state
|
133
|
+
rescue => load_exception
|
134
|
+
$stderr.puts "Error loading state, #{load_exception}"
|
135
|
+
$log.debug? && puts(load_exception.inspect)
|
136
|
+
$log.debug? && puts(load_exception.backtrace)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
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
|
+
# DownCommand reads yaml, parses model elements
|
10
|
+
# and brings all defined model elements "down", that is
|
11
|
+
# stopping and removing bridges, containers etc.
|
12
|
+
# - :target_dir
|
13
|
+
class DownCommand < UpDownCommand
|
14
|
+
# allow to get access to handler object
|
15
|
+
attr_reader :handler
|
16
|
+
|
17
|
+
# initializes DownCommand, creates handler
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
@handler = DownCommandHandler.new
|
21
|
+
end
|
22
|
+
|
23
|
+
# run in given zone:
|
24
|
+
# returns:
|
25
|
+
# - bool: true if successful, false otherwise
|
26
|
+
def run_on_zone(zone_name)
|
27
|
+
b_result = true
|
28
|
+
|
29
|
+
networks = @project.get_element('networks')
|
30
|
+
|
31
|
+
# select appgroups in this zone and take them down first
|
32
|
+
appgroups_in_zone = objects_in_zone('appgroups', zone_name)
|
33
|
+
appgroups_in_zone.each do |appgroup_name, appgroup_data|
|
34
|
+
$log.debug("Processing appgroup \'#{appgroup_name}\'")
|
35
|
+
|
36
|
+
# process network attachments
|
37
|
+
zone_networks = objects_in_zone('networks', zone_name)
|
38
|
+
success = handler.handle_network_attachments(zone_name, zone_networks,
|
39
|
+
appgroup_name, appgroup_data,
|
40
|
+
@project.target_dir)
|
41
|
+
b_result &= success
|
42
|
+
|
43
|
+
# then take down containers
|
44
|
+
success = handler.handle_appgroup(zone_name,
|
45
|
+
appgroup_name, appgroup_data,
|
46
|
+
@project.target_dir)
|
47
|
+
b_result &= success
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# select networks in current zone only
|
52
|
+
networks_in_zone = UpDownCommand.get_networks_for_zone(networks, zone_name)
|
53
|
+
networks_in_zone.each do |network_name, network_data|
|
54
|
+
$log.debug("Bringing down network #{network_name}")
|
55
|
+
|
56
|
+
# if we have dhcp, unconfigure dnsmasq
|
57
|
+
b_result &= default_handle_dhcp(zone_name, network_name, network_data, @handler)
|
58
|
+
|
59
|
+
# if we have a host ip on that bridge, take it down first
|
60
|
+
b_result &= default_handle_hostip(network_name, network_data, @handler)
|
61
|
+
|
62
|
+
# we should have a bridge with that name.
|
63
|
+
success = @handler.handle_bridge(network_name)
|
64
|
+
b_result &= success
|
65
|
+
end
|
66
|
+
b_result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,199 @@
|
|
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
|
+
# implements handle_xxx methods for DownCommand
|
10
|
+
# rubocop:disable ClassLength
|
11
|
+
class DownCommandHandler < BaseCommand
|
12
|
+
# take bridge down
|
13
|
+
def handle_bridge(bridge_name)
|
14
|
+
bridge_resource = Wire::Resource::ResourceFactory.instance.create(:ovsbridge, bridge_name)
|
15
|
+
if bridge_resource.down?
|
16
|
+
outputs 'DOWN', "Bridge #{bridge_name} already down.", :ok2
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
|
20
|
+
bridge_resource.down
|
21
|
+
if bridge_resource.down?
|
22
|
+
outputs 'DOWN', "Bridge #{bridge_name} down/removed.", :ok
|
23
|
+
state.update(:bridge, bridge_name, :down)
|
24
|
+
else
|
25
|
+
outputs 'DOWN', "Error bringing down bridge #{bridge_name}.", :err
|
26
|
+
b_result = false
|
27
|
+
end
|
28
|
+
|
29
|
+
b_result
|
30
|
+
end
|
31
|
+
|
32
|
+
# remove ip from bridge interface
|
33
|
+
def handle_hostip(bridge_name, hostip)
|
34
|
+
b_result = true
|
35
|
+
|
36
|
+
bridge_resource = Wire::Resource::ResourceFactory.instance.create(:ovsbridge, bridge_name)
|
37
|
+
if bridge_resource.down?
|
38
|
+
outputs 'DOWN', "Bridge #{bridge_name} already down, will not care about ip", :ok2
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
42
|
+
# we should have a bridge with that name.
|
43
|
+
hostip_resource = Wire::Resource::ResourceFactory
|
44
|
+
.instance.create(:bridgeip, hostip, bridge_name)
|
45
|
+
if hostip_resource.down?
|
46
|
+
outputs 'DOWN', "IP #{hostip} on bridge #{bridge_name} already down.", :ok2
|
47
|
+
return
|
48
|
+
end
|
49
|
+
|
50
|
+
hostip_resource.down
|
51
|
+
if hostip_resource.down?
|
52
|
+
outputs 'DOWN', "IP #{hostip} on bridge #{bridge_name} down/removed.", :ok
|
53
|
+
state.update(:hostip, hostip, :down)
|
54
|
+
else
|
55
|
+
outputs 'DOWN', "Error taking down ip #{hostip} on bridge #{bridge_name}.", :err
|
56
|
+
|
57
|
+
b_result = false
|
58
|
+
end
|
59
|
+
|
60
|
+
b_result
|
61
|
+
end
|
62
|
+
|
63
|
+
# unconfigures dnsmasq for dhcp
|
64
|
+
# params:
|
65
|
+
# +zone_name+ name of zone
|
66
|
+
# +network_name+ name of network (and bridge)
|
67
|
+
# +network+ network entry
|
68
|
+
# +address_start+ start of address range (i.e.192.168.10.10)
|
69
|
+
# +address_end+ end of dhcp address range (i.e.192.168.10.100)
|
70
|
+
# Returns
|
71
|
+
# - [Bool] true if dhcp setup is valid
|
72
|
+
def handle_dhcp(zone_name, network_name, network_entry, address_start, address_end)
|
73
|
+
resource_dhcp = Wire::Resource::ResourceFactory
|
74
|
+
.instance.create(:dhcpconfig, "wire__#{zone_name}", network_name,
|
75
|
+
network_entry, address_start, address_end)
|
76
|
+
if resource_dhcp.down?
|
77
|
+
outputs 'DOWN', "dnsmasq/dhcp config on network \'#{network_name}\' is already down.", :ok2
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
|
81
|
+
resource_dhcp.down
|
82
|
+
if resource_dhcp.down?
|
83
|
+
outputs 'DOWN', "dnsmasq/dhcp config on network \'#{network_name}\' is down.", :ok
|
84
|
+
state.update(:dnsmasq, network_name, :down)
|
85
|
+
return true
|
86
|
+
else
|
87
|
+
outputs 'DOWN', 'Error unconfiguring dnsmasq/dhcp ' \
|
88
|
+
"config on network \'#{network_name}\'.", :err
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# take the appgroups' controller and directs methods to
|
94
|
+
# it. First checks if appgroup is down. If so, ok. If not, take it down
|
95
|
+
# and ensure that it's down
|
96
|
+
# Params:
|
97
|
+
# +zone_name+:: Name of zone
|
98
|
+
# +appgroup_name+:: Name of Appgroup
|
99
|
+
# +appgroup_entry+:: Appgroup data from model
|
100
|
+
# +target_dir+:: Target directory (where fig file is located)
|
101
|
+
def handle_appgroup(zone_name, appgroup_name, appgroup_entry, target_dir)
|
102
|
+
# get path
|
103
|
+
controller_entry = appgroup_entry[:controller]
|
104
|
+
|
105
|
+
if controller_entry[:type] == 'fig'
|
106
|
+
return handle_appgroup__fig(zone_name, appgroup_name, appgroup_entry, target_dir)
|
107
|
+
end
|
108
|
+
|
109
|
+
$log.error "Appgroup not handled for zone #{zone_name}, " \
|
110
|
+
"unknown controller type #{controller_entry[:type]}"
|
111
|
+
false
|
112
|
+
end
|
113
|
+
|
114
|
+
# implement appgroup handling for fig controller
|
115
|
+
# Params:
|
116
|
+
# +zone_name+:: Name of zone
|
117
|
+
# +appgroup_name+:: Name of Appgroup
|
118
|
+
# +appgroup_entry+:: Appgroup data from model
|
119
|
+
# +target_dir+:: Target directory (where fig file is located)
|
120
|
+
def handle_appgroup__fig(zone_name, appgroup_name, appgroup_entry, target_dir)
|
121
|
+
# get path
|
122
|
+
controller_entry = appgroup_entry[:controller]
|
123
|
+
|
124
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
125
|
+
|
126
|
+
resource_fig = Wire::Resource::ResourceFactory
|
127
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
128
|
+
|
129
|
+
if resource_fig.down?
|
130
|
+
outputs 'DOWN', "appgroup \'#{appgroup_name}\' for zone #{zone_name} is already down.", :ok2
|
131
|
+
return true
|
132
|
+
end
|
133
|
+
|
134
|
+
b_result = false
|
135
|
+
resource_fig.down
|
136
|
+
if resource_fig.down?
|
137
|
+
outputs 'DOWN', "appgroup \'#{appgroup_name}\' for zone #{zone_name} is down.", :ok
|
138
|
+
state.update(:appgroup, appgroup_name, :down)
|
139
|
+
b_result = true
|
140
|
+
else
|
141
|
+
outputs 'DOWN', "Error taking down appgroup \'#{appgroup_name}\' for zone #{zone_name}.",
|
142
|
+
:err
|
143
|
+
b_result = false
|
144
|
+
end
|
145
|
+
|
146
|
+
b_result
|
147
|
+
end
|
148
|
+
|
149
|
+
# detaches networks to containers of appgroup
|
150
|
+
# Params:
|
151
|
+
# ++_zone_name++: Name of zone
|
152
|
+
# ++networks++: Array of networks names, what to attach
|
153
|
+
# ++appgroup_name++: Name of appgroup
|
154
|
+
# ++appgroup_entry++: appgroup hash
|
155
|
+
# ++target_dir++: project target dir
|
156
|
+
# Returns
|
157
|
+
# - [Bool] true if appgroup setup is ok
|
158
|
+
def handle_network_attachments(_zone_name, networks, appgroup_name,
|
159
|
+
appgroup_entry, target_dir)
|
160
|
+
# query container ids of containers running here
|
161
|
+
# get path
|
162
|
+
controller_entry = appgroup_entry[:controller]
|
163
|
+
|
164
|
+
container_ids = []
|
165
|
+
|
166
|
+
if controller_entry[:type] == 'fig'
|
167
|
+
fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
|
168
|
+
|
169
|
+
resource_fig = Wire::Resource::ResourceFactory
|
170
|
+
.instance.create(:figadapter, "#{appgroup_name}", fig_path)
|
171
|
+
|
172
|
+
container_ids = resource_fig.up_ids || []
|
173
|
+
$log.debug "Got #{container_ids.size} container id(s) from adapter"
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
resource_nw = Wire::Resource::ResourceFactory
|
178
|
+
.instance.create(:networkinjection, appgroup_name, networks.keys, container_ids)
|
179
|
+
if resource_nw.down?
|
180
|
+
outputs 'DOWN', "appgroup \'#{appgroup_name}\' network " \
|
181
|
+
'attachments already detached.', :ok2
|
182
|
+
state.update(:appgroup, appgroup_name, :down)
|
183
|
+
return true
|
184
|
+
else
|
185
|
+
resource_nw.down
|
186
|
+
if resource_nw.down?
|
187
|
+
outputs 'DOWN', "appgroup \'#{appgroup_name}\' detached " \
|
188
|
+
"networks #{networks.keys.join(',')}.", :ok
|
189
|
+
state.update(:appgroup, appgroup_name, :down)
|
190
|
+
return true
|
191
|
+
else
|
192
|
+
outputs 'DOWN', "Error detaching networks to appgroup \'#{appgroup_name}\'.",
|
193
|
+
:err
|
194
|
+
return false
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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
|
+
# Init Command opens an interactive console dialog
|
10
|
+
# for initializing a model structure
|
11
|
+
# params:
|
12
|
+
# - :target_dir
|
13
|
+
class InitCommand < BaseCommand
|
14
|
+
def run(params = {})
|
15
|
+
puts "Initializing model in #{params[:target_dir]}"
|
16
|
+
|
17
|
+
model_data = {}
|
18
|
+
zone_data = {}
|
19
|
+
network_data = {}
|
20
|
+
model_data.store :zones, zone_data
|
21
|
+
model_data.store :networks, network_data
|
22
|
+
|
23
|
+
zone_names = InitInteractive.ask_for_zone_names
|
24
|
+
if zone_names.size == 0
|
25
|
+
$stderr.puts 'ERROR: must at least have one zone'
|
26
|
+
exit Wire.cli_exitcode(:init_bad_input)
|
27
|
+
end
|
28
|
+
zone_names.each do |zone_name|
|
29
|
+
|
30
|
+
zone_detail = {
|
31
|
+
:desc => 'Enter a short description here',
|
32
|
+
:long_desc => 'Enter a longer description here'
|
33
|
+
}
|
34
|
+
|
35
|
+
zone_data.store zone_name, zone_detail
|
36
|
+
|
37
|
+
networks = InitInteractive.ask_for_network_in_zone zone_name
|
38
|
+
networks.each do |network_name|
|
39
|
+
|
40
|
+
network_details = InitInteractive.ask_detail_data_for_network network_name
|
41
|
+
network_details.merge!({ :zone => zone_name })
|
42
|
+
network_data.store network_name, network_details
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# write resulting model to file
|
47
|
+
export_model_file(model_data, params[:target_dir])
|
48
|
+
end
|
49
|
+
|
50
|
+
# Given a model structure and a target dir, this method
|
51
|
+
# ensures that targetdir exists and structure contents
|
52
|
+
# are written to individual files
|
53
|
+
def export_model_file(model_data, target_dir)
|
54
|
+
puts "Target dir is #{target_dir}"
|
55
|
+
|
56
|
+
# ensure target_dir exists
|
57
|
+
if File.exist?(target_dir)
|
58
|
+
if File.directory?(target_dir)
|
59
|
+
$stdout.puts "Writing output to #{target_dir}"
|
60
|
+
else
|
61
|
+
$stderr.puts "ERROR: Target dir #{target_dir} exists, " \
|
62
|
+
'but is not a directory.'
|
63
|
+
exit Wire.cli_exitcode(:init_dir_error)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
FileUtils.mkdir_p(target_dir)
|
68
|
+
rescue => excpt
|
69
|
+
$stderr.puts "ERROR: Unable to create #{target_dir}: #{excpt}"
|
70
|
+
exit Wire.cli_exitcode(:init_dir_error)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
[:zones, :networks].each do |element_sym|
|
75
|
+
element = model_data[element_sym]
|
76
|
+
export_element_file element_sym, element, target_dir
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# exports an element part of the model to a single file
|
81
|
+
# in target_dir, as yaml.
|
82
|
+
def export_element_file(element_sym, element_data, target_dir)
|
83
|
+
filename = File.join(target_dir, "#{element_sym}.yaml")
|
84
|
+
open(filename, 'w') do |out_file|
|
85
|
+
out_file.puts(element_data.to_yaml)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|