jupiter 0.0.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|