summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Blomquist <gblomqui@redhat.com>2008-06-30 13:56:55 -0400
committerGreg <gblomqui@redhat.com>2008-07-01 17:00:06 -0400
commit1b8d211e10918e7f4f3f7aedaa816a7a880b888b (patch)
tree828d1ff689311230bd92d298076f25efcd01916d
parent78a484c9854439f1e97b9bb590852cc6942a6147 (diff)
Removed Red Hat DDNS and references from everest-bootstrap, everestd, and cloudmasterd
Changes include: * everest-bootstrap's default mode is now "cloud". - It is assumed that all systems provisioned by everest-bootstrap will be sent to a cloudmaster for provisioning. However, a cloudmaster does not necessarily have to control several minions to qualify. A cloudmaster can be configured to simply control its own disk space. - The "advanced" mode also expects that systems are getting provisioned in a cloud, and requires a "cloudmaster" parameter. - The previous "--config-only" command line parameter has been changed to a mode. Now a user can select between "standard", "advanced", and "config-only" modes. - Hooks for cobbler dns have been added. A great deal more work needs to be done here before it is ready, though. - everest-bootstrap can now ask everestd if it knows the IP address and hostname of newly provisioned machines * everestd can now examine the /var/log/cobbler/install.log file to determine the IP address and hostname of new systems. - I suspect that this functionality will get moved from everestd to the cloudmaster. Users of everest-bootstrap will be directed to the cloud's status page to access the systems' IP addy and hostnames.
-rw-r--r--cloudmasterd/lib/cloudmasterd.rb15
-rw-r--r--everest-bootstrap/bin/everest-bootstrap218
-rw-r--r--everest-bootstrap/lib/everest-bootstrap/core.rb77
-rw-r--r--everestd/lib/everestd.rb114
4 files changed, 241 insertions, 183 deletions
diff --git a/cloudmasterd/lib/cloudmasterd.rb b/cloudmasterd/lib/cloudmasterd.rb
index a2dcc22..f5151d1 100644
--- a/cloudmasterd/lib/cloudmasterd.rb
+++ b/cloudmasterd/lib/cloudmasterd.rb
@@ -108,6 +108,7 @@ module Cloudmasterd::Models
t.column :email, :string, :null => false, :limit => 255
t.column :cloud, :string, :null => false, :limit => 255
t.column :state, :string, :null => false, :limit => 255
+ #t.column :repo, :string, :null => false, :limit => 255 # Add the repo column capture the origin repo
t.column :created_date, :datetime, :null => true
end
end
@@ -140,24 +141,24 @@ module Cloudmasterd::Controllers
# run the appropriate koan command to create the given "fqdn"
# on the given "host" and "vol_group"
- def _koan(host, fqdn, repo)
+ def _koan(host, system_name, repo)
# Run the koan process
- output = `func "#{host}" call virt install #{repo} #{fqdn} True #{fqdn} /images`
+ output = `func "#{host}" call virt install #{repo} #{system_name} True #{system_name} /images`
# Throw an exception if the process failed
raise output unless $?.success?
# Make the new host autostart
- `func "#{host}" call command run "ln -s /etc/xen/#{fqdn} /etc/xen/auto/"`
+ `func "#{host}" call command run "ln -s /etc/xen/#{system_name} /etc/xen/auto/"`
end
# POST /koan
def create
- machine_fqdn = input.machine_fqdn
+ system_name = input.system_name
repo = input.repo
email = input.email
- cobbler_profile = _get_cobbler_profile(machine_fqdn, repo)
+ cobbler_profile = _get_cobbler_profile(system_name, repo)
cobbler_distro = _get_cobbler_distro(cobbler_profile["distro"], repo)
# Synchronize access before making the func calls
@@ -165,9 +166,9 @@ module Cloudmasterd::Controllers
@host = _get_best_host(cobbler_profile["virt_ram"], cobbler_distro["arch"])
begin
- _koan(@host, machine_fqdn, repo)
+ _koan(@host, system_name, repo)
- Machine.create :name => machine_fqdn, :email => email, :cloud => @host, :state => "Installing", :created_date => DateTime.now()
+ Machine.create :name => system_name, :email => email, :cloud => @host, :state => "Installing", :created_date => DateTime.now()
render :_koan
rescue Exception => e
@exception = e
diff --git a/everest-bootstrap/bin/everest-bootstrap b/everest-bootstrap/bin/everest-bootstrap
index b5812c5..f85ce6f 100644
--- a/everest-bootstrap/bin/everest-bootstrap
+++ b/everest-bootstrap/bin/everest-bootstrap
@@ -20,34 +20,31 @@ Main {
say("<%= color(\"#{text}\", :red) %>")
end
- def get_input(cloud=false)
- unless ENV['USER'] == 'root' || params["config-only"].given? || cloud
- raise "You must run this command as root unless " +
- "you specify the '--config-only' option"
- end
-
+ def get_input
@facts = Hash.new
- if cloud
- @cloudmaster = ask("Enter your cloud master: ")
- @email = ask("Enter your email address for cloud notifications: ")
- end
-
- @repo = ask("Enter your Everest repo machine name (leave off the '-repo'): ")
- @user = ask("Enter your kerberos username: ")
-
- say_red("Your machine name is the part right before the Everest type.")
- say_red("For example, 'sso1-build.usersys.redhat.com' has a machine name of 'sso1'.")
- say_red("If you do not specify a machine name it will default to your kerberos name.")
-
- if agree("Enter machine name? (y/n)", true)
- @machine_name = ask("Machine name: ")
- else
- @machine_name = @user
- end
+ say_red("\nYour everest 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 Everest repo machine name (leave off the '-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: ")
+ @email = ask("Enter your email address for cloud notifications: ")
+
+ say_red("\nYour cobbler system name consists of two parts")
+ say_red("\t* a system prefix")
+ say_red("\t* a machine type")
+ say_red("The system prefix can be used to help group common systems")
+ say_red("together using some canonical name. For instance, this can be")
+ say_red("helpful when configuring clustered JBoss servers")
+ @system_prefix = ask("Enter your system prefix: ")
# Once we know the repo we can fetch the supported machines
@everest_repo = EverestRepo.new(@repo)
+ say_red("\nNow, you can select your machine type.")
say_red("To see a description of these machine types visit: " +
"#{@everest_repo.machine_types_url}")
@@ -59,27 +56,15 @@ Main {
# This might be useful is we stop using DDNS
@facts["everest_machine_type"] = @machine_type
- if agree("Configure this machine with Red Hat DDNS? (y/n)", true)
- # Our naming convention
- hostname = @machine_name + "-" + @machine_type
- @fqdn = hostname + ".usersys.redhat.com"
-
- if agree("Do you know the DDNS hash for this machine? (y/n)", true)
- @facts["rh_ddns_hash"] = ask("Enter Red Hat DDNS hash: ")
- else
- @password = ask("Enter your kerberos password to setup DDNS: ") { |q| q.echo = "*" }
- @facts["rh_ddns_hash"] = RedHatDDNS::DDNS.new(@user, @password, hostname).ddns_hash
- end
- else
- @fqdn = ask("Enter fully qualified domain name for this machine: ")
- end
-
+ 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(*@everest_repo.cobbler_profiles)
end
- say_red("Now you need to enter some parameters what will be used to configure this machine.")
+ 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.")
@everest_repo.facts_for(@machine_type, @machine_name).each do |f|
@@ -89,129 +74,57 @@ Main {
end
end
- if agree("Enter addition facts? (y/n)", true)
+ if agree("\nEnter addition facts? (y/n)", true)
begin
name = ask("Enter fact name: ")
value = ask("Enter fact value: ")
@facts[name] = value
end while agree("Enter another? ", true)
end
-
- unless params["config-only"].given? || cloud
- if agree("Use LVM for VM storage (recommended)? (y/n)", true)
- @virt_path = choose do |menu|
- menu.prompt = "Select the Volume Group to use: "
- menu.choices(*(`/usr/sbin/vgdisplay --short`.split("\n").map {|l| /"(.*)"/.match(l).captures[0]}))
- end
- else
- @virt_path = ask("Enter the flat file to be used for guest: ")
- end
-
- xen_conf = "/etc/xen/#{@fqdn.split(".")[0]}"
- if File.exist?(xen_conf)
- say_red("Previous Xen configuration detected at #{xen_conf}.")
- say_red("This will cause Koan to abort.")
- if agree("Clean up? (y/n)", true)
- File.delete(xen_conf)
- end
- end
-
- say_red("The Koan process is now starting. After it finishes start the VM back up with " +
- "'xm create <name>'.")
- say_red("HINT: 'xm list' will show you the running VMs.")
- end
end
- option('config-only', 'c'){
- description "Only send the machine configuration to the Puppetmaster"
- }
-
- def run
+ def _run(config_only=false)
# Ask all the silly questions
get_input
-
+
classes = @everest_repo.classes_for(@machine_type)
config = {"classes" => classes, "parameters" => @facts}
- e = EverestMachine.new(@machine_type,
- @fqdn,
- @repo,
- config)
- e.post_config
- e.add_system_to_cobbler
- e.koan(@virt_path) unless params["config-only"].given?
- end
-
- mode 'advanced' do
- option('fqdn', 'f'){
- required
- description "Fully qualified domain name of machine to be provisioned"
- argument_required
- }
-
- option('repo', '-r'){
- required
- description "Fully qualified domain name for the Everest repo machine to use for provisioning"
- argument_required
- }
-
- option('yaml', 'y'){
- description "YAML configuration for this machine"
- argument_required
- validate {|f| File.exist?(f)}
- }
-
- option('virt-path', 'v'){
- description "Volume group or flat file for koan provisioning"
- argument_required
- }
-
- def run
- config = if params['yaml'].given?
- YAML.load(File.read(params['yaml'].value))
- else
- YAML.load($stdin.read)
+ @everest_repo.register_machine(@fqdn, config)
+ unless config_only
+ cloud_master = CloudController.new(@cloudmaster, @everest_repo)
+ cloud_master.create_machine(@fqdn, @email)
+ if @everest_repo.cobbler_dns?
+ @everest_repo.register_dns_entry
end
-
- e = EverestMachine.new(config["parameters"]["everest_machine_type"],
- params['fqdn'].value,
- params['repo'].value,
- config)
- e.post_config
- e.add_system_to_cobbler
- e.koan(params['virt-path'].value) if params["virt-path"].given?
end
end
- mode 'cloud' do
+ def run
+ _run
+ end
+
+ # Allow user to simply create the cobbler system
+ # but not actually create the VM
+ mode 'config-only' do
def run
- # Get input for the cloud
- get_input(true)
-
- classes = @everest_repo.classes_for(@machine_type)
- config = {"classes" => classes, "parameters" => @facts}
-
- # Create the everest machine
- e = EverestMachine.new(@machine_type,
- @fqdn,
- @repo,
- config,
- @email)
-
- e.post_config
- e.add_system_to_cobbler
- cloud_master = CloudController.new(@cloudmaster, @repo)
- cloud_master.create_machine(@fqdn, @email)
+ _run(true)
end
end
- mode 'cloud-advanced' do
+ # Allow user to supply a yaml file with the machine
+ # configuration instead of answering all the questions
+ mode 'advanced' do
option('fqdn', 'f'){
- required
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 Everest repo machine to use for provisioning"
@@ -237,6 +150,18 @@ Main {
}
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
@@ -244,10 +169,25 @@ Main {
end
everest_repo = EverestRepo.new(params['repo'].value)
- everest_repo.register_machine(params['fqdn'].value, config)
+ everest_repo.register_machine(name, config)
cloud_master = CloudController.new(params['cloudmaster'].value, everest_repo)
- cloud_master.create_machine(params['fqdn'].value, params['email'].value)
+ host = cloud_master.create_machine(name, params['email'].value)
+
+ installed_system = everest_repo.get_installed_system(name)
+ if not installed_system.empty?
+ if everest_repo.cobbler_dns? and params['fqdn'].given?
+ # register the new system with cobbler dns using the name,
+ # the installed_system's IP, and the given fqdn
+ else
+ fqdn = installed_system["hostname"]
+ end
+ say("Your new system is being provisioned on #{host}.")
+ say("The FQDN of new system is #{fqdn}.")
+ say("The IP address of the new system is #{installed_system["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
}
diff --git a/everest-bootstrap/lib/everest-bootstrap/core.rb b/everest-bootstrap/lib/everest-bootstrap/core.rb
index db52085..07e6b9e 100644
--- a/everest-bootstrap/lib/everest-bootstrap/core.rb
+++ b/everest-bootstrap/lib/everest-bootstrap/core.rb
@@ -18,6 +18,7 @@ require 'erb'
require 'yaml'
require 'restr'
require 'xmlrpc/client'
+require 'rubygems'
module EverestBootstrap
class EverestRepo
@@ -27,7 +28,7 @@ module EverestBootstrap
@repo = repo
# Allow users to pass in just the machine-name or the fqdn
@fqdn = @repo.split(".").size > 1 ? @repo : "#{@repo}-repo.usersys.redhat.com"
- @everestd = "http://#{@fqdn}:8106"
+ @everestd = "http://#{@fqdn}/everest"
@machine_types_url = @everestd + "/machine_types.html"
@cobblerd = XMLRPC::Client.new2("http://#{@fqdn}:25152")
@@ -112,9 +113,45 @@ module EverestBootstrap
post_yaml(machine_fqdn, machine_type, YAML.dump(config))
add_system_to_cobbler(machine_fqdn, config["parameters"], email)
end
+
+ # Retrive information form the /var/log/cobbler/install.log
+ def get_installed_systems
+ systems = Restr.get("#{@everestd}/systems.xml")
+ return systems["system"].map do |system|
+ def system.name
+ self["name"].to_s
+ end
+
+ def system.ip
+ self["ip"].to_s
+ end
+
+ def system.hostname
+ self["hostname"].to_s
+ end
+ system
+ end
+ end
+
+ def get_installed_system(system_name)
+ systems = get_installed_systems
+ systems.delete_if{|system|
+ system.name.to_s != system_name.to_s
+ }
+ end
+
+ def cobbler_dns?
+ return false
+ end
+
+ def register_dns_entry(ip, name)
+
+ end
end
class CloudController
+ attr_reader :repo, :cloud
+
# Create a new CloudController with the given server name (prefix or fqdn)
# and repo (full EverestRepo object)
def initialize(name, repo)
@@ -126,43 +163,11 @@ module EverestBootstrap
@repo = EverestRepo.new(@repo)
end
- @controller = name
- # Allow users to pass in just the machine-name or the fqdn
- @fqdn = @controller.split(".").size > 1 ? @controller : "#{@controller}-host.usersys.redhat.com"
- @cloud = "http://#{@fqdn}:8107"
- end
-
- def create_machine(machine_fqdn, email)
- host = Restr.post("#{@cloud}/koan", :machine_fqdn => machine_fqdn, :repo => @repo.fqdn, :email => email)
- puts "Machine is being created on #{host}"
- end
- end
-
- class EverestMachine
- include RedHatDDNS
- attr_reader :type, :hostname, :fqdn
-
- def initialize(machine_type, fqdn, repo, config, email=nil)
- @machine_type = machine_type
- @fqdn = fqdn
- @config = config
- @email = email
- @everest_repo = EverestRepo.new(repo)
- end
-
- def post_config
- @everest_repo.post_yaml(@fqdn, @machine_type, YAML.dump(@config))
- end
-
- def add_system_to_cobbler
- @everest_repo.add_system_to_cobbler(@fqdn, @config["parameters"], @email)
+ @cloud = "http://#{name}/cloud"
end
- def koan(virt_path)
- koan_command = "/usr/bin/koan -s #{@everest_repo.fqdn} " +
- "--virt --virt-type=xenpv --virt-path=#{virt_path} " +
- "--system=#{@fqdn} --virt-name=#{@fqdn.split(".")[0]}"
- `#{koan_command}`
+ def create_machine(system_name, email)
+ return Restr.post("#{@cloud}/koan", :system_name => system_name, :repo => @repo.fqdn, :email => email)
end
end
end
diff --git a/everestd/lib/everestd.rb b/everestd/lib/everestd.rb
index 45e1b99..32cd8a2 100644
--- a/everestd/lib/everestd.rb
+++ b/everestd/lib/everestd.rb
@@ -25,7 +25,9 @@ require 'picnic'
require 'reststop'
require 'everest-dsl'
require 'restr'
+require 'cgi'
require 'xmlrpc/client'
+require 'pp'
CONTEXT="/everest"
@@ -33,6 +35,46 @@ Camping.goes :Everestd
Everestd.picnic!
module Everestd::Controllers
+ class Systems < REST 'systems'
+ # OMG, this is ugly
+ def _get_cobbler_installed_systems
+ systems = {}
+ `cat /var/log/cobbler/install.log | cut -f2-3`.each do |line|
+ name, ip = line.split("\t")
+ ip.chomp!
+ name.chomp!
+ hostname = _get_host_name(ip).chomp
+ puts "name: #{name}, ip: #{ip}, hostname: #{hostname}"
+
+ systems[name] = {"ip" => ip, "hostname" => hostname}
+ end
+ return systems
+ end
+
+ def _get_host_name(ip)
+ lookup = `nslookup #{ip} | grep name | cut -f2`
+ unless lookup.empty?
+ return lookup.split("=")[1].strip.split(".").join(".")
+ end
+ end
+
+ def read(name)
+ name = CGI::unescape(name)
+ @systems = _get_cobbler_installed_systems
+ @system = {}
+ if @systems.has_key?(name)
+ @system = {"name" => name, "ip" => @systems[name]["ip"], "hostname" => @systems[name]["hostname"]}
+ end
+ render :view_system
+ end
+
+ def list
+ @systems = _get_cobbler_installed_systems
+ pp @systems
+ render :list_systems
+ end
+ end
+
class MachineTypes < REST 'machine_types'
include EverestDsl
@@ -147,7 +189,8 @@ module Everestd::Views
div.content! do
h1 do
[a("Machine Types", :href => CONTEXT + R(Everestd::Controllers::MachineTypes)),
- a("Nodes", :href => CONTEXT + R(Everestd::Controllers::Nodes))].join " | "
+ a("Nodes", :href => CONTEXT + R(Everestd::Controllers::Nodes)),
+ a("Systems", :href => CONTEXT + R(Everestd::Controllers::Systems))].join " | "
end
self << yield
end
@@ -212,6 +255,17 @@ module Everestd::Views
end
end
+ def view_system
+ h1 @system["name"]
+
+ p do
+ "IP Address: #{@system["ip"]} "
+ end
+ p do
+ "Hostname: #{@system["hostname"]}"
+ end
+ end
+
def list_nodes
h1 "Nodes:"
p "To create a new node just browse to the page corresponding to the hostname. " +
@@ -241,6 +295,34 @@ module Everestd::Views
end
end
end
+
+ def list_systems
+ host = ENV["HOSTNAME"]
+ cobbler_web = "http://#{host}/cobbler/web"
+ h1 "Systems:"
+ h4 do
+ text("This information is gathered from the /var/log/cobbler/install.log file.\n")
+ text("If you don't see what you're looking for, try ")
+ a("cobbler web", :href => "#{cobbler_web}/?mode=system_list")
+ end
+
+ p do
+ ol do
+ @systems.each_key do |name|
+ li do
+ a(name, :href => URL("http://#{host}/#{CONTEXT}/systems/?id=#{name}"))
+ text(" (")
+ a("edit in cobbler", :href => "#{cobbler_web}/?mode=system_edit&name=#{name}")
+ text(")")
+ ul do
+ li "ip: #{@systems[name]["ip"]}"
+ li "hostname: #{@systems[name]["hostname"]}"
+ end
+ end
+ end
+ end
+ end
+ end
end
default_format :HTML
@@ -255,6 +337,14 @@ module Everestd::Views
def view_node
::YAML.dump(@info)
end
+
+ def view_system
+ ::YAML.dump(@system)
+ end
+
+ def list_systems
+ ::YAML.dump(@systems)
+ end
end
module XML
@@ -312,6 +402,28 @@ module Everestd::Views
@info["classes"].each {|c| @x.class(c)}
}
end
+
+ def list_systems
+ @x.instruct!
+ @x.systems {
+ @systems.each_key {|system|
+ @x.system {
+ @x.name(system)
+ @x.ip(@systems[system]["ip"])
+ @x.hostname(@systems[system]["hostname"])
+ }
+ }
+ }
+ end
+
+ def view_system
+ @x.instruct!
+ @x.system {
+ @x.name(@system["name"])
+ @x.ip(@system["ip"])
+ @x.hostname(@system["hostname"])
+ }
+ end
end
end