rubyipmi 0.8.1 → 0.9.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.
- checksums.yaml +4 -4
- data/Gemfile +5 -8
- data/README.md +92 -27
- data/Rakefile +1 -6
- data/VERSION +1 -1
- data/lib/rubyipmi.rb +69 -30
- data/lib/rubyipmi/commands/basecommand.rb +16 -18
- data/lib/rubyipmi/freeipmi/commands/basecommand.rb +2 -4
- data/lib/rubyipmi/freeipmi/commands/bmc.rb +7 -0
- data/lib/rubyipmi/freeipmi/commands/bmcconfig.rb +10 -0
- data/lib/rubyipmi/freeipmi/commands/bmcdevice.rb +1 -0
- data/lib/rubyipmi/freeipmi/commands/bmcinfo.rb +0 -3
- data/lib/rubyipmi/freeipmi/commands/chassis.rb +1 -0
- data/lib/rubyipmi/freeipmi/commands/chassisconfig.rb +0 -2
- data/lib/rubyipmi/freeipmi/commands/fru.rb +0 -1
- data/lib/rubyipmi/freeipmi/commands/lan.rb +22 -23
- data/lib/rubyipmi/freeipmi/commands/sensors.rb +8 -7
- data/lib/rubyipmi/freeipmi/connection.rb +14 -19
- data/lib/rubyipmi/freeipmi/errorcodes.rb +0 -1
- data/lib/rubyipmi/ipmitool/commands/basecommand.rb +0 -3
- data/lib/rubyipmi/ipmitool/commands/bmc.rb +8 -0
- data/lib/rubyipmi/ipmitool/commands/chassis.rb +1 -0
- data/lib/rubyipmi/ipmitool/commands/fru.rb +0 -7
- data/lib/rubyipmi/ipmitool/connection.rb +12 -13
- data/lib/rubyipmi/ipmitool/errorcodes.rb +2 -1
- data/rubyipmi.gemspec +21 -14
- data/spec/integration/bmc_spec.rb +9 -10
- data/spec/integration/chassis_config_spec.rb +6 -8
- data/spec/integration/chassis_spec.rb +3 -3
- data/spec/integration/connection_spec.rb +16 -15
- data/spec/integration/fru_spec.rb +6 -7
- data/spec/integration/lan_spec.rb +21 -34
- data/spec/integration/power_spec.rb +5 -5
- data/spec/integration/rubyipmi_spec.rb +63 -9
- data/spec/integration/sensor_spec.rb +7 -8
- data/spec/spec_helper.rb +10 -7
- data/spec/unit/freeipmi/bmc-info_spec.rb +5 -6
- data/spec/unit/freeipmi/bmc_spec.rb +8 -9
- data/spec/unit/freeipmi/connection_spec.rb +41 -23
- data/spec/unit/freeipmi/errorcodes_spec.rb +4 -10
- data/spec/unit/freeipmi/fru_spec.rb +15 -16
- data/spec/unit/freeipmi/sensors_spec.rb +17 -15
- data/spec/unit/ipmitool/bmc_spec.rb +11 -12
- data/spec/unit/ipmitool/connection_spec.rb +43 -21
- data/spec/unit/ipmitool/errorcodes_spec.rb +5 -4
- data/spec/unit/ipmitool/fru_spec.rb +15 -15
- data/spec/unit/ipmitool/lan_spec.rb +16 -15
- data/spec/unit/ipmitool/sensors_spec.rb +16 -15
- data/spec/unit/rubyipmi_spec.rb +6 -6
- metadata +64 -24
- data/README.rdoc +0 -18
@@ -44,6 +44,7 @@ module Rubyipmi::Ipmitool
|
|
44
44
|
end
|
45
45
|
|
46
46
|
else
|
47
|
+
logger.debug("Device with name: #{device} is not a valid boot device for host #{options["hostname"]}") if logger
|
47
48
|
raise "Device with name: #{device} is not a valid boot device for host #{options["hostname"]}"
|
48
49
|
end
|
49
50
|
return bootstatus
|
@@ -6,7 +6,6 @@ module Rubyipmi::Ipmitool
|
|
6
6
|
|
7
7
|
DEFAULT_FRU = 'builtin_fru_device'
|
8
8
|
|
9
|
-
|
10
9
|
def initialize(opts = ObservableHash.new)
|
11
10
|
super("ipmitool", opts)
|
12
11
|
@list = {}
|
@@ -101,9 +100,6 @@ module Rubyipmi::Ipmitool
|
|
101
100
|
|
102
101
|
end
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
103
|
class FruData < Hash
|
108
104
|
|
109
105
|
def name
|
@@ -138,8 +134,5 @@ module Rubyipmi::Ipmitool
|
|
138
134
|
def method_missing(method, *args, &block)
|
139
135
|
self.fetch(method.to_s, nil)
|
140
136
|
end
|
141
|
-
|
142
137
|
end
|
143
|
-
|
144
|
-
|
145
138
|
end
|
@@ -12,11 +12,10 @@ module Rubyipmi
|
|
12
12
|
|
13
13
|
class Connection
|
14
14
|
|
15
|
-
attr_accessor :options
|
15
|
+
attr_accessor :options
|
16
16
|
|
17
17
|
|
18
18
|
def initialize(user, pass, host, opts)
|
19
|
-
@debug = opts[:debug]
|
20
19
|
@options = Rubyipmi::ObservableHash.new
|
21
20
|
raise("Must provide a host to connect to") unless host
|
22
21
|
@options["H"] = host
|
@@ -32,6 +31,11 @@ module Rubyipmi
|
|
32
31
|
@options['I'] = drivers_map[opts[:driver]] unless drivers_map[opts[:driver]].nil?
|
33
32
|
end
|
34
33
|
|
34
|
+
# test the connection to ensure we can at least make a single call
|
35
|
+
def connection_works?
|
36
|
+
status = ! (bmc.info.nil? || bmc.info.empty? )
|
37
|
+
end
|
38
|
+
|
35
39
|
def drivers_map
|
36
40
|
{
|
37
41
|
'lan15' => 'lan',
|
@@ -62,18 +66,13 @@ module Rubyipmi
|
|
62
66
|
|
63
67
|
def get_diag
|
64
68
|
data = {}
|
65
|
-
data[
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
if @bmc
|
73
|
-
data['bmc_info'] = @bmc.info
|
74
|
-
end
|
69
|
+
data[:provider] = provider
|
70
|
+
data[:frus] = fru.getfrus
|
71
|
+
data[:sensors] = sensors.getsensors
|
72
|
+
data[:bmc_info] = bmc.info
|
73
|
+
data[:version] = bmc.version
|
74
|
+
data
|
75
75
|
end
|
76
|
-
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
@@ -5,7 +5,8 @@ module Rubyipmi
|
|
5
5
|
@@codes = {
|
6
6
|
"Authentication type NONE not supported\nAuthentication type NONE not supported\n" +
|
7
7
|
"Error: Unable to establish LAN session\nGet Device ID command failed\n" => {"I" => "lanplus"},
|
8
|
-
"Authentication type NONE not supported" => {"I" => "lanplus"}
|
8
|
+
"Authentication type NONE not supported" => {"I" => "lanplus"},
|
9
|
+
"Error: Unable to establish LAN session\nGet Device ID command failed\n" => {"I" => "lanplus"}
|
9
10
|
|
10
11
|
|
11
12
|
}
|
data/rubyipmi.gemspec
CHANGED
@@ -2,28 +2,26 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: rubyipmi 0.
|
5
|
+
# stub: rubyipmi 0.9.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "rubyipmi"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.9.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Corey Osman"]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2015-03-09"
|
15
15
|
s.description = "Provides a library for controlling IPMI devices using pure ruby code"
|
16
16
|
s.email = "corey@logicminds.biz"
|
17
17
|
s.extra_rdoc_files = [
|
18
18
|
"LICENSE.txt",
|
19
|
-
"README.md"
|
20
|
-
"README.rdoc"
|
19
|
+
"README.md"
|
21
20
|
]
|
22
21
|
s.files = [
|
23
22
|
"Gemfile",
|
24
23
|
"LICENSE.txt",
|
25
24
|
"README.md",
|
26
|
-
"README.rdoc",
|
27
25
|
"RELEASE_NOTES.md",
|
28
26
|
"Rakefile",
|
29
27
|
"VERSION",
|
@@ -104,35 +102,44 @@ Gem::Specification.new do |s|
|
|
104
102
|
"spec/vagrant.pub"
|
105
103
|
]
|
106
104
|
s.homepage = "http://github.com/logicminds/rubyipmi"
|
107
|
-
s.licenses = ["
|
108
|
-
s.rubygems_version = "2.
|
105
|
+
s.licenses = ["LGPLv2.1"]
|
106
|
+
s.rubygems_version = "2.4.5"
|
109
107
|
s.summary = "A ruby wrapper for ipmi command line tools that supports ipmitool and freeipmi"
|
110
108
|
|
111
109
|
if s.respond_to? :specification_version then
|
112
110
|
s.specification_version = 4
|
113
111
|
|
114
112
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
115
|
-
s.add_development_dependency(%q<rspec>, ["
|
113
|
+
s.add_development_dependency(%q<rspec>, ["~> 3.1"])
|
116
114
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
117
115
|
s.add_development_dependency(%q<bundler>, [">= 1.1.5"])
|
118
|
-
s.add_development_dependency(%q<jeweler>, ["~>
|
116
|
+
s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
|
119
117
|
s.add_development_dependency(%q<highline>, [">= 0"])
|
120
118
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
119
|
+
s.add_development_dependency(%q<coveralls>, [">= 0"])
|
120
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
121
|
+
s.add_development_dependency(%q<pry-rescue>, [">= 0"])
|
121
122
|
else
|
122
|
-
s.add_dependency(%q<rspec>, ["
|
123
|
+
s.add_dependency(%q<rspec>, ["~> 3.1"])
|
123
124
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
124
125
|
s.add_dependency(%q<bundler>, [">= 1.1.5"])
|
125
|
-
s.add_dependency(%q<jeweler>, ["~>
|
126
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
126
127
|
s.add_dependency(%q<highline>, [">= 0"])
|
127
128
|
s.add_dependency(%q<rake>, [">= 0"])
|
129
|
+
s.add_dependency(%q<coveralls>, [">= 0"])
|
130
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
131
|
+
s.add_dependency(%q<pry-rescue>, [">= 0"])
|
128
132
|
end
|
129
133
|
else
|
130
|
-
s.add_dependency(%q<rspec>, ["
|
134
|
+
s.add_dependency(%q<rspec>, ["~> 3.1"])
|
131
135
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
132
136
|
s.add_dependency(%q<bundler>, [">= 1.1.5"])
|
133
|
-
s.add_dependency(%q<jeweler>, ["~>
|
137
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
134
138
|
s.add_dependency(%q<highline>, [">= 0"])
|
135
139
|
s.add_dependency(%q<rake>, [">= 0"])
|
140
|
+
s.add_dependency(%q<coveralls>, [">= 0"])
|
141
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
142
|
+
s.add_dependency(%q<pry-rescue>, [">= 0"])
|
136
143
|
end
|
137
144
|
end
|
138
145
|
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
|
+
|
2
3
|
describe "Bmc" do
|
3
4
|
|
4
5
|
before :each do
|
@@ -11,27 +12,26 @@ describe "Bmc" do
|
|
11
12
|
end
|
12
13
|
|
13
14
|
it "creates a bmc object" do
|
14
|
-
@conn.bmc.
|
15
|
-
|
15
|
+
expect(@conn.bmc).not_to be_nil
|
16
16
|
end
|
17
17
|
|
18
18
|
it "options should change after calling info" do
|
19
19
|
before = @conn.bmc.options.clone
|
20
20
|
info = @conn.bmc.info
|
21
21
|
after = @conn.bmc.options.clone
|
22
|
-
before.length.
|
22
|
+
expect(before.length).to be < after.length
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should retrun a max retry count' do
|
26
|
-
@conn.bmc.max_retry_count.
|
26
|
+
expect(@conn.bmc.max_retry_count).to be > 0
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should reset the bmc device" do
|
30
|
-
@conn.bmc.reset('cold').
|
30
|
+
expect(@conn.bmc.reset('cold')).not_to be_nil
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should reset the bmc device warmly" do
|
34
|
-
@conn.bmc.reset('warm').
|
34
|
+
expect(@conn.bmc.reset('warm')).not_to be_nil
|
35
35
|
end
|
36
36
|
|
37
37
|
it "reset should fail when type is wrong" do
|
@@ -39,11 +39,10 @@ describe "Bmc" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "is able to retrieve the bmc info" do
|
42
|
-
@conn.bmc.info.
|
42
|
+
expect(@conn.bmc.info).not_to be_nil
|
43
43
|
end
|
44
44
|
|
45
45
|
it "is able to retrieve the guid" do
|
46
|
-
@conn.bmc.guid.
|
46
|
+
expect(@conn.bmc.guid).not_to be_nil
|
47
47
|
end
|
48
|
-
|
49
48
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
|
+
|
2
3
|
|
3
4
|
describe "Chassis Config" do
|
4
5
|
|
@@ -12,19 +13,19 @@ describe "Chassis Config" do
|
|
12
13
|
end
|
13
14
|
|
14
15
|
it "test to set booting from PXE" do
|
15
|
-
@conn.chassis.config.bootpxe.
|
16
|
+
expect(@conn.chassis.config.bootpxe).to eq(true)
|
16
17
|
end
|
17
18
|
|
18
19
|
it "test to set booting from Disk" do
|
19
|
-
@conn.chassis.config.bootdisk.
|
20
|
+
expect(@conn.chassis.config.bootdisk).to eq(true)
|
20
21
|
end
|
21
22
|
|
22
23
|
it "test to set booting from Cdrom" do
|
23
|
-
@conn.chassis.config.bootcdrom.
|
24
|
+
expect(@conn.chassis.config.bootcdrom).to eq(true)
|
24
25
|
end
|
25
26
|
|
26
27
|
it "test to set booting from bios" do
|
27
|
-
@conn.chassis.config.bootbios.
|
28
|
+
expect(@conn.chassis.config.bootbios).to eq(true)
|
28
29
|
end
|
29
30
|
|
30
31
|
it "test to set boot persistent value" do
|
@@ -34,7 +35,4 @@ describe "Chassis Config" do
|
|
34
35
|
it "test to checkout the entire chassis config" do
|
35
36
|
|
36
37
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
38
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Chassis" do
|
4
4
|
|
@@ -14,13 +14,13 @@ describe "Chassis" do
|
|
14
14
|
it "test to turn uid light on for 5 seconds" do
|
15
15
|
value = @conn.chassis.identify(true, 5)
|
16
16
|
sleep(6)
|
17
|
-
value.
|
17
|
+
expect(value).to eq(true)
|
18
18
|
end
|
19
19
|
|
20
20
|
it "test to turn uid light on then off" do
|
21
21
|
@conn.chassis.identify(true)
|
22
22
|
sleep(2)
|
23
|
-
@conn.chassis.identify(false).
|
23
|
+
expect(@conn.chassis.identify(false)).to eq(true)
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
@@ -1,35 +1,36 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
|
+
|
2
3
|
describe "Connection" do
|
3
4
|
|
4
5
|
before :each do
|
5
6
|
user ||= ENV["ipmiuser"] || "admin"
|
6
7
|
pass ||= ENV["ipmipass"] || "password"
|
7
|
-
host ||= ENV["ipmihost"] || "
|
8
|
+
host ||= ENV["ipmihost"] || "192.168.1.16"
|
8
9
|
provider ||= ENV["ipmiprovider"] || "ipmitool"
|
9
10
|
@conn = Rubyipmi.connect(user, pass, host, provider)
|
10
|
-
|
11
11
|
end
|
12
12
|
|
13
13
|
it "creates a new object" do
|
14
|
-
@conn.
|
15
|
-
|
14
|
+
expect(@conn).to be_truthy
|
16
15
|
end
|
17
16
|
|
18
17
|
it 'creates a bmc object' do
|
19
|
-
@conn.bmc.
|
20
|
-
puts "Last Call: #{@conn.bmc.lastcall.inspect}"
|
21
|
-
|
18
|
+
expect(@conn.bmc).to be_truthy
|
22
19
|
end
|
23
20
|
|
24
21
|
it 'creates a chassis object' do
|
25
|
-
@conn.chassis.
|
26
|
-
|
22
|
+
expect(@conn.chassis).to be_truthy
|
23
|
+
end
|
27
24
|
|
25
|
+
it 'can test the connection' do
|
26
|
+
expect(@conn.connection_works?).to eq true
|
28
27
|
end
|
29
28
|
|
29
|
+
it 'can get diag info' do
|
30
|
+
expect(@conn.get_diag.keys).to eq([:provider, :frus, :sensors, :bmc_info, :version])
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#end
|
33
|
+
it 'can get version info' do
|
34
|
+
expect(@conn.bmc.version).to match(/[\d\.]{3,4}/)
|
35
|
+
end
|
36
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'spec_helper'
|
3
2
|
describe "Fru" do
|
4
3
|
|
5
4
|
attr_accessor :provider
|
@@ -13,24 +12,24 @@ describe "Fru" do
|
|
13
12
|
end
|
14
13
|
|
15
14
|
it "test should return manufacturer" do
|
16
|
-
@conn.fru.manufacturer.
|
15
|
+
expect(@conn.fru.manufacturer).not_to be nil
|
17
16
|
|
18
17
|
end
|
19
18
|
|
20
19
|
it "test should return serial" do
|
21
|
-
@conn.fru.board_serial.
|
20
|
+
expect(@conn.fru.board_serial).not_to be nil
|
22
21
|
end
|
23
22
|
|
24
23
|
it "test should return product name" do
|
25
|
-
@conn.fru.model.
|
24
|
+
expect(@conn.fru.model).not_to be nil
|
26
25
|
end
|
27
26
|
|
28
27
|
it "test should return fru list" do
|
29
|
-
@conn.fru.list.length.
|
28
|
+
expect(@conn.fru.list.length).to be >= 1
|
30
29
|
end
|
31
30
|
|
32
31
|
it "test missing method with known good method" do
|
33
|
-
@conn.fru.chassis_type.
|
32
|
+
expect(@conn.fru.chassis_type).not_to be nil
|
34
33
|
end
|
35
34
|
|
36
35
|
it "test missing method with known bad method" do
|
@@ -1,63 +1,50 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'spec_helper'
|
3
2
|
describe "Lan" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
provider ||= ENV["ipmiprovider"] || "ipmitool"
|
10
|
-
@conn = Rubyipmi.connect(user, pass, host, provider)
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
before :all do
|
4
|
+
@user ||= ENV["ipmiuser"] || "admin"
|
5
|
+
@pass ||= ENV["ipmipass"] || "password"
|
6
|
+
@host ||= ENV["ipmihost"] || "10.0.1.16"
|
7
|
+
@provider ||= ENV["ipmiprovider"] || "ipmitool"
|
14
8
|
end
|
9
|
+
let(:conn) { Rubyipmi.connect(@user, @pass, @host, @provider) }
|
15
10
|
|
16
11
|
it "get ip address" do
|
17
|
-
|
12
|
+
expect(conn.bmc.lan.ip).to eq(@host)
|
18
13
|
end
|
19
14
|
|
20
15
|
it "get netmask" do
|
21
|
-
|
16
|
+
expect(conn.bmc.lan.netmask).to be_truthy
|
22
17
|
end
|
23
18
|
|
24
19
|
it "get gateway address" do
|
25
|
-
|
20
|
+
expect(conn.bmc.lan.gateway).to be_truthy
|
26
21
|
end
|
27
22
|
|
28
23
|
it "get mac address" do
|
29
|
-
|
24
|
+
expect(conn.bmc.lan.mac).to be_truthy
|
30
25
|
end
|
31
26
|
|
32
27
|
it "get static or dhcp" do
|
33
|
-
|
28
|
+
expect(conn.bmc.lan.dhcp?).to be_truthy
|
34
29
|
end
|
35
30
|
|
36
31
|
it "static should be opposite of dhcp" do
|
37
|
-
|
32
|
+
expect(conn.bmc.lan.dhcp? ).to_not eq(conn.bmc.lan.static?)
|
38
33
|
end
|
39
34
|
|
40
|
-
it "dhcp should be opposite of static" do
|
41
|
-
@conn.bmc.lan.static?.should_not == @conn.bmc.lan.dhcp?
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
35
|
it "should set gateway address" do
|
46
|
-
gw =
|
47
|
-
|
48
|
-
|
49
|
-
|
36
|
+
gw = conn.bmc.lan.gateway
|
37
|
+
conn.bmc.lan.gateway = gw
|
38
|
+
expect(conn.bmc.lan.gateway = gw).to be_truthy
|
50
39
|
end
|
51
40
|
|
52
41
|
it "should set netmask" do
|
53
|
-
netmask =
|
54
|
-
(
|
42
|
+
netmask = conn.bmc.lan.netmask
|
43
|
+
expect(conn.bmc.lan.netmask = netmask).to be_truthy
|
55
44
|
end
|
56
45
|
|
57
46
|
it "should set ip address" do
|
58
|
-
ip =
|
59
|
-
(
|
47
|
+
ip = conn.bmc.lan.ip
|
48
|
+
expect(conn.bmc.lan.ip = ip).to be_truthy
|
60
49
|
end
|
61
|
-
|
62
|
-
|
63
|
-
end
|
50
|
+
end
|