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,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
|