jupiter 0.0.1 → 0.8.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 +1 -0
- data/.rspec +2 -0
- data/Gemfile +1 -0
- data/README.md +323 -3
- data/bin/jupiter +7 -0
- data/config.yaml.example +37 -0
- data/jupiter.gemspec +10 -0
- data/lib/jupiter.rb +45 -1
- data/lib/jupiter/cli.rb +100 -0
- data/lib/jupiter/cli/colorizer.rb +44 -0
- data/lib/jupiter/cli/output.rb +355 -0
- data/lib/jupiter/configuration.rb +18 -0
- data/lib/jupiter/host.rb +257 -0
- data/lib/jupiter/nagios.rb +188 -0
- data/lib/jupiter/template.rb +39 -0
- data/lib/jupiter/uuid.rb +20 -0
- data/lib/jupiter/version.rb +1 -1
- data/lib/jupiter/virtualmachine.rb +123 -0
- data/spec/jupiter/cli_spec.rb +14 -0
- data/spec/jupiter/host_spec.rb +29 -0
- data/spec/jupiter/nagios_spec.rb +9 -0
- data/spec/jupiter/uuid_spec.rb +13 -0
- data/spec/jupiter/virtualmachine_spec.rb +12 -0
- data/spec/jupiter_spec.rb +7 -0
- data/spec/spec_helper.rb +14 -0
- metadata +129 -6
@@ -0,0 +1,39 @@
|
|
1
|
+
module Jupiter
|
2
|
+
class Template
|
3
|
+
|
4
|
+
attr_reader :location, :sshuser, :sshpass, :sshport, :host, :vmhost
|
5
|
+
|
6
|
+
def initialize(vmhost)
|
7
|
+
@vmhost = vmhost
|
8
|
+
@location = Jupiter.templates.fetch(:location)
|
9
|
+
@sshuser = Jupiter.templates.fetch(:sshuser)
|
10
|
+
@sshpass = Jupiter.templates.fetch(:sshpass)
|
11
|
+
@sshport = Jupiter.templates.fetch(:sshport)
|
12
|
+
@host = Jupiter.templates.fetch(:host)
|
13
|
+
end
|
14
|
+
|
15
|
+
def templates_list
|
16
|
+
template_list = ssh.exec!("ls #{@location}").to_s
|
17
|
+
close_ssh
|
18
|
+
array_of_templates= template_list.split("\n")
|
19
|
+
array_of_templates.select! { |x| x.include? '.tar.gz'}
|
20
|
+
end
|
21
|
+
|
22
|
+
def transfer_template(file, new_name)
|
23
|
+
ssh.exec!("scp -P #{@vmhost.sshport} #{location}/#{file}.tar.gz #{@vmhost.sshuser}@#{@vmhost.host}:#{@vmhost.vmpath}/")
|
24
|
+
close_ssh
|
25
|
+
@vmhost.setup_template(file, new_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def ssh
|
29
|
+
@ssh ||= Net::SSH.start(@host, @sshuser, password: @sshpass, port: @sshport)
|
30
|
+
end
|
31
|
+
|
32
|
+
def close_ssh
|
33
|
+
ssh.close
|
34
|
+
@ssh = nil
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/jupiter/uuid.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
module Jupiter
|
3
|
+
class UUID
|
4
|
+
|
5
|
+
def pad(text)
|
6
|
+
v = text * (1 + (64 / text.length))
|
7
|
+
v[0,64]
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate(text)
|
11
|
+
v = Digest::MD5.hexdigest(pad(text))
|
12
|
+
v.gsub!(/(.{2})(?=.)/, '\1 \2')
|
13
|
+
v.insert 23, "-"
|
14
|
+
v.slice!(24)
|
15
|
+
return v
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/jupiter/version.rb
CHANGED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Jupiter
|
2
|
+
class VirtualMachine
|
3
|
+
|
4
|
+
attr_reader :deploy_user, :deploy_pass, :sudo_user, :sudo_pass
|
5
|
+
attr_accessor :ip, :port
|
6
|
+
|
7
|
+
def initialize(ip, port)
|
8
|
+
@deploy_user = Jupiter.vmusers.fetch(:deploy_user)
|
9
|
+
@deploy_pass = Jupiter.vmusers.fetch(:deploy_pass)
|
10
|
+
@sudo_user = Jupiter.vmusers.fetch(:sudo_user)
|
11
|
+
@sudo_pass = Jupiter.vmusers.fetch(:sudo_pass)
|
12
|
+
self.ip = ip
|
13
|
+
self.port = port
|
14
|
+
end
|
15
|
+
|
16
|
+
def ssh_deploy
|
17
|
+
@ssh_deploy ||= Net::SSH.start(ip, @deploy_user, password: @deploy_pass, port: port)
|
18
|
+
end
|
19
|
+
|
20
|
+
def close_ssh_deploy
|
21
|
+
ssh_deploy.close
|
22
|
+
@ssh_deploy = nil
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_users_groups(user)
|
27
|
+
groups = ssh_deploy.exec!(%Q[id -nG #{user}]).chomp.split(/ /)
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_from_sudo_group(user)
|
31
|
+
result = ssh_deploy.exec!(%Q[sudo gpasswd -d #{user} sudo])
|
32
|
+
end
|
33
|
+
|
34
|
+
def rename_linux_guest(newname)
|
35
|
+
old_hostname = ssh_deploy.exec!("hostname").to_s.chomp
|
36
|
+
puts %Q[\nCurrent hostname is: #{old_hostname}\n]
|
37
|
+
ssh_deploy.exec!(%Q[sudo /bin/hostname #{newname}])
|
38
|
+
ssh_deploy.exec!(%Q[sudo /bin/chmod 666 /etc/hostname])
|
39
|
+
ssh_deploy.exec!(%Q[sudo /bin/echo '#{newname}' > /etc/hostname])
|
40
|
+
ssh_deploy.exec!(%Q[sudo /bin/chmod 644 /etc/hostname])
|
41
|
+
ssh_deploy.exec!(%Q[sudo /bin/chmod 666 /etc/hosts])
|
42
|
+
ssh_deploy.exec!(%Q[sudo /bin/sed -i 's|#{old_hostname}|#{newname}|g' /etc/hosts])
|
43
|
+
ssh_deploy.exec!(%Q[sudo /bin/chmod 644 /etc/hosts])
|
44
|
+
ssh_deploy.exec!(%Q[sudo /etc/init.d/hostname restart])
|
45
|
+
puts %Q[\nNew hostname is....]
|
46
|
+
puts ssh_deploy.exec!("hostname")
|
47
|
+
close_ssh_deploy
|
48
|
+
puts %Q[\nFinished changing hostname.]
|
49
|
+
end
|
50
|
+
|
51
|
+
def resize_lvm_volume_step_1
|
52
|
+
partitions = read_output_lines('sudo fdisk -l /dev/sda')
|
53
|
+
lvm_partition = detect_lvm_partition(partitions)
|
54
|
+
lvm_partition_number = lvm_partition.tr!('^0-9', '')
|
55
|
+
cylinders = detect_cylinders(partitions)
|
56
|
+
|
57
|
+
ssh_deploy.exec!(%Q[sudo /sbin/fdisk /dev/sda]) do |channel, stream, data|
|
58
|
+
channel.send_data(%Q[p\n])
|
59
|
+
channel.send_data(%Q[d\n])
|
60
|
+
channel.send_data(%Q[#{lvm_partition_number}\n])
|
61
|
+
channel.send_data(%Q[n\n])
|
62
|
+
channel.send_data(%Q[p\n])
|
63
|
+
channel.send_data(%Q[#{lvm_partition_number}\n])
|
64
|
+
channel.send_data(%Q[\n])
|
65
|
+
channel.send_data(%Q[\n])
|
66
|
+
channel.send_data(%Q[t\n])
|
67
|
+
channel.send_data(%Q[#{lvm_partition_number}\n])
|
68
|
+
channel.send_data(%Q[8e\n])
|
69
|
+
channel.send_data(%Q[w\n])
|
70
|
+
end
|
71
|
+
close_ssh_deploy
|
72
|
+
result = "\nThe system needs to reboot to read the new partition table. Please wait...\n"
|
73
|
+
# VM must be rebooted before moving on to step 2.
|
74
|
+
end
|
75
|
+
|
76
|
+
def resize_lvm_volume_step_2
|
77
|
+
partitions = read_output_lines('sudo fdisk -l /dev/sda')
|
78
|
+
lvm_partition = detect_lvm_partition(partitions)
|
79
|
+
pvs = ssh_deploy.exec!(%Q[sudo pvs])
|
80
|
+
pvresize = ssh_deploy.exec!(%Q[sudo pvresize #{lvm_partition}])
|
81
|
+
vgs = ssh_deploy.exec!(%Q[sudo vgs])
|
82
|
+
logical_vol = detect_lvm_group_path
|
83
|
+
lvextend = ssh_deploy.exec!(%Q[sudo lvextend -l +100%FREE #{logical_vol}])
|
84
|
+
resize2fs = ssh_deploy.exec!(%Q[sudo resize2fs #{logical_vol}])
|
85
|
+
close_ssh_deploy
|
86
|
+
result = "\n#{pvresize}\n\n#{vgs}\n\n#{lvextend}\n\n#{resize2fs}\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
def detect_lvm_group_path
|
90
|
+
df_output = read_output_lines('df -h')
|
91
|
+
lvm_path = array_element(df_output, '/dev/mapper/')
|
92
|
+
raise CantFindLogicalVolPathError.new("Can't detect path to logical volume where the root partition resides.") if lvm_path.kind_of?(Array)
|
93
|
+
return lvm_path.split[0]
|
94
|
+
end
|
95
|
+
|
96
|
+
def detect_lvm_partition(fdisk_output)
|
97
|
+
lvm_entry = array_element(fdisk_output, '8e Linux LVM')
|
98
|
+
raise InvalidLVMError.new("No LVM partition detected.") if lvm_entry.kind_of?(Array)
|
99
|
+
return lvm_entry.split[0]
|
100
|
+
end
|
101
|
+
|
102
|
+
def detect_cylinders(fdisk_output)
|
103
|
+
cylinder_entry = array_element(fdisk_output, '255 heads, 63 sectors')
|
104
|
+
raise InvalidCylindersError.new("There was an error retrieving the cylinders information.") if cylinder_entry.kind_of?(Array)
|
105
|
+
seperated_entries = cylinder_entry.split(',')
|
106
|
+
cylinder_count = array_element(seperated_entries, 'cylinders')
|
107
|
+
return cylinder_count.tr!('^.0-9', '')
|
108
|
+
end
|
109
|
+
|
110
|
+
def read_output_lines(command)
|
111
|
+
output = ssh_deploy.exec!(command).to_s
|
112
|
+
output.split("\n")
|
113
|
+
end
|
114
|
+
|
115
|
+
def array_element(array, some_string)
|
116
|
+
array.each { |x| return x.to_s if x.include? some_string }
|
117
|
+
end
|
118
|
+
|
119
|
+
class InvalidLVMError < StandardError; end
|
120
|
+
class InvalidCylindersError < StandardError; end
|
121
|
+
class CantFindLogicalVolPathError < StandardError; end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Jupiter::Input do
|
4
|
+
|
5
|
+
it "is a class" do
|
6
|
+
expect(Jupiter::Input).to be_a(Class)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can clean a file name" do
|
10
|
+
file = Jupiter::Input.new.clean_filename('This is a filename &%$!12()LOL')
|
11
|
+
expect(file).to eq('This-is-a-filename-12LOL')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Jupiter::Host do
|
4
|
+
|
5
|
+
let(:options) { {:name => 'TestHost', :vmpath => '/vmfs/test_path', :host => '192.168.11.11', :sshport => '22', :sshuser => 'TestUser', :sshpass => 'TestPass', :dcname => 'TestDCName' }}
|
6
|
+
|
7
|
+
it "is a class" do
|
8
|
+
expect(Jupiter::Host).to be_a(Class)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should recieve the correct credentials" do
|
12
|
+
testssh = Jupiter::Host.new(options)
|
13
|
+
expect(testssh).instance_of?(Class)
|
14
|
+
Net::SSH.should_receive(:start).with("192.168.11.11", "TestUser", {:password=>"TestPass", :port=>"22"})
|
15
|
+
testssh.ssh
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can generate a valid mac address" do
|
19
|
+
mac_regex = /^([0-9a-f]{2}([:-]|$)){6}$/i
|
20
|
+
mac = Jupiter::Host.new(options).generate_mac_address
|
21
|
+
mac.should =~ mac_regex
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can flatten a hash" do
|
25
|
+
hash_to_flatten = {:foo => 'bar', :red => 'dwarf', :yoda => 'dork with the force'}
|
26
|
+
string = Jupiter::Host.new(options).flatten_hash(hash_to_flatten)
|
27
|
+
expect(string).to eq(%Q[foo = "bar"\nred = "dwarf"\nyoda = "dork with the force"])
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Jupiter::UUID do
|
4
|
+
|
5
|
+
it "correctly calculates a VMWare style UUID" do
|
6
|
+
expect(Jupiter::UUID.new.generate('TestSeedForGeneratingUUID')).to eq('74 06 6c fa 54 fe a4 1d-1a e2 88 25 c3 c9 31 4d')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "is a class" do
|
10
|
+
expect(Jupiter::UUID).to be_a(Class)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.unshift("./lib")
|
2
|
+
require "jupiter"
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
6
|
+
config.run_all_when_everything_filtered = true
|
7
|
+
config.filter_run :focus
|
8
|
+
|
9
|
+
# Run specs in random order to surface order dependencies. If you find an
|
10
|
+
# order dependency and want to debug it, you can fix the order by providing
|
11
|
+
# the seed, which is printed after each run.
|
12
|
+
# --seed 1234
|
13
|
+
config.order = 'random'
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jupiter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,25 +10,141 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
14
|
-
dependencies:
|
13
|
+
date: 2013-05-01 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rbvmomi
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.6.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 1.6.0
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: net-ssh
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 2.6.5
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.6.5
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: net-scp
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.1.0
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: thor
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 0.17.0
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 0.17.0
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: pry
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ~>
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 0.9.11.4
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 0.9.11.4
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: rspec
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ~>
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 2.12.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.12.0
|
15
111
|
description: Automated vSphere deployment in ruby
|
16
112
|
email:
|
17
113
|
- marshall.wright.boyce@gmail.com
|
18
114
|
- adamhunter@me.com
|
19
|
-
executables:
|
115
|
+
executables:
|
116
|
+
- jupiter
|
20
117
|
extensions: []
|
21
118
|
extra_rdoc_files: []
|
22
119
|
files:
|
23
120
|
- .gitignore
|
121
|
+
- .rspec
|
24
122
|
- .rvmrc
|
25
123
|
- Gemfile
|
26
124
|
- LICENSE.txt
|
27
125
|
- README.md
|
28
126
|
- Rakefile
|
127
|
+
- bin/jupiter
|
128
|
+
- config.yaml.example
|
29
129
|
- jupiter.gemspec
|
30
130
|
- lib/jupiter.rb
|
131
|
+
- lib/jupiter/cli.rb
|
132
|
+
- lib/jupiter/cli/colorizer.rb
|
133
|
+
- lib/jupiter/cli/output.rb
|
134
|
+
- lib/jupiter/configuration.rb
|
135
|
+
- lib/jupiter/host.rb
|
136
|
+
- lib/jupiter/nagios.rb
|
137
|
+
- lib/jupiter/template.rb
|
138
|
+
- lib/jupiter/uuid.rb
|
31
139
|
- lib/jupiter/version.rb
|
140
|
+
- lib/jupiter/virtualmachine.rb
|
141
|
+
- spec/jupiter/cli_spec.rb
|
142
|
+
- spec/jupiter/host_spec.rb
|
143
|
+
- spec/jupiter/nagios_spec.rb
|
144
|
+
- spec/jupiter/uuid_spec.rb
|
145
|
+
- spec/jupiter/virtualmachine_spec.rb
|
146
|
+
- spec/jupiter_spec.rb
|
147
|
+
- spec/spec_helper.rb
|
32
148
|
homepage: https://github.com/tma1/jupiter
|
33
149
|
licenses: []
|
34
150
|
post_install_message:
|
@@ -49,9 +165,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
165
|
version: '0'
|
50
166
|
requirements: []
|
51
167
|
rubyforge_project:
|
52
|
-
rubygems_version: 1.8.
|
168
|
+
rubygems_version: 1.8.23
|
53
169
|
signing_key:
|
54
170
|
specification_version: 3
|
55
171
|
summary: Deploy vSphere slices and configure them automatically using a combination
|
56
172
|
of tools in ruby.
|
57
|
-
test_files:
|
173
|
+
test_files:
|
174
|
+
- spec/jupiter/cli_spec.rb
|
175
|
+
- spec/jupiter/host_spec.rb
|
176
|
+
- spec/jupiter/nagios_spec.rb
|
177
|
+
- spec/jupiter/uuid_spec.rb
|
178
|
+
- spec/jupiter/virtualmachine_spec.rb
|
179
|
+
- spec/jupiter_spec.rb
|
180
|
+
- spec/spec_helper.rb
|