diff options
| author | Greg Blomquist <gblomqui@redhat.com> | 2008-06-30 13:56:55 -0400 |
|---|---|---|
| committer | Greg <gblomqui@redhat.com> | 2008-07-01 17:00:06 -0400 |
| commit | 1b8d211e10918e7f4f3f7aedaa816a7a880b888b (patch) | |
| tree | 828d1ff689311230bd92d298076f25efcd01916d | |
| parent | 78a484c9854439f1e97b9bb590852cc6942a6147 (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.rb | 15 | ||||
| -rw-r--r-- | everest-bootstrap/bin/everest-bootstrap | 218 | ||||
| -rw-r--r-- | everest-bootstrap/lib/everest-bootstrap/core.rb | 77 | ||||
| -rw-r--r-- | everestd/lib/everestd.rb | 114 |
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 |
