testlab 0.2.1 → 0.3.0
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.
- data/.gitignore +0 -1
- data/Gemfile +0 -2
- data/bin/tl +28 -41
- data/lib/testlab/container/actions.rb +35 -0
- data/lib/testlab/container/class_methods.rb +7 -1
- data/lib/testlab/container/generators.rb +11 -0
- data/lib/testlab/container/interface.rb +10 -17
- data/lib/testlab/container/lifecycle.rb +14 -2
- data/lib/testlab/container/lxc.rb +24 -10
- data/lib/testlab/container/method_missing.rb +3 -1
- data/lib/testlab/container/status.rb +46 -2
- data/lib/testlab/container.rb +52 -2
- data/lib/testlab/interface.rb +45 -0
- data/lib/testlab/monkeys.rb +4 -0
- data/lib/testlab/network/actions.rb +1 -1
- data/lib/testlab/network/bind.rb +2 -2
- data/lib/testlab/network/class_methods.rb +1 -1
- data/lib/testlab/network/status.rb +12 -4
- data/lib/testlab/network.rb +2 -1
- data/lib/testlab/node/actions.rb +45 -0
- data/lib/testlab/node/bind.rb +7 -5
- data/lib/testlab/node/lifecycle.rb +3 -5
- data/lib/testlab/node/status.rb +1 -2
- data/lib/testlab/node.rb +1 -2
- data/lib/testlab/providers/vagrant.rb +1 -1
- data/lib/testlab/provisioners/shell.rb +8 -4
- data/lib/testlab/utility/misc.rb +49 -0
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +123 -31
- data/spec/support/Labfile +8 -9
- data/testlab.gemspec +1 -0
- metadata +24 -5
- data/lib/testlab/router.rb +0 -66
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/bin/tl
CHANGED
@@ -3,39 +3,15 @@ require 'gli'
|
|
3
3
|
require 'testlab'
|
4
4
|
|
5
5
|
include GLI::App
|
6
|
+
include TestLab::Utility::Misc
|
6
7
|
|
7
|
-
|
8
|
+
version TestLab::VERSION
|
8
9
|
|
9
|
-
|
10
|
+
program_desc %(A framework for building lightweight virtual infrastructure using LXC)
|
11
|
+
program_long_desc %(Program Long Description)
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# desc 'Describe some flag here'
|
15
|
-
# default_value 'the default'
|
16
|
-
# arg_name 'The name of the argument'
|
17
|
-
# flag [:f,:flagname]
|
18
|
-
|
19
|
-
# desc 'Manage the test lab'
|
20
|
-
# arg_name 'Describe arguments to lab here'
|
21
|
-
# command :lab do |c|
|
22
|
-
|
23
|
-
# # c.desc 'Describe a switch to lab'
|
24
|
-
# # c.switch :s
|
25
|
-
|
26
|
-
# # c.desc 'Describe a flag to lab'
|
27
|
-
# # c.default_value 'default'
|
28
|
-
# # c.flag :f
|
29
|
-
# # c.action do |global_options,options,args|
|
30
|
-
|
31
|
-
# # # Your command logic here
|
32
|
-
|
33
|
-
# # # If you have any errors, just raise them
|
34
|
-
# # # raise "that command made no sense"
|
35
|
-
|
36
|
-
# # puts "lab command ran"
|
37
|
-
# # end
|
38
|
-
# end
|
13
|
+
sort_help :manually
|
14
|
+
default_command :help
|
39
15
|
|
40
16
|
desc 'Create the test lab'
|
41
17
|
command :create do |create|
|
@@ -90,7 +66,8 @@ desc 'Manage nodes'
|
|
90
66
|
arg_name 'Describe arguments to node here'
|
91
67
|
command :node do |c|
|
92
68
|
|
93
|
-
c.desc 'Node ID'
|
69
|
+
c.desc 'Node ID or Name'
|
70
|
+
c.arg_name 'node'
|
94
71
|
c.flag [:i, :id]
|
95
72
|
|
96
73
|
c.desc 'Open an SSH console to a node'
|
@@ -117,7 +94,8 @@ desc 'Manage containers'
|
|
117
94
|
arg_name 'Describe arguments to container here'
|
118
95
|
command :container do |c|
|
119
96
|
|
120
|
-
c.desc 'Container ID'
|
97
|
+
c.desc 'Container ID or Name'
|
98
|
+
c.arg_name 'container'
|
121
99
|
c.flag [:i, :id]
|
122
100
|
|
123
101
|
c.desc 'Open an SSH console to a container'
|
@@ -170,7 +148,7 @@ pre do |global,command,options,args|
|
|
170
148
|
@ui = ZTK::UI.new(:logger => @logger)
|
171
149
|
@testlab = TestLab.new(:ui => @ui)
|
172
150
|
|
173
|
-
message =
|
151
|
+
message = format_message("TestLab v#{TestLab::VERSION} Loaded".black.bold)
|
174
152
|
@testlab.ui.stdout.puts(message)
|
175
153
|
|
176
154
|
true
|
@@ -183,16 +161,25 @@ post do |global,command,options,args|
|
|
183
161
|
end
|
184
162
|
|
185
163
|
on_error do |exception|
|
186
|
-
|
187
|
-
|
188
|
-
@ui.stderr.puts(["EXCEPTION:".red.bold, exception.inspect.red].join(' '))
|
164
|
+
@ui.stderr.puts
|
165
|
+
@ui.stderr.puts(format_message(["ERROR:".red, exception.message.red.bold].join(' ')))
|
189
166
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
167
|
+
case exception
|
168
|
+
when GLI::BadCommandLine, GLI::UnknownCommand, GLI::UnknownCommandArgument, GLI::UnknownGlobalArgument then
|
169
|
+
command_regex = /Command '([\w]+)' /
|
170
|
+
command = exception.message.scan(command_regex).flatten.first
|
171
|
+
|
172
|
+
commands[:help] and commands[:help].execute({}, {}, (command.nil? ? [] : [command.to_s]))
|
194
173
|
|
195
|
-
|
174
|
+
false
|
175
|
+
else
|
176
|
+
@logger.fatal { exception.inspect }
|
177
|
+
exception.backtrace.each do |line|
|
178
|
+
@logger.logdev.write("#{line}\n")
|
179
|
+
end
|
180
|
+
|
181
|
+
false
|
182
|
+
end
|
196
183
|
end
|
197
184
|
|
198
185
|
exit run(ARGV)
|
@@ -4,6 +4,11 @@ class TestLab
|
|
4
4
|
module Actions
|
5
5
|
|
6
6
|
# Create the container
|
7
|
+
#
|
8
|
+
# Builds the configuration for the container and sends a request to the
|
9
|
+
# LXC sub-system to create the container.
|
10
|
+
#
|
11
|
+
# @return [Boolean] True if successful.
|
7
12
|
def create
|
8
13
|
@ui.logger.debug { "Container Create: #{self.id} " }
|
9
14
|
|
@@ -22,33 +27,63 @@ class TestLab
|
|
22
27
|
|
23
28
|
self.lxc.create(*create_args)
|
24
29
|
end
|
30
|
+
|
31
|
+
true
|
25
32
|
end
|
26
33
|
|
27
34
|
# Destroy the container
|
35
|
+
#
|
36
|
+
# Sends a request to the LXC sub-system to destroy the container.
|
37
|
+
#
|
38
|
+
# @return [Boolean] True if successful.
|
28
39
|
def destroy
|
29
40
|
@ui.logger.debug { "Container Destroy: #{self.id} " }
|
30
41
|
|
31
42
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Destroy', :red)) do
|
32
43
|
self.lxc.destroy
|
33
44
|
end
|
45
|
+
|
46
|
+
true
|
34
47
|
end
|
35
48
|
|
36
49
|
# Start the container
|
50
|
+
#
|
51
|
+
# Sends a request to the LXC sub-system to bring the container online.
|
52
|
+
#
|
53
|
+
# @return [Boolean] True if successful.
|
37
54
|
def up
|
38
55
|
@ui.logger.debug { "Container Up: #{self.id} " }
|
39
56
|
|
57
|
+
(self.lxc.state == :not_created) and raise ContainerError, "We can not online a non-existant container!"
|
58
|
+
|
40
59
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
41
60
|
self.lxc.start
|
61
|
+
self.lxc.wait(:running)
|
62
|
+
|
63
|
+
(self.lxc.state != :running) and raise ContainerError, "The container failed to online!"
|
42
64
|
end
|
65
|
+
|
66
|
+
true
|
43
67
|
end
|
44
68
|
|
45
69
|
# Stop the container
|
70
|
+
#
|
71
|
+
# Sends a request to the LXC sub-system to take the container offline.
|
72
|
+
#
|
73
|
+
# @return [Boolean] True if successful.
|
46
74
|
def down
|
47
75
|
@ui.logger.debug { "Container Down: #{self.id} " }
|
48
76
|
|
77
|
+
(self.lxc.state == :not_created) and raise ContainerError, "We can not offline a non-existant container!"
|
78
|
+
|
49
79
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Down', :red)) do
|
50
80
|
self.lxc.stop
|
81
|
+
self.lxc.wait(:stopped)
|
82
|
+
|
83
|
+
(self.lxc.state != :stopped) and raise ContainerError, "The container failed to offline!"
|
51
84
|
end
|
85
|
+
|
86
|
+
true
|
52
87
|
end
|
53
88
|
|
54
89
|
end
|
@@ -3,11 +3,17 @@ class TestLab
|
|
3
3
|
|
4
4
|
module ClassMethods
|
5
5
|
|
6
|
+
# Container domain list
|
7
|
+
#
|
8
|
+
# Returns an array of strings containing all the unique domains defined
|
9
|
+
# across all containers
|
10
|
+
#
|
11
|
+
# @return [Array<String>] A unique array of all defined domain names.
|
6
12
|
def domains
|
7
13
|
self.all.map do |container|
|
8
14
|
container.domain ||= container.node.labfile.config[:domain]
|
9
15
|
container.domain
|
10
|
-
end.compact
|
16
|
+
end.compact.uniq
|
11
17
|
end
|
12
18
|
|
13
19
|
end
|
@@ -3,6 +3,12 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Generators
|
5
5
|
|
6
|
+
# Generate IP address
|
7
|
+
#
|
8
|
+
# Generates an RFC compliant private IP address.
|
9
|
+
#
|
10
|
+
# @return [String] A random, private IP address in the 192.168.0.1/24
|
11
|
+
# range.
|
6
12
|
def generate_ip
|
7
13
|
octets = [ 192..192,
|
8
14
|
168..168,
|
@@ -15,6 +21,11 @@ class TestLab
|
|
15
21
|
ip.join(".")
|
16
22
|
end
|
17
23
|
|
24
|
+
# Generate MAC address
|
25
|
+
#
|
26
|
+
# Generates an RFC compliant private MAC address.
|
27
|
+
#
|
28
|
+
# @return [String] A random, private MAC address.
|
18
29
|
def generate_mac
|
19
30
|
digits = [ %w(0),
|
20
31
|
%w(0),
|
@@ -3,24 +3,17 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Interface
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
# Returns a BIND PTR record
|
17
|
-
def ptr
|
18
|
-
TestLab::Utility.ptr(self.primary_interface.last[:ip])
|
19
|
-
end
|
20
|
-
|
6
|
+
# Container primary interface
|
7
|
+
#
|
8
|
+
# Returns the primary interface for the container. If the container has
|
9
|
+
# multiple interfaces, this is based on which ever interface is marked
|
10
|
+
# with the primary flag. If the container only has one interface, then
|
11
|
+
# it is returned.
|
12
|
+
#
|
13
|
+
# @return [TestLab::Interface] The primary interface for the container.
|
21
14
|
def primary_interface
|
22
|
-
if self.interfaces.any?{ |i
|
23
|
-
self.interfaces.find{ |i
|
15
|
+
if self.interfaces.any?{ |i| i.primary == true }
|
16
|
+
self.interfaces.find{ |i| i.primary == true }
|
24
17
|
else
|
25
18
|
self.interfaces.first
|
26
19
|
end
|
@@ -3,7 +3,13 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Lifecycle
|
5
5
|
|
6
|
-
#
|
6
|
+
# Setup the container
|
7
|
+
#
|
8
|
+
# Attempts to setup the container. We first create the container, then
|
9
|
+
# attempt to bring it online. Afterwards the containers provisioner is
|
10
|
+
# called.
|
11
|
+
#
|
12
|
+
# @return [Boolean] True if successful.
|
7
13
|
def setup
|
8
14
|
@ui.logger.debug { "Container Setup: #{self.id} " }
|
9
15
|
|
@@ -19,7 +25,13 @@ class TestLab
|
|
19
25
|
true
|
20
26
|
end
|
21
27
|
|
22
|
-
#
|
28
|
+
# Teardown the container
|
29
|
+
#
|
30
|
+
# Attempts to teardown the container. We first call the provisioner
|
31
|
+
# teardown method defined for the container, if any. Next we attempt to
|
32
|
+
# offline the container. Afterwards the container is destroy.
|
33
|
+
#
|
34
|
+
# @return [Boolean] True if successful.
|
23
35
|
def teardown
|
24
36
|
@ui.logger.debug { "Container Teardown: #{self.id} " }
|
25
37
|
|
@@ -3,7 +3,9 @@ class TestLab
|
|
3
3
|
|
4
4
|
module LXC
|
5
5
|
|
6
|
-
#
|
6
|
+
# LXC::Container object
|
7
|
+
#
|
8
|
+
# Returns a *LXC::Container* class instance configured for this container.
|
7
9
|
#
|
8
10
|
# @return [LXC] An instance of LXC::Container configured for this
|
9
11
|
# container.
|
@@ -11,12 +13,19 @@ class TestLab
|
|
11
13
|
@lxc ||= self.node.lxc.container(self.id)
|
12
14
|
end
|
13
15
|
|
14
|
-
# SSH
|
16
|
+
# ZTK:SSH object
|
17
|
+
#
|
18
|
+
# Returns a *ZTK:SSH* class instance configured for this container.
|
19
|
+
#
|
20
|
+
# @return [ZTK::SSH] An instance of ZTK::SSH configured for this
|
21
|
+
# container.
|
15
22
|
def ssh(options={})
|
16
23
|
self.node.container_ssh(self, options)
|
17
24
|
end
|
18
25
|
|
19
26
|
# Does the container exist?
|
27
|
+
#
|
28
|
+
# @return [Boolean] True if the containers exists, false otherwise.
|
20
29
|
def exists?
|
21
30
|
@ui.logger.debug { "Container Exists?: #{self.id} " }
|
22
31
|
|
@@ -25,7 +34,7 @@ class TestLab
|
|
25
34
|
|
26
35
|
# Returns arguments for lxc-create based on our distro
|
27
36
|
#
|
28
|
-
# @return [Array] An array of arguments for lxc-create
|
37
|
+
# @return [Array<String>] An array of arguments for lxc-create
|
29
38
|
def create_args
|
30
39
|
case self.distro.downcase
|
31
40
|
when "ubuntu" then
|
@@ -49,21 +58,26 @@ class TestLab
|
|
49
58
|
end
|
50
59
|
end
|
51
60
|
|
61
|
+
# LXC Network Configuration
|
62
|
+
#
|
52
63
|
# Builds an array of hashes containing the lxc configuration options for
|
53
|
-
# our
|
64
|
+
# our network interfaces.
|
65
|
+
#
|
66
|
+
# @return [Array<Hash>] An array of hashes defining the containers
|
67
|
+
# interfaces for use in configuring LXC.
|
54
68
|
def build_lxc_network_conf(interfaces)
|
55
69
|
networks = Array.new
|
56
70
|
|
57
|
-
interfaces.each do |
|
71
|
+
interfaces.each do |interface|
|
58
72
|
networks << Hash[
|
59
73
|
'lxc.network.type' => :veth,
|
60
74
|
'lxc.network.flags' => :up,
|
61
|
-
'lxc.network.link' =>
|
62
|
-
'lxc.network.name' =>
|
63
|
-
'lxc.network.hwaddr' =>
|
64
|
-
'lxc.network.ipv4' =>
|
75
|
+
'lxc.network.link' => interface.network.bridge,
|
76
|
+
'lxc.network.name' => interface.name,
|
77
|
+
'lxc.network.hwaddr' => interface.mac,
|
78
|
+
'lxc.network.ipv4' => "#{interface.ip}/#{interface.cidr} #{interface.netmask}"
|
65
79
|
]
|
66
|
-
if (
|
80
|
+
if (interface.primary == true) || (interfaces.count == 1)
|
67
81
|
networks.last.merge!('lxc.network.ipv4.gateway' => :auto)
|
68
82
|
end
|
69
83
|
end
|
@@ -3,7 +3,9 @@ class TestLab
|
|
3
3
|
|
4
4
|
module MethodMissing
|
5
5
|
|
6
|
-
#
|
6
|
+
# Provisioner method handler
|
7
|
+
#
|
8
|
+
# Proxies missing methods to the containers defined provisioner, if any.
|
7
9
|
def method_missing(method_name, *method_args)
|
8
10
|
@ui.logger.debug { "CONTAINER METHOD MISSING: #{method_name.inspect}(#{method_args.inspect})" }
|
9
11
|
|
@@ -3,14 +3,54 @@ class TestLab
|
|
3
3
|
|
4
4
|
module Status
|
5
5
|
|
6
|
+
# Container IP
|
7
|
+
#
|
8
|
+
# Returns the IP of the container.
|
9
|
+
#
|
10
|
+
# @return [String] The containers IP address.
|
11
|
+
def ip
|
12
|
+
TestLab::Utility.ip(self.primary_interface.address)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Container CIDR
|
16
|
+
#
|
17
|
+
# Returns the CIDR of the container
|
18
|
+
#
|
19
|
+
# @return [Integer] The containers CIDR address.
|
20
|
+
def cidr
|
21
|
+
TestLab::Utility.cidr(self.primary_interface.address).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
# Container BIND PTR Record
|
25
|
+
#
|
26
|
+
# Returns a BIND reverse-DNS PTR record.
|
27
|
+
#
|
28
|
+
# @return [String] The containers ARPA PTR record.
|
29
|
+
def ptr
|
30
|
+
TestLab::Utility.ptr(self.primary_interface.address)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Container FQDN
|
34
|
+
#
|
35
|
+
# Returns the FQDN for the container.
|
36
|
+
#
|
37
|
+
# @return [String] The containers FQDN.
|
6
38
|
def fqdn
|
7
39
|
self.domain ||= self.node.labfile.config[:domain]
|
8
40
|
|
9
41
|
[self.id, self.domain].join('.')
|
10
42
|
end
|
11
43
|
|
44
|
+
# Container Status
|
45
|
+
#
|
46
|
+
# Returns a hash of status information for the container.
|
47
|
+
#
|
48
|
+
# @return [Hash] A hash of status information for the container.
|
12
49
|
def status
|
13
|
-
interfaces = self.interfaces.collect
|
50
|
+
interfaces = self.interfaces.collect do |interface|
|
51
|
+
"#{interface.network_id}:#{interface.name}:#{interface.ip}/#{interface.cidr}"
|
52
|
+
end.join(', ')
|
53
|
+
|
14
54
|
{
|
15
55
|
:id => self.id,
|
16
56
|
:fqdn => self.fqdn,
|
@@ -23,7 +63,11 @@ class TestLab
|
|
23
63
|
}
|
24
64
|
end
|
25
65
|
|
26
|
-
# State
|
66
|
+
# Container State
|
67
|
+
#
|
68
|
+
# What state the container is in.
|
69
|
+
#
|
70
|
+
# @return [Symbol] A symbol indicating the state of the container.
|
27
71
|
def state
|
28
72
|
self.lxc.state
|
29
73
|
end
|
data/lib/testlab/container.rb
CHANGED
@@ -5,8 +5,59 @@ class TestLab
|
|
5
5
|
|
6
6
|
# Container Class
|
7
7
|
#
|
8
|
+
# This class represents the TestLab Container DSL object.
|
9
|
+
#
|
10
|
+
# @example A simple container definition with a single interface:
|
11
|
+
# container "server-west-1" do
|
12
|
+
# domain "west.zone"
|
13
|
+
#
|
14
|
+
# distro "ubuntu"
|
15
|
+
# release "precise"
|
16
|
+
#
|
17
|
+
# interface do
|
18
|
+
# network_id :west
|
19
|
+
# name :eth0
|
20
|
+
# address '10.11.0.254/16'
|
21
|
+
# mac '00:00:5e:48:e9:6f'
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @example Multiple interfaces can be defined as well:
|
26
|
+
# container "dual-nic" do
|
27
|
+
# distro "ubuntu"
|
28
|
+
# release "precise"
|
29
|
+
#
|
30
|
+
# interface do
|
31
|
+
# network_id :east
|
32
|
+
# name :eth0
|
33
|
+
# address '10.10.0.200/16'
|
34
|
+
# mac '00:00:5e:63:b5:9f'
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# interface do
|
38
|
+
# network_id :west
|
39
|
+
# primary true
|
40
|
+
# name :eth1
|
41
|
+
# address '10.11.0.200/16'
|
42
|
+
# mac '00:00:5e:08:63:df'
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# The operating system is determined by the *distro* and *release* attributes.
|
47
|
+
# The hostname (container ID) is passed as a parameter to the container call.
|
48
|
+
# A *domain* may additionally be specified (overriding the global domain, if
|
49
|
+
# set). If the *domain* attributes is omited, then the global domain is use,
|
50
|
+
# again only if it is set. The hostname (container ID) and the domain will be
|
51
|
+
# joined together to form the FQDN of the container.
|
52
|
+
#
|
53
|
+
# @see TestLab::Interface
|
54
|
+
#
|
8
55
|
# @author Zachary Patten <zachary@jovelabs.net>
|
9
56
|
class Container < ZTK::DSL::Base
|
57
|
+
|
58
|
+
# An array of symbols of the various keys in our status hash.
|
59
|
+
#
|
60
|
+
# @see TestLab::Container::Status
|
10
61
|
STATUS_KEYS = %w(node_id id fqdn state distro release interfaces provisioner).map(&:to_sym)
|
11
62
|
|
12
63
|
# Sub-Modules
|
@@ -33,6 +84,7 @@ class TestLab
|
|
33
84
|
|
34
85
|
# Associations and Attributes
|
35
86
|
belongs_to :node, :class_name => 'TestLab::Node'
|
87
|
+
has_many :interfaces, :class_name => 'TestLab::Interface'
|
36
88
|
|
37
89
|
attribute :provisioner
|
38
90
|
attribute :config
|
@@ -43,8 +95,6 @@ class TestLab
|
|
43
95
|
attribute :passwd
|
44
96
|
attribute :keys
|
45
97
|
|
46
|
-
attribute :interfaces
|
47
|
-
|
48
98
|
attribute :distro
|
49
99
|
attribute :release
|
50
100
|
attribute :arch
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class TestLab
|
2
|
+
|
3
|
+
# Interface Error Class
|
4
|
+
class InterfaceError < TestLabError; end
|
5
|
+
|
6
|
+
# Interface Class
|
7
|
+
#
|
8
|
+
# @author Zachary Patten <zachary@jovelabs.net>
|
9
|
+
class Interface < ZTK::DSL::Base
|
10
|
+
|
11
|
+
# Associations and Attributes
|
12
|
+
belongs_to :container, :class_name => 'TestLab::Container'
|
13
|
+
belongs_to :network, :class_name => 'TestLab::Network'
|
14
|
+
|
15
|
+
attribute :address
|
16
|
+
attribute :mac
|
17
|
+
attribute :name
|
18
|
+
|
19
|
+
attribute :primary
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super(*args)
|
23
|
+
|
24
|
+
@ui = TestLab.ui
|
25
|
+
end
|
26
|
+
|
27
|
+
def ip
|
28
|
+
TestLab::Utility.ip(self.address)
|
29
|
+
end
|
30
|
+
|
31
|
+
def cidr
|
32
|
+
TestLab::Utility.cidr(self.address)
|
33
|
+
end
|
34
|
+
|
35
|
+
def netmask
|
36
|
+
TestLab::Utility.netmask(self.address)
|
37
|
+
end
|
38
|
+
|
39
|
+
def ptr
|
40
|
+
TestLab::Utility.ptr(self.address)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -26,7 +26,7 @@ class TestLab
|
|
26
26
|
@ui.logger.debug { "Network Up: #{self.id} " }
|
27
27
|
|
28
28
|
please_wait(:ui => @ui, :message => format_object_action(self, 'Up', :green)) do
|
29
|
-
self.node.ssh.exec(%(sudo ifconfig #{self.bridge} #{self.ip} up), :silence => true, :ignore_exit_status => true)
|
29
|
+
self.node.ssh.exec(%(sudo ifconfig #{self.bridge} #{self.ip} netmask #{self.netmask} up), :silence => true, :ignore_exit_status => true)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
data/lib/testlab/network/bind.rb
CHANGED
@@ -5,12 +5,12 @@ class TestLab
|
|
5
5
|
|
6
6
|
# BIND PTR Record
|
7
7
|
def ptr
|
8
|
-
TestLab::Utility.ptr(self.
|
8
|
+
TestLab::Utility.ptr(self.address)
|
9
9
|
end
|
10
10
|
|
11
11
|
# Returns the ARPA network
|
12
12
|
def arpa
|
13
|
-
TestLab::Utility.arpa(self.
|
13
|
+
TestLab::Utility.arpa(self.address)
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
@@ -5,7 +5,7 @@ class TestLab
|
|
5
5
|
|
6
6
|
# Network status
|
7
7
|
def status
|
8
|
-
interface = "#{bridge}:#{
|
8
|
+
interface = "#{bridge}:#{self.address}"
|
9
9
|
{
|
10
10
|
:id => self.id,
|
11
11
|
:node_id => self.node.id,
|
@@ -17,19 +17,27 @@ class TestLab
|
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
20
|
+
def ip
|
21
|
+
TestLab::Utility.ip(self.address)
|
22
|
+
end
|
23
|
+
|
24
|
+
def cidr
|
25
|
+
TestLab::Utility.cidr(self.address)
|
26
|
+
end
|
27
|
+
|
20
28
|
# Returns the network mask
|
21
29
|
def netmask
|
22
|
-
TestLab::Utility.netmask(self.
|
30
|
+
TestLab::Utility.netmask(self.address)
|
23
31
|
end
|
24
32
|
|
25
33
|
# Returns the network address
|
26
34
|
def network
|
27
|
-
TestLab::Utility.network(self.
|
35
|
+
TestLab::Utility.network(self.address)
|
28
36
|
end
|
29
37
|
|
30
38
|
# Returns the broadcast address
|
31
39
|
def broadcast
|
32
|
-
TestLab::Utility.broadcast(self.
|
40
|
+
TestLab::Utility.broadcast(self.address)
|
33
41
|
end
|
34
42
|
|
35
43
|
# Network Bridge State
|
data/lib/testlab/network.rb
CHANGED
@@ -27,10 +27,11 @@ class TestLab
|
|
27
27
|
|
28
28
|
# Associations and Attributes
|
29
29
|
belongs_to :node, :class_name => 'TestLab::Node'
|
30
|
+
has_many :interfaces, :class_name => 'TestLab::Interface'
|
30
31
|
|
32
|
+
attribute :address
|
31
33
|
attribute :bridge
|
32
34
|
|
33
|
-
attribute :ip
|
34
35
|
attribute :config
|
35
36
|
|
36
37
|
|