1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
#!/usr/bin/env ruby
require 'ostruct'
require 'genome-bootstrap'
require 'main'
require 'net/http'
require 'uri'
require "highline/import"
#http://www.mail-archive.com/capistrano@googlegroups.com/msg01822.html
HighLine.track_eof = false
include GenomeBootstrap
Main {
def handle_exception e
puts e.message
end unless $DEBUG
def say_red(text)
say("<%= color(\"#{text}\", :red) %>")
end
# It's a little silly to have this much indirection. Smells like things need
# to be refactored a bit.
def get_system_ip(repo, system_name)
sleep_time = 5
tries = 20
say("Trying to determine the ip address.")
say("We'll try and maximum of #{tries} times.")
repo.get_system_ip(system_name, tries) do
# It's really silly that we have to poll for the ip like this.
say("Polling for cobbler status...")
say("Retrying in #{sleep_time} seconds")
sleep sleep_time
end
end
def get_input
@facts = Hash.new
say_red("\nYour genome repo server is the system that serves as the")
say_red("puppet master, git server, and cobbler server all in one.")
@repo = ask("Enter your Genome repo fully qualified domain name (fqdn): ")
# Default the "repoappliance" parameter to the given repo value
@facts["repoappliance"] = @repo
say_red("\nYour cloud master is the server that determines where the")
say_red("machine you're trying to create will be provisioned. Typically")
say_red("cloud masters control several machines in a cloud. However,")
say_red("cloud masters can be configured to simply manage their own disk space.")
@cloudmaster = ask("Enter your cloud master fqdn: ")
@email = ask("Enter your email address for cloud notifications: ")
# Allows genomed to know which cloudmaster is controlling this new machine
@facts["cloudmaster"] = @cloudmaster
say_red("\nYour system prefix is added to your machine name to help identify")
say_red("it as your own. It must be a single word and should be short (e.g. username).")
@system_prefix = ask("Enter your system prefix: ")
# Once we know the repo we can fetch the supported machines
@genome_repo = GenomeRepo.new(@repo)
say_red("\nNow, you can select your machine type.")
say_red("To see a description of these machine types visit: " +
"#{@genome_repo.machine_types_url}")
@machine_type = choose do |menu|
menu.prompt = "Select your machine type: "
menu.choices(*@genome_repo.machines.map{|m| m.name})
end
# Nice to keep around with the machine's specification
@facts["genome_machine_type"] = @machine_type
@system_name = "#{@system_prefix}-#{@machine_type}"
@facts["genome_system_name"] = @system_name
say_red("\nYour cobbler profile determines the OS, the disk space, and")
say_red("the amount of memory that should be allocated to the system")
say_red("that you are provisioning.")
@facts["cobbler_profile"] = choose do |menu|
menu.prompt = "Select your cobbler profile (This determines the OS): "
menu.choices(*@genome_repo.bootstrapping_cobbler_profiles)
end
facts = @genome_repo.facts_for(@machine_type)
if not facts.empty?
say_red("\nNow you need to enter some parameters what will be used to configure this machine.")
say_red("Most of the defaults will work out fine for development.")
facts.each do |f|
say_red("Description: #{f.desc}") unless f.desc.empty?
@facts[f.name] = ask("Enter value for #{f.name}: ") do |q|
q.default = f.default
end
end
end
end
def _run(config_only=false)
# Ask all the silly questions
get_input
classes = @genome_repo.classes_for(@machine_type)
config = {"classes" => classes, "parameters" => @facts}
say("\nYour system is now being provisioned")
@genome_repo.register_machine(@system_name, config)
unless config_only
cloud_master = CloudController.new(@cloudmaster, @genome_repo)
id, host = cloud_master.create_machine(@system_name, @email)
if ip = get_system_ip(@genome_repo, @system_name)
cloud_master.update_hostname(id, ip)
say("Your new system is being provisioned on #{host}.")
say("The IP address of the new system is #{ip}.")
else
say("Your new system is being provisioned on #{host}.")
say("You can visit #{@cloudmaster.cloud} to see the status of the new system.")
end
end
end
def run
_run
end
# Allow user to simply create the cobbler system
# but not actually create the VM
mode 'config-only' do
def run
_run(true)
end
end
# Allow user to supply a yaml file with the machine
# configuration instead of answering all the questions
mode 'advanced' do
option('fqdn', 'f'){
description "Fully qualified domain name of machine to be provisioned"
argument_required
}
option('system', 's'){
description "Cobbler system name of the machine to be provisioned"
argument_required
}
option('repo', '-r'){
required
description "Fully qualified domain name for the Genome repo machine to use for provisioning"
argument_required
}
option('cloudmaster', 'c'){
required
description "Fully qualified domain name for the machine controlling the cloud"
argument_required
}
option('email', 'e'){
required
description "Your email address to use to help identify the instance owner"
argument_required
}
option('yaml', 'y'){
description "YAML configuration for this machine"
argument_required
validate {|f| File.exist?(f)}
}
def run
unless params['fqdn'].given? || params['system'].given?
say("You must provide either an 'fqdn' parameter or a 'system' parameter")
exit(1)
end
# FQDN beats system parameter
if params['fqdn'].given?
name = params['fqdn'].value
else
name = params['system'].value
end
config = if params['yaml'].given?
YAML.load(File.read(params['yaml'].value))
else
YAML.load($stdin.read)
end
genome_repo = GenomeRepo.new(params['repo'].value)
genome_repo.register_machine(name, config)
cloud_master = CloudController.new(params['cloudmaster'].value, genome_repo)
host = cloud_master.create_machine(name, params['email'].value)
if ip = get_system_ip(genome_repo, name)
say("Your new system is being provisioned on #{host}.")
say("The IP address of the new system is #{ip}.")
else
say("Your new system is being provisioned on #{host}.")
say("You can visit #{cloud_master.cloud} to see the status of the new system.")
end
end
end
}
|