From 40598cb7bfeb6b1042482fe91701770b179c1803 Mon Sep 17 00:00:00 2001 From: Chris Alfonso Date: Mon, 7 Jul 2008 17:20:43 -0400 Subject: Renaming everying everest to genome --- genome-bootstrap/lib/genome-bootstrap/core.rb | 188 ++++++++++++++++++++++++++ genome-bootstrap/lib/genome-bootstrap/ddns.rb | 75 ++++++++++ 2 files changed, 263 insertions(+) create mode 100644 genome-bootstrap/lib/genome-bootstrap/core.rb create mode 100644 genome-bootstrap/lib/genome-bootstrap/ddns.rb (limited to 'genome-bootstrap/lib/genome-bootstrap') diff --git a/genome-bootstrap/lib/genome-bootstrap/core.rb b/genome-bootstrap/lib/genome-bootstrap/core.rb new file mode 100644 index 0000000..4b9ac94 --- /dev/null +++ b/genome-bootstrap/lib/genome-bootstrap/core.rb @@ -0,0 +1,188 @@ +# Copyright (C) 2008 Red Hat, Inc + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# a long with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'erb' +require 'yaml' +require 'restr' +require 'xmlrpc/client' +require 'rubygems' + +module GenomeBootstrap + class GenomeRepo + attr_reader :machines, :machine_types_url, :cobbler_profiles, :fqdn, :repo + + def initialize(repo) + @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" + @genomed = "http://#{@fqdn}/genome" + @machine_types_url = @genomed + "/machine_types.html" + + @cobblerd = XMLRPC::Client.new2("http://#{@fqdn}:25152") + + # TODO: figure out a way to pass these values in + @token = @cobblerd.call2("login", "cobbler", "password")[1] + @cobbler_profiles = @cobblerd.call2("get_profiles", @token)[1].map {|p| p["name"]} + end + + def machines + @machines ||= fetch_data + end + + def facts_for(type, machine_name) + # Don't want to pull in the genome lib. See below fore more detail. + facts = restr_get("#{@genomed}/machine_types/#{type}.xml", "fact") + return facts.map do |f| + def f.name + self["name"] + end + + def f.desc + self["description"] + end + + # Here's where we make use of the DSL's simple templating + f.instance_variable_set(:@repo, @repo) + f.instance_variable_set(:@machine_name, machine_name) + def f.default + # handle there case where there is no default + self["default"].gsub("%repo%", @repo).gsub("%machine_name%", @machine_name) rescue "" + end + + f + end + end + + def classes_for(type) + restr_get("#{@genomed}/machine_types/#{type}.xml", "class") + end + + def fetch_data + # Build out some mock objects so we don't have to couple to the genome + # lib. That lib has lots of funky metaprogramming stuff in it and it + # might need to be changed in the future. The fewer tools relying on it + # the better. + machine_types = restr_get("#{@genomed}/machine_types.xml", "machine_type") + + return machine_types.map do |m| + def m.name + self["name"] + end + + def m.desc + self["description"] + end + + m + end + end + + def post_yaml(node_name, machine_type, yaml) + Restr.post("#{@genomed}/nodes", :node_name => node_name, :yaml => yaml) + end + + def add_system_to_cobbler(name, params, email) + system_id = @cobblerd.call2("new_system", @token)[1] + @cobblerd.call2('modify_system', system_id, 'name', name, @token) + @cobblerd.call2('modify_system', system_id, 'profile', params["cobbler_profile"], @token) + + # These values ultimately get used by genome-firstboot + ksmeta = "fqdn=#{name} " + + "genome_repo=#{@fqdn}" + + ksmeta << " email=#{email}" if email + + @cobblerd.call2('modify_system', system_id, 'ksmeta', ksmeta, @token) + @cobblerd.call2('save_system', system_id, @token) + end + + def register_machine(machine_fqdn, config, email="") + machine_type = config["parameters"]["genome_machine_type"] + 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("#{@genomed}/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 + + # This is a workaround for a Restr "feature". If only one element it is + # returned as a Hash instead of an Array. The way we use Restr assumes that it + # will always return an Array. + def restr_get(url, xml_node=nil) + data = xml_node ? Restr.get(url)[xml_node] : Restr.get(url) + + return case data + when Hash + Array.new << data + when Array + data + end + end + end + + class CloudController + attr_reader :repo, :cloud + + # Create a new CloudController with the given server name (prefix or fqdn) + # and repo (full GenomeRepo object) + def initialize(name, repo) + @repo = repo + + # If @repo is not an GenomeRepo object, assume it's the + # fqdn of a repo + if not @repo.is_a? GenomeRepo then + @repo = GenomeRepo.new(@repo) + end + + @cloud = "http://#{name}/cloud" + end + + 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/genome-bootstrap/lib/genome-bootstrap/ddns.rb b/genome-bootstrap/lib/genome-bootstrap/ddns.rb new file mode 100644 index 0000000..e0e982a --- /dev/null +++ b/genome-bootstrap/lib/genome-bootstrap/ddns.rb @@ -0,0 +1,75 @@ +# Copyright (C) 2008 Red Hat, Inc + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# a long with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +require 'net/https' + +module RedHatDDNS + SERVER = 'kickstart.rdu.redhat.com' + + class DDNS + def initialize(username, password, host) + @username = username + @password = password + @hostname = host + end + + def ddns_hash + @ddns_hash ||= fetch_hash + end + + def to_s + ddns_hash + end + + def main_page + req = "wget -q -O- --no-check-certificate " + + "--http-user=#{@username} --http-password='#{@password}' " + + %["https://#{SERVER}/redhat-ddns/admin/"] + + puts "Fetching DDNS hash..." + yield `#{req}` + end + + def request_new_hash + req = "wget -q -O- --no-check-certificate " + + "--http-user=#{@username} --http-password='#{@password}' " + + %["https://#{SERVER}/redhat-ddns/admin/add.php?host=#{@hostname}&_submit=Submit+Request"] + + puts "Requesting a new hash" + `#{req}` + end + + def fetch_hash(options={:tries => 3}) + options[:tries].times do + # In order to test the regex with mocha we can't rely on the + # return value from the main_page method. That's why I + # declare 'hash' here and store the results from inside the + # block + hash = nil + main_page do |html| + hash = /#{@hostname}<\/pre>.*?hash=(.*)\"/.match(html)[1] rescue nil + end + return hash if hash + puts "Hash not found for #{@hostname}" + request_new_hash + end + + raise RuntimeError.new("Error fetching DDNS hash:\n" + + "This usually happens when a hostname is reserved under another " + + "user's account or you typed password incorrectly.") + end + end +end -- cgit