From cf796141ac01c866e81663f20699ccd56ce2d50b Mon Sep 17 00:00:00 2001 From: root Date: Thu, 19 Jun 2008 15:36:54 -0400 Subject: Moved the cloud daemon to cloudmasterd to give it a better name --- cloud/.gitignore | 2 - cloud/History.txt | 4 - cloud/License.txt | 20 - cloud/Manifest.txt | 31 - cloud/README.txt | 48 - cloud/Rakefile | 4 - cloud/bin/cloud | 14 - cloud/bin/cloud-ctl | 8 - cloud/config.example.yml | 88 -- cloud/config/hoe.rb | 70 - cloud/config/requirements.rb | 15 - cloud/extra/cloud.redhat | 43 - cloud/extra/cloud.spec | 67 - cloud/lib/cloud.rb | 166 -- cloud/lib/cloud/version.rb | 9 - cloud/log/debug.log | 0 cloud/script/console | 10 - cloud/script/destroy | 14 - cloud/script/generate | 14 - cloud/script/txt2html | 74 - cloud/setup.rb | 1585 -------------------- cloud/spec/cloud_spec.rb | 11 - cloud/spec/spec.opts | 1 - cloud/spec/spec_helper.rb | 10 - cloud/tasks/deployment.rake | 34 - cloud/tasks/environment.rake | 7 - cloud/tasks/rspec.rake | 21 - cloud/tasks/website.rake | 17 - cloud/website/index.html | 11 - cloud/website/index.txt | 39 - .../javascripts/rounded_corners_lite.inc.js | 285 ---- cloud/website/stylesheets/screen.css | 138 -- cloud/website/template.html.erb | 48 - cloudmasterd/.gitignore | 2 + cloudmasterd/History.txt | 4 + cloudmasterd/License.txt | 20 + cloudmasterd/Manifest.txt | 31 + cloudmasterd/README.txt | 48 + cloudmasterd/Rakefile | 4 + cloudmasterd/bin/cloudmasterd | 14 + cloudmasterd/bin/cloudmasterd-ctl | 8 + cloudmasterd/config.example.yml | 88 ++ cloudmasterd/config/hoe.rb | 70 + cloudmasterd/config/requirements.rb | 15 + cloudmasterd/extra/cloudmasterd.redhat | 43 + cloudmasterd/extra/cloudmasterd.spec | 67 + cloudmasterd/lib/cloudmasterd.rb | 170 +++ cloudmasterd/lib/cloudmasterd/version.rb | 9 + cloudmasterd/log/debug.log | 0 cloudmasterd/script/console | 10 + cloudmasterd/script/destroy | 14 + cloudmasterd/script/generate | 14 + cloudmasterd/script/txt2html | 74 + cloudmasterd/setup.rb | 1585 ++++++++++++++++++++ cloudmasterd/spec/cloudmasterd_spec.rb | 11 + cloudmasterd/spec/spec.opts | 1 + cloudmasterd/spec/spec_helper.rb | 10 + cloudmasterd/tasks/deployment.rake | 34 + cloudmasterd/tasks/environment.rake | 7 + cloudmasterd/tasks/rspec.rake | 21 + cloudmasterd/tasks/website.rake | 17 + cloudmasterd/website/index.html | 11 + cloudmasterd/website/index.txt | 39 + .../javascripts/rounded_corners_lite.inc.js | 285 ++++ cloudmasterd/website/stylesheets/screen.css | 138 ++ cloudmasterd/website/template.html.erb | 48 + 66 files changed, 2912 insertions(+), 2908 deletions(-) delete mode 100644 cloud/.gitignore delete mode 100644 cloud/History.txt delete mode 100644 cloud/License.txt delete mode 100644 cloud/Manifest.txt delete mode 100644 cloud/README.txt delete mode 100644 cloud/Rakefile delete mode 100644 cloud/bin/cloud delete mode 100644 cloud/bin/cloud-ctl delete mode 100644 cloud/config.example.yml delete mode 100644 cloud/config/hoe.rb delete mode 100644 cloud/config/requirements.rb delete mode 100755 cloud/extra/cloud.redhat delete mode 100644 cloud/extra/cloud.spec delete mode 100644 cloud/lib/cloud.rb delete mode 100644 cloud/lib/cloud/version.rb delete mode 100644 cloud/log/debug.log delete mode 100755 cloud/script/console delete mode 100755 cloud/script/destroy delete mode 100755 cloud/script/generate delete mode 100755 cloud/script/txt2html delete mode 100644 cloud/setup.rb delete mode 100644 cloud/spec/cloud_spec.rb delete mode 100644 cloud/spec/spec.opts delete mode 100644 cloud/spec/spec_helper.rb delete mode 100644 cloud/tasks/deployment.rake delete mode 100644 cloud/tasks/environment.rake delete mode 100644 cloud/tasks/rspec.rake delete mode 100644 cloud/tasks/website.rake delete mode 100644 cloud/website/index.html delete mode 100644 cloud/website/index.txt delete mode 100644 cloud/website/javascripts/rounded_corners_lite.inc.js delete mode 100644 cloud/website/stylesheets/screen.css delete mode 100644 cloud/website/template.html.erb create mode 100644 cloudmasterd/.gitignore create mode 100644 cloudmasterd/History.txt create mode 100644 cloudmasterd/License.txt create mode 100644 cloudmasterd/Manifest.txt create mode 100644 cloudmasterd/README.txt create mode 100644 cloudmasterd/Rakefile create mode 100644 cloudmasterd/bin/cloudmasterd create mode 100644 cloudmasterd/bin/cloudmasterd-ctl create mode 100644 cloudmasterd/config.example.yml create mode 100644 cloudmasterd/config/hoe.rb create mode 100644 cloudmasterd/config/requirements.rb create mode 100755 cloudmasterd/extra/cloudmasterd.redhat create mode 100644 cloudmasterd/extra/cloudmasterd.spec create mode 100644 cloudmasterd/lib/cloudmasterd.rb create mode 100644 cloudmasterd/lib/cloudmasterd/version.rb create mode 100644 cloudmasterd/log/debug.log create mode 100755 cloudmasterd/script/console create mode 100755 cloudmasterd/script/destroy create mode 100755 cloudmasterd/script/generate create mode 100755 cloudmasterd/script/txt2html create mode 100644 cloudmasterd/setup.rb create mode 100644 cloudmasterd/spec/cloudmasterd_spec.rb create mode 100644 cloudmasterd/spec/spec.opts create mode 100644 cloudmasterd/spec/spec_helper.rb create mode 100644 cloudmasterd/tasks/deployment.rake create mode 100644 cloudmasterd/tasks/environment.rake create mode 100644 cloudmasterd/tasks/rspec.rake create mode 100644 cloudmasterd/tasks/website.rake create mode 100644 cloudmasterd/website/index.html create mode 100644 cloudmasterd/website/index.txt create mode 100644 cloudmasterd/website/javascripts/rounded_corners_lite.inc.js create mode 100644 cloudmasterd/website/stylesheets/screen.css create mode 100644 cloudmasterd/website/template.html.erb diff --git a/cloud/.gitignore b/cloud/.gitignore deleted file mode 100644 index 3567727..0000000 --- a/cloud/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -pkg* -*.gem diff --git a/cloud/History.txt b/cloud/History.txt deleted file mode 100644 index 59ce905..0000000 --- a/cloud/History.txt +++ /dev/null @@ -1,4 +0,0 @@ -== 0.0.1 2008-04-09 - -* 1 major enhancement: - * Initial release diff --git a/cloud/License.txt b/cloud/License.txt deleted file mode 100644 index 7a2ed3c..0000000 --- a/cloud/License.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008 Brenton Leanhardt - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/cloud/Manifest.txt b/cloud/Manifest.txt deleted file mode 100644 index 54bc2dc..0000000 --- a/cloud/Manifest.txt +++ /dev/null @@ -1,31 +0,0 @@ -History.txt -License.txt -Manifest.txt -README.txt -Rakefile -bin/cloud -bin/cloud-ctl -config.example.yml -config/hoe.rb -config/requirements.rb -extra/cloud.redhat -lib/cloud.rb -lib/cloud/version.rb -log/debug.log -script/console -script/destroy -script/generate -script/txt2html -setup.rb -spec/cloud.rb -spec/spec.opts -spec/spec_helper.rb -tasks/deployment.rake -tasks/environment.rake -tasks/rspec.rake -tasks/website.rake -website/index.html -website/index.txt -website/javascripts/rounded_corners_lite.inc.js -website/stylesheets/screen.css -website/template.html.erb diff --git a/cloud/README.txt b/cloud/README.txt deleted file mode 100644 index 52e3511..0000000 --- a/cloud/README.txt +++ /dev/null @@ -1,48 +0,0 @@ -= cloud - -* FIX (url) - -== DESCRIPTION: - -FIX (describe your package) - -== FEATURES/PROBLEMS: - -* FIX (list of features or problems) - -== SYNOPSIS: - - FIX (code sample of usage) - -== REQUIREMENTS: - -* FIX (list of requirements) - -== INSTALL: - -* FIX (sudo gem install, anything else) - -== LICENSE: - -(The MIT License) - -Copyright (c) 2008 FIX - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cloud/Rakefile b/cloud/Rakefile deleted file mode 100644 index e469154..0000000 --- a/cloud/Rakefile +++ /dev/null @@ -1,4 +0,0 @@ -require 'config/requirements' -require 'config/hoe' # setup Hoe + all gem configuration - -Dir['tasks/**/*.rake'].each { |rake| load rake } \ No newline at end of file diff --git a/cloud/bin/cloud b/cloud/bin/cloud deleted file mode 100644 index ff14dc9..0000000 --- a/cloud/bin/cloud +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Brenton Leanhardt on 2008-4-9. -# Copyright (c) 2008. All rights reserved. - -require 'rubygems' -require 'picnic/cli' - -cli = Picnic::Cli.new( - 'cloud', - :app_path => File.expand_path(File.dirname(File.expand_path(__FILE__))) -) - -cli.handle_cli_input diff --git a/cloud/bin/cloud-ctl b/cloud/bin/cloud-ctl deleted file mode 100644 index b38a487..0000000 --- a/cloud/bin/cloud-ctl +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env ruby - -require 'rubygems' -require 'picnic/service_control' - -ctl = Picnic::ServiceControl.new('cloud') - -ctl.handle_cli_input diff --git a/cloud/config.example.yml b/cloud/config.example.yml deleted file mode 100644 index 32aeeaf..0000000 --- a/cloud/config.example.yml +++ /dev/null @@ -1,88 +0,0 @@ -# AN IMPORTANT NOTE ABOUT YAML CONFIGURATION FILES: -# !!! Be sure to use spaces instead of tabs for indentation, as YAML is very -# !!! sensitive to white-space inconsistencies! - -##### HTTP SERVER ##################################################################### - -# Under what HTTP environment are you running the Everestd server? The following methods -# are currently supported: -# -# webrick -- simple stand-alone HTTP server; this is the default method -# mongrel -- fast stand-alone HTTP server; much faster than webrick, but -# you'll have to first install the mongrel gem -# - -### webrick example - -server: webrick -port: 8107 - -### webrick SSL example - -#server: webrick -#port: 443 -#ssl_cert: /path/to/your/ssl.pem - -# if the private key is separate from cert: -#ssl_key: /path/to/your/private_key.pem - - -### mongrel example - -#server: mongrel -#port: 8106 - -# It is possible to run mongrel over SSL, but you will need to use a reverse proxy -# (try Pound or Apache). - - -##### DATABASE ######################################################################## - -# The Blog needs a database to store its records. -# -# By default, we use MySQL, since it is widely used and does not require any additional -# ruby libraries besides ActiveRecord. -# -# With MySQL, your config would be something like the following: -# (be sure to create the blog database in MySQL beforehand, -# i.e. `mysqladmin -u root create blog`) - -#database: -# adapter: mysql -# database: blog -# username: root -# password: -# host: localhost - - -# Instead of MySQL you can use SQLite3, PostgreSQL, MSSQL, or anything else supported -# by ActiveRecord. -# -# If you do not have a database server available, you can try using the SQLite3 -# back-end. SQLite3 does not require it's own server. Instead all data is stored -# in local files. For SQLite3, your configuration would look something like the -# following (don't forget to install the 'sqlite3-ruby' gem first!): -# -#database: -# adapter: sqlite3 -# dbfile: /var/lib/blog.db - -##### EVERESTD ######################################################################## - - -##### LOGGING ######################################################################### - -# This log is where you'll want to look in case of problems. -# -# By default, we will try to create a log file named 'blog.log' in the current -# directory (the directory where you're running the blog from). A better place to put -# the log is in /var/log, but you will have to run blog as root or otherwise give -# it permissions. -# -# Set the level to DEBUG if you want more detailed logging. Other options are -# INFO, WARN, and ERROR (DEBUG is most verbose, ERROR is least). - -log: - level: DEBUG - file: /var/log/cloud.log -# level: INFO diff --git a/cloud/config/hoe.rb b/cloud/config/hoe.rb deleted file mode 100644 index 4b1c166..0000000 --- a/cloud/config/hoe.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'cloud/version' - -AUTHOR = 'Brenton Leanhardt' # can also be an array of Authors -EMAIL = "bleanhar@redhat.com" -DESCRIPTION = "daemon for machine configuration" -GEM_NAME = 'cloud' # what ppl will type to install your gem -RUBYFORGE_PROJECT = 'cloud' # The unix name for your project -HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org" -DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}" - -@config_file = "~/.rubyforge/user-config.yml" -@config = nil -RUBYFORGE_USERNAME = "unknown" -def rubyforge_username - unless @config - begin - @config = YAML.load(File.read(File.expand_path(@config_file))) - rescue - puts <<-EOS -ERROR: No rubyforge config file found: #{@config_file} -Run 'rubyforge setup' to prepare your env for access to Rubyforge - - See http://newgem.rubyforge.org/rubyforge.html for more details - EOS - exit - end - end - RUBYFORGE_USERNAME.replace @config["username"] -end - - -REV = nil -# UNCOMMENT IF REQUIRED: -# REV = YAML.load(`svn info`)['Revision'] -VERS = Everestd::VERSION::STRING + (REV ? ".#{REV}" : "") -RDOC_OPTS = ['--quiet', '--title', 'cloud documentation', - "--opname", "index.html", - "--line-numbers", - "--main", "README", - "--inline-source"] - -class Hoe - def extra_deps - @extra_deps.reject! { |x| Array(x).first == 'hoe' } - @extra_deps - end -end - -# Generate all the Rake tasks -# Run 'rake -T' to see list of generated tasks (from gem root directory) -$hoe = Hoe.new(GEM_NAME, VERS) do |p| - p.developer(AUTHOR, EMAIL) - p.description = DESCRIPTION - p.summary = DESCRIPTION - p.url = HOMEPATH - p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT - p.test_globs = ["test/**/test_*.rb"] - p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] - - # == Optional - p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n") - p.extra_deps = ['picnic', 'activesupport', ['reststop', '>= 0.2.1'], 'everest'] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ] - - p.spec_extras = {:executables => ['cloud', 'cloud-ctl']} # A hash of extra values to set in the gemspec. - -end - -CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n") -PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}" -$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc') -$hoe.rsync_args = '-av --delete --ignore-errors' diff --git a/cloud/config/requirements.rb b/cloud/config/requirements.rb deleted file mode 100644 index 9292b69..0000000 --- a/cloud/config/requirements.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'fileutils' -include FileUtils - -require 'rubygems' -%w[rake hoe newgem rubigen].each do |req_gem| - begin - require req_gem - rescue LoadError - puts "This Rakefile requires the '#{req_gem}' RubyGem." - puts "Installation: gem install #{req_gem} -y" - exit - end -end - -$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib])) diff --git a/cloud/extra/cloud.redhat b/cloud/extra/cloud.redhat deleted file mode 100755 index 670ab9f..0000000 --- a/cloud/extra/cloud.redhat +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# -# cloud: Init script for Cloud daemon. -# -# chkconfig: 35 91 03 -# -# description: Deamon for creating cloud machines in an everest framework -# -# -# - -# Source function library. -. /etc/init.d/functions - -CTL=cloud-ctl - -[ -z "$HOME" ] && export HOME=/ - -case "$1" in - start) - echo -n $"Starting cloud: " - $CTL start - RETVAL=$? - ;; - stop) - echo -n $"Stopping cloud: " - $CTL stop - RETVAL=$? - ;; - restart) - $0 stop - $0 start - ;; - status) - $CTL status - RETVAL=$? - ;; - *) - echo $"Usage: $0 {start|stop|status|restart}" - RETVAL=1 -esac - -exit $RETVAL diff --git a/cloud/extra/cloud.spec b/cloud/extra/cloud.spec deleted file mode 100644 index d309c3b..0000000 --- a/cloud/extra/cloud.spec +++ /dev/null @@ -1,67 +0,0 @@ -# Generated from cloud-0.1.0.gem by gem2rpm -*- rpm-spec -*- -%define ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']") -%define gemdir %(ruby -rubygems -e 'puts Gem::dir' 2>/dev/null) -%define gemname cloud -%define geminstdir %{gemdir}/gems/%{gemname}-%{version} - -Summary: daemon for machine configuration -Name: rubygem-%{gemname} -Version: 0.1.1 -Release: 6%{?dist} -Group: Development/Languages -License: GPLv2+ or Ruby -URL: http://cloud.rubyforge.org -Source0: %{gemname}-%{version}.gem -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Requires: rubygems -Requires: rubygem(picnic) -Requires: rubygem(activesupport) -Requires: rubygem(reststop) >= 0.2.1 -Requires: rubygem(everest) -BuildRequires: rubygems -BuildArch: noarch -Provides: rubygem(%{gemname}) = %{version} - -%description -daemon for machine configuration - - -%prep - -%build - -%install -rm -rf %{buildroot} -mkdir -p %{buildroot}%{gemdir} %{buildroot}/etc/init.d %{buildroot}/etc/cloud -gem install --local --install-dir %{buildroot}%{gemdir} \ - --force --rdoc %{SOURCE0} -mkdir -p %{buildroot}/%{_bindir} -mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir} -mv %{buildroot}%{geminstdir}/extra/cloud.redhat %{buildroot}/etc/init.d/cloud -mv %{buildroot}%{geminstdir}/config.example.yml %{buildroot}/etc/cloud/config.yml -rmdir %{buildroot}%{gemdir}/bin -find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x - -%clean -rm -rf %{buildroot} - -%files -%{_bindir}/cloud -%{_bindir}/cloud-ctl -%{gemdir}/gems/%{gemname}-%{version}/ -%doc %{gemdir}/doc/%{gemname}-%{version} -%doc %{geminstdir}/History.txt -%doc %{geminstdir}/License.txt -%doc %{geminstdir}/Manifest.txt -%doc %{geminstdir}/README.txt -%doc %{geminstdir}/website/index.txt -%{gemdir}/cache/%{gemname}-%{version}.gem -%{gemdir}/specifications/%{gemname}-%{version}.gemspec -%config /etc/cloud/config.yml - -%defattr(755, root, root, -) -/etc/init.d/cloud - -%changelog -* Thu Apr 24 2008 - 0.1.0-1 -- Initial package diff --git a/cloud/lib/cloud.rb b/cloud/lib/cloud.rb deleted file mode 100644 index 70b4e19..0000000 --- a/cloud/lib/cloud.rb +++ /dev/null @@ -1,166 +0,0 @@ -$: << File.dirname(File.expand_path(__FILE__)) - -gem 'reststop', '~> 0.2' - -require 'yaml' -require 'fileutils' -require 'rubygems' -require 'picnic' -require 'reststop' -require 'everest' -require 'restr' -require 'xmlrpc/client' - -Camping.goes :Cloud -Cloud.picnic! - -module Cloud::Helpers - class Cobblerd - def initialize(repo) - @repo = repo - @xmlrpc = XMLRPC::Client.new2("http://#{@repo}:25152") - @token = @xmlrpc.call2("login", "cobbler", "password")[1] - end - - def _call(method, *args) - return @xmlrpc.call2(method, *args)[1] - end - - def distros - _call("get_distros", @token) - end - - def profiles - _call("get_profiles", @token) - end - - def systems - _call("get_systems", @token) - end - - def repos - _call("get_repos", @token) - end - - def distro(name) - _call("get_distro", name, @token) - end - - def distro_for_koan(name) - _call("get_distro_for_koan", name, @token) - end - - def profile(name) - _call("get_profile", name, @token) - end - - def profile_for_koan(name) - _call("get_profile_for_koan", name, @token) - end - - def system(name) - _call("get_system", name, @token) - end - - def system_for_koan(name) - _call("get_system_for_koan", name, @token) - end - - def repo(name) - _call("get_repo", name, @token) - end - - def repo_for_koan(name) - _call("get_repo_for_koan", name, @token) - end - - end -end - -module Cloud::Controllers - class Koan < REST 'koan' - # Retrieve the cobbler profile for the given profile name - def _get_cobbler_profile(system_name, repo) - cobblerd = Cloud::Helpers::Cobblerd.new(repo) - cobbler_system = cobblerd.system(system_name) - return cobblerd.profile(cobbler_system["profile"]) - end - - # Find the best host on which to create a VM that requires - # the given "disk_size" and "ram" - def _get_best_host(disk_size, ram) - return `func-find-resources -m #{ram} -d #{disk_size}`.split(':') - end - - # run the appropriate koan command to create the given "fqdn" - # on the given "host" and "vol_group" - def _koan(host, vol_group, fqdn, repo) - # Run the koan process - func_cmd = "func \"#{host}\" call virt install #{repo} #{fqdn} True #{fqdn.split('.')[0]} #{vol_group}" - puts `#{func_cmd}` - - # Make the new host autostart - func_cmd = "func \"#{host}\" call command run \"ln -s /etc/xen/#{fqdn.split('.')[0]} /etc/xen/auto/\"" - puts `#{func_cmd}` - end - - # POST /koan - def create - machine_fqdn = input.machine_fqdn - repo = input.repo - - cobbler_profile = _get_cobbler_profile(machine_fqdn, repo) - @host, vol_group = _get_best_host(cobbler_profile["virt_file_size"], cobbler_profile["virt_ram"]) - _koan(@host, vol_group, machine_fqdn, repo) - render :_koan - end - end -end - -module Cloud::Views - def initialize(*args) - super(*args) - @x = Builder::XmlMarkup.new(:indent => 1) - end - - module HTML - def layout - html do - head do - title 'Everest Cloud Controller' - #link :rel => 'stylesheet', :type => 'text/css', - #:href => self/'/styles.css', :media => 'screen' - end - body do - div.content do - self << yield - end - end - end - end - - def _koan - @host - end - end - default_format :HTML - - module YAML - CONTENT_TYPE = 'text/plain' - - def layout - yield - end - end - - module XML - def layout - yield - end - end -end - -# Required by picnic -def Cloud.create; end - -Cloud.start_picnic diff --git a/cloud/lib/cloud/version.rb b/cloud/lib/cloud/version.rb deleted file mode 100644 index cf75a7b..0000000 --- a/cloud/lib/cloud/version.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Cloud #:nodoc: - module VERSION #:nodoc: - MAJOR = 0 - MINOR = 1 - TINY = 1 - - STRING = [MAJOR, MINOR, TINY].join('.') - end -end diff --git a/cloud/log/debug.log b/cloud/log/debug.log deleted file mode 100644 index e69de29..0000000 diff --git a/cloud/script/console b/cloud/script/console deleted file mode 100755 index ef928b7..0000000 --- a/cloud/script/console +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env ruby -# File: script/console -irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' - -libs = " -r irb/completion" -# Perhaps use a console_lib to store any extra methods I may want available in the cosole -# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}" -libs << " -r #{File.dirname(__FILE__) + '/../lib/cloud.rb'}" -puts "Loading cloud gem" -exec "#{irb} #{libs} --simple-prompt" diff --git a/cloud/script/destroy b/cloud/script/destroy deleted file mode 100755 index e48464d..0000000 --- a/cloud/script/destroy +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby -APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) - -begin - require 'rubigen' -rescue LoadError - require 'rubygems' - require 'rubigen' -end -require 'rubigen/scripts/destroy' - -ARGV.shift if ['--help', '-h'].include?(ARGV[0]) -RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] -RubiGen::Scripts::Destroy.new.run(ARGV) diff --git a/cloud/script/generate b/cloud/script/generate deleted file mode 100755 index c27f655..0000000 --- a/cloud/script/generate +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby -APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) - -begin - require 'rubigen' -rescue LoadError - require 'rubygems' - require 'rubigen' -end -require 'rubigen/scripts/generate' - -ARGV.shift if ['--help', '-h'].include?(ARGV[0]) -RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] -RubiGen::Scripts::Generate.new.run(ARGV) diff --git a/cloud/script/txt2html b/cloud/script/txt2html deleted file mode 100755 index 8190daa..0000000 --- a/cloud/script/txt2html +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env ruby - -require 'rubygems' -begin - require 'newgem' -rescue LoadError - puts "\n\nGenerating the website requires the newgem RubyGem" - puts "Install: gem install newgem\n\n" - exit(1) -end -require 'redcloth' -require 'syntax/convertors/html' -require 'erb' -require File.dirname(__FILE__) + '/../lib/cloud/version.rb' - -version = Everestd::VERSION::STRING -download = 'http://rubyforge.org/projects/cloud' - -class Fixnum - def ordinal - # teens - return 'th' if (10..19).include?(self % 100) - # others - case self % 10 - when 1: return 'st' - when 2: return 'nd' - when 3: return 'rd' - else return 'th' - end - end -end - -class Time - def pretty - return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}" - end -end - -def convert_syntax(syntax, source) - return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^
|
$!,'') -end - -if ARGV.length >= 1 - src, template = ARGV - template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb') - -else - puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html") - exit! -end - -template = ERB.new(File.open(template).read) - -title = nil -body = nil -File.open(src) do |fsrc| - title_text = fsrc.readline - body_text = fsrc.read - syntax_items = [] - body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)!m){ - ident = syntax_items.length - element, syntax, source = $1, $2, $3 - syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}" - "syntax-temp-#{ident}" - } - title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip - body = RedCloth.new(body_text).to_html - body.gsub!(%r!(?:
)?syntax-temp-(\d+)(?:
)?!){ syntax_items[$1.to_i] } -end -stat = File.stat(src) -created = stat.ctime -modified = stat.mtime - -$stdout << template.result(binding) diff --git a/cloud/setup.rb b/cloud/setup.rb deleted file mode 100644 index 424a5f3..0000000 --- a/cloud/setup.rb +++ /dev/null @@ -1,1585 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2005 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -unless Errno.const_defined?(:ENOTEMPTY) # Windows? - module Errno - class ENOTEMPTY - # We do not raise this exception, implementation is not needed. - end - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted Windows' stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class ConfigTable - - include Enumerable - - def initialize(rbconfig) - @rbconfig = rbconfig - @items = [] - @table = {} - # options - @install_prefix = nil - @config_opt = nil - @verbose = true - @no_harm = false - end - - attr_accessor :install_prefix - attr_accessor :config_opt - - attr_writer :verbose - - def verbose? - @verbose - end - - attr_writer :no_harm - - def no_harm? - @no_harm - end - - def [](key) - lookup(key).resolve(self) - end - - def []=(key, val) - lookup(key).set val - end - - def names - @items.map {|i| i.name } - end - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or setup_rb_error "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def load_script(path, inst = nil) - if File.file?(path) - MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path - end - end - - def savefile - '.config' - end - - def load_savefile - begin - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - self[k] = v.strip - end - rescue Errno::ENOENT - setup_rb_error $!.message + "\n#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value? and i.value - end - } - end - - def load_standard_entries - standard_entries(@rbconfig).each do |ent| - add ent - end - end - - def standard_entries(rbconfig) - c = rbconfig - - rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) - - major = c['MAJOR'].to_i - minor = c['MINOR'].to_i - teeny = c['TEENY'].to_i - version = "#{major}.#{minor}" - - # ruby ver. >= 1.4.4? - newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - - if c['rubylibdir'] - # V > 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = c['rubylibdir'] - librubyverarch = c['archdir'] - siteruby = c['sitedir'] - siterubyver = c['sitelibdir'] - siterubyverarch = c['sitearchdir'] - elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = c['sitedir'] - siterubyver = "$siteruby/#{version}" - siterubyverarch = "$siterubyver/#{c['arch']}" - else - # V < 1.4.4 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" - siterubyver = siteruby - siterubyverarch = "$siterubyver/#{c['arch']}" - end - parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') - } - - if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] - else - makeprog = 'make' - end - - [ - ExecItem.new('installdirs', 'std/site/home', - 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ - {|val, table| - case val - when 'std' - table['rbdir'] = '$librubyver' - table['sodir'] = '$librubyverarch' - when 'site' - table['rbdir'] = '$siterubyver' - table['sodir'] = '$siterubyverarch' - when 'home' - setup_rb_error '$HOME was not set' unless ENV['HOME'] - table['prefix'] = ENV['HOME'] - table['rbdir'] = '$libdir/ruby' - table['sodir'] = '$libdir/ruby' - end - }, - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', parameterize.call(c['libdir']), - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for system configuration files'), - PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), - 'the directory for local state data'), - PathItem.new('libruby', 'path', libruby, - 'the directory for ruby libraries'), - PathItem.new('librubyver', 'path', librubyver, - 'the directory for standard ruby libraries'), - PathItem.new('librubyverarch', 'path', librubyverarch, - 'the directory for standard ruby extensions'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') - ] - end - private :standard_entries - - def load_multipackage_entries - multipackage_entries().each do |ent| - add ent - end - end - - def multipackage_entries - [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') - ] - end - private :multipackage_entries - - ALIASES = { - 'std-ruby' => 'librubyver', - 'stdruby' => 'librubyver', - 'rubylibdir' => 'librubyver', - 'archdir' => 'librubyverarch', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } - - def fixup - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - @items.freeze - @table.freeze - @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ - end - - def parse_opt(opt) - m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" - m.to_a[1,2] - end - - def dllext - @rbconfig['DLEXT'] - end - - def value_config?(name) - lookup(name).value? - end - - class Item - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value? - true - end - - def value - @value - end - - def resolve(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end - end - - class BoolItem < Item - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - case val - when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' - when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' - else - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - end - end - - class PathItem < Item - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end - end - - class ProgramItem < Item - def config_type - 'program' - end - end - - class SelectItem < Item - def initialize(name, selection, default, desc) - super - @ok = selection.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end - end - - class ExecItem < Item - def initialize(name, selection, desc, &block) - super name, selection, nil, desc - @ok = selection.split('/') - @action = block - end - - def config_type - 'exec' - end - - def value? - false - end - - def resolve(table) - setup_rb_error "$#{name()} wrongly used as option value" - end - - undef set - - def evaluate(val, table) - v = val.strip.downcase - unless @ok.include?(v) - setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" - end - @action.call v, table - end - end - - class PackageSelectionItem < Item - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end - end - - class MetaConfigEnvironment - def initialize(config, installer) - @config = config - @installer = installer - end - - def config_names - @config.names - end - - def config?(name) - @config.key?(name) - end - - def bool_config?(name) - @config.lookup(name).config_type == 'bool' - end - - def path_config?(name) - @config.lookup(name).config_type == 'path' - end - - def value_config?(name) - @config.lookup(name).config_type != 'exec' - end - - def add_config(item) - @config.add item - end - - def add_bool_config(name, default, desc) - @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - @config.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - @config.lookup(name).default = default - end - - def remove_config(name) - @config.remove(name) - end - - # For only multipackage - def packages - raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer - @installer.packages - end - - # For only multipackage - def declare_packages(list) - raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer - @installer.packages = list - end - end - -end # class ConfigTable - - -# This module requires: #verbose?, #no_harm? -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # Does not check '/', it's too abnormal. - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(path) - $stderr.puts "rm -f #{path}" if verbose? - return if no_harm? - force_remove_file path - end - - def rm_rf(path) - $stderr.puts "rm -rf #{path}" if verbose? - return if no_harm? - remove_tree path - end - - def remove_tree(path) - if File.symlink?(path) - remove_file path - elsif File.dir?(path) - remove_tree0 path - else - force_remove_file path - end - end - - def remove_tree0(path) - Dir.foreach(path) do |ent| - next if ent == '.' - next if ent == '..' - entpath = "#{path}/#{ent}" - if File.symlink?(entpath) - remove_file entpath - elsif File.dir?(entpath) - remove_tree0 entpath - else - force_remove_file entpath - end - end - begin - Dir.rmdir path - rescue Errno::ENOTEMPTY - # directory may not be empty - end - end - - def move_file(src, dest) - force_remove_file dest - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| - f.write File.binread(src) - } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def force_remove_file(path) - begin - remove_file path - rescue - end - end - - def remove_file(path) - File.chmod 0777, path - File.unlink path - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(*args) - $stderr.puts args.join(' ') if verbose? - system(*args) or raise RuntimeError, - "system(#{args.map{|a| a.inspect }.join(' ')}) failed" - end - - def ruby(*args) - command config('rubyprog'), *args - end - - def make(task = nil) - command(*[config('makeprog'), task].compact) - end - - def extdir?(dir) - File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") - end - - def files_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.file?("#{dir}/#{ent}") } - } - end - - DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) - - def directories_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT - } - end - -end - - -# This module requires: #srcdir_root, #objdir_root, #relpath -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - # obsolete: use metaconfig to change configuration - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file?(srcfile(path)) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.4.1' - Copyright = 'Copyright (c) 2000-2005 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'test', 'run all tests in test/' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - config = ConfigTable.new(load_rbconfig()) - config.load_standard_entries - config.load_multipackage_entries if multipackage? - config.fixup - klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) - klass.new(File.dirname($0), config).invoke - end - - def ToplevelInstaller.multipackage? - File.dir?(File.dirname($0) + '/packages') - end - - def ToplevelInstaller.load_rbconfig - if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - load File.expand_path(arg.split(/=/, 2)[1]) - $".push 'rbconfig.rb' - else - require 'rbconfig' - end - ::Config::CONFIG - end - - def initialize(ardir_root, config) - @ardir = File.expand_path(ardir_root) - @config = config - # cache - @valid_task_re = nil - end - - def config(key) - @config[key] - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - case task - when 'config', 'test' - ; - when 'clean', 'distclean' - @config.load_savefile if File.exist?(@config.savefile) - else - @config.load_savefile - end - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig" - end - - def init_installers - @installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) - return arg - when '-q', '--quiet' - @config.verbose = false - when '--verbose' - @config.verbose = true - when '--help' - print_usage $stdout - exit 0 - when '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - when '--copyright' - puts Copyright - exit 0 - else - setup_rb_error "unknown global option '#{arg}'" - end - end - nil - end - - def valid_task?(t) - valid_task_re() =~ t - end - - def valid_task_re - @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ - end - - def parsearg_no_options - unless ARGV.empty? - task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) - setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_test parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - evalopt = [] - set = [] - @config.config_opt = [] - while i = ARGV.shift - if /\A--?\z/ =~ i - @config.config_opt = ARGV.dup - break - end - name, value = *@config.parse_opt(i) - if @config.value_config?(name) - @config[name] = value - else - evalopt.push [name, value] - end - set.push name - end - evalopt.each do |name, value| - @config.lookup(name).evaluate value, @config - end - # Check if configuration is valid - set.each do |n| - @config[n] if @config.value_config?(n) - end - end - - def parsearg_install - @config.no_harm = false - @config.install_prefix = '' - while a = ARGV.shift - case a - when '--no-harm' - @config.no_harm = true - when /\A--prefix=/ - path = a.split(/=/, 2)[1] - path = File.expand_path(path) unless path[0,1] == '/' - @config.install_prefix = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} " - out.puts " ruby #{File.basename $0} [] []" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, ' --help', 'print this message' - out.printf fmt, ' --version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - @config.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_test - @installer.exec_test - end - - def exec_show - @config.each do |i| - printf "%-20s %s\n", i.name, i.value if i.value? - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end # class ToplevelInstaller - - -class ToplevelInstallerMulti < ToplevelInstaller - - include FileOperations - - def initialize(ardir_root, config) - super - @packages = directories_of("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig", self - @packages.each do |name| - @config.load_script "#{@ardir}/packages/#{name}/metaconfig" - end - end - - attr_reader :packages - - def packages=(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_test - run_hook 'pre-test' - each_selected_installers {|inst| inst.exec_test } - run_hook 'post-test' - end - - def exec_clean - rm_f @config.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f @config.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if verbose? - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def run_hook(id) - @root_installer.run_hook id - end - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - -end # class ToplevelInstallerMulti - - -class Installer - - FILETYPES = %w( bin lib ext data conf man ) - - include FileOperations - include HookScriptAPI - - def initialize(config, srcroot, objroot) - @config = config - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - def noop(rel) - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # Config Access - # - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - - def verbose_off - begin - save, @config.verbose = @config.verbose?, false - yield - ensure - @config.verbose = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - alias config_dir_bin noop - alias config_dir_lib noop - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - alias config_dir_data noop - alias config_dir_conf noop - alias config_dir_man noop - - def extconf - ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - files_of(curr_srcdir()).each do |fname| - update_shebang_line "#{curr_srcdir()}/#{fname}" - end - end - - alias setup_dir_lib noop - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - alias setup_dir_data noop - alias setup_dir_conf noop - alias setup_dir_man noop - - def update_shebang_line(path) - return if no_harm? - return if config('shebang') == 'never' - old = Shebang.load(path) - if old - $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 - new = new_shebang(old) - return if new.to_s == old.to_s - else - return unless config('shebang') == 'all' - new = Shebang.new(config('rubypath')) - end - $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? - open_atomic_writer(path) {|output| - File.open(path, 'rb') {|f| - f.gets if old # discard - output.puts new.to_s - output.print f.read - } - } - end - - def new_shebang(old) - if /\Aruby/ =~ File.basename(old.cmd) - Shebang.new(config('rubypath'), old.args) - elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' - Shebang.new(config('rubypath'), old.args[1..-1]) - else - return old unless config('shebang') == 'all' - Shebang.new(config('rubypath')) - end - end - - def open_atomic_writer(path, &block) - tmpfile = File.basename(path) + '.tmp' - begin - File.open(tmpfile, 'wb', &block) - File.rename tmpfile, File.basename(path) - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - class Shebang - def Shebang.load(path) - line = nil - File.open(path) {|f| - line = f.gets - } - return nil unless /\A#!/ =~ line - parse(line) - end - - def Shebang.parse(line) - cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') - new(cmd, args) - end - - def initialize(cmd, args = []) - @cmd = cmd - @args = args - end - - attr_reader :cmd - attr_reader :args - - def to_s - "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") - end - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files rubyextentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_dir_conf(rel) - # FIXME: should not remove current config files - # (rename previous file to .old/.org) - install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 - end - - def install_dir_man(rel) - install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @config.install_prefix - list.each do |fname| - install fname, dest, mode, @config.install_prefix - end - end - - def libfiles - glob_reject(%w(*.y *.output), targetfiles()) - end - - def rubyextentions(dir) - ents = glob_select("*.#{@config.dllext}", targetfiles()) - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - ents - end - - def targetfiles - mapdir(existfiles() - hookfiles()) - end - - def mapdir(ents) - ents.map {|ent| - if File.exist?(ent) - then ent # objdir - else "#{curr_srcdir()}/#{ent}" # srcdir - end - } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - JUNK_FILES = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - - def existfiles - glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def glob_select(pat, ents) - re = globs2re([pat]) - ents.select {|ent| re =~ ent } - end - - def glob_reject(pats, ents) - re = globs2re(pats) - ents.reject {|ent| re =~ ent } - end - - GLOB2REGEX = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - - def globs2re(pats) - /\A(?:#{ - pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') - })\z/ - end - - # - # TASK test - # - - TESTDIR = 'test' - - def exec_test - unless File.directory?('test') - $stderr.puts 'no test in this package' if verbose? - return - end - $stderr.puts 'Running tests...' if verbose? - begin - require 'test/unit' - rescue LoadError - setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' - end - runner = Test::Unit::AutoRunner.new(true) - runner.to_run << TESTDIR - runner.run - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias clean_dir_bin noop - alias clean_dir_lib noop - alias clean_dir_data noop - alias clean_dir_conf noop - alias clean_dir_man noop - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias distclean_dir_bin noop - alias distclean_dir_lib noop - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - alias distclean_dir_data noop - alias distclean_dir_conf noop - alias distclean_dir_man noop - - # - # Traversing - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if type == 'ext' and config('without-ext') == 'yes' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - directories_of(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - - def run_hook(id) - path = [ "#{curr_srcdir()}/#{id}", - "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } - return unless path - begin - instance_eval File.read(path), path, 1 - rescue - raise if $DEBUG - setup_rb_error "hook #{path} failed:\n" + $!.message - end - end - -end # class Installer - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -if $0 == __FILE__ - begin - ToplevelInstaller.invoke - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end diff --git a/cloud/spec/cloud_spec.rb b/cloud/spec/cloud_spec.rb deleted file mode 100644 index a52055a..0000000 --- a/cloud/spec/cloud_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require File.dirname(__FILE__) + '/spec_helper.rb' - -# Time to add your specs! -# http://rspec.info/ -describe "Place your specs here" do - - it "find this spec in spec directory" do - violated "Be sure to write your specs" - end - -end diff --git a/cloud/spec/spec.opts b/cloud/spec/spec.opts deleted file mode 100644 index 53607ea..0000000 --- a/cloud/spec/spec.opts +++ /dev/null @@ -1 +0,0 @@ ---colour diff --git a/cloud/spec/spec_helper.rb b/cloud/spec/spec_helper.rb deleted file mode 100644 index 63ce735..0000000 --- a/cloud/spec/spec_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -begin - require 'spec' -rescue LoadError - require 'rubygems' - gem 'rspec' - require 'spec' -end - -$:.unshift(File.dirname(__FILE__) + '/../lib') -require 'cloud' diff --git a/cloud/tasks/deployment.rake b/cloud/tasks/deployment.rake deleted file mode 100644 index 2f43742..0000000 --- a/cloud/tasks/deployment.rake +++ /dev/null @@ -1,34 +0,0 @@ -desc 'Release the website and new gem version' -task :deploy => [:check_version, :website, :release] do - puts "Remember to create SVN tag:" - puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " + - "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} " - puts "Suggested comment:" - puts "Tagging release #{CHANGES}" -end - -desc 'Runs tasks website_generate and install_gem as a local deployment of the gem' -task :local_deploy => [:website_generate, :install_gem] - -task :check_version do - unless ENV['VERSION'] - puts 'Must pass a VERSION=x.y.z release version' - exit - end - unless ENV['VERSION'] == VERS - puts "Please update your version.rb to match the release version, currently #{VERS}" - exit - end -end - -desc 'Install the package as a gem, without generating documentation(ri/rdoc)' -task :install_gem_no_doc => [:clean, :package] do - sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri" -end - -namespace :manifest do - desc 'Recreate Manifest.txt to include ALL files' - task :refresh do - `rake check_manifest | patch -p0 > Manifest.txt` - end -end \ No newline at end of file diff --git a/cloud/tasks/environment.rake b/cloud/tasks/environment.rake deleted file mode 100644 index 691ed3b..0000000 --- a/cloud/tasks/environment.rake +++ /dev/null @@ -1,7 +0,0 @@ -task :ruby_env do - RUBY_APP = if RUBY_PLATFORM =~ /java/ - "jruby" - else - "ruby" - end unless defined? RUBY_APP -end diff --git a/cloud/tasks/rspec.rake b/cloud/tasks/rspec.rake deleted file mode 100644 index 2415fa4..0000000 --- a/cloud/tasks/rspec.rake +++ /dev/null @@ -1,21 +0,0 @@ -begin - require 'spec' -rescue LoadError - require 'rubygems' - require 'spec' -end -begin - require 'spec/rake/spectask' -rescue LoadError - puts <<-EOS -To use rspec for testing you must install rspec gem: - gem install rspec -EOS - exit(0) -end - -desc "Run the specs under spec/models" -Spec::Rake::SpecTask.new do |t| - t.spec_opts = ['--options', "spec/spec.opts"] - t.spec_files = FileList['spec/**/*_spec.rb'] -end diff --git a/cloud/tasks/website.rake b/cloud/tasks/website.rake deleted file mode 100644 index 93e03fa..0000000 --- a/cloud/tasks/website.rake +++ /dev/null @@ -1,17 +0,0 @@ -desc 'Generate website files' -task :website_generate => :ruby_env do - (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt| - sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} } - end -end - -desc 'Upload website files to rubyforge' -task :website_upload do - host = "#{rubyforge_username}@rubyforge.org" - remote_dir = "/var/www/gforge-projects/#{PATH}/" - local_dir = 'website' - sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}} -end - -desc 'Generate and upload website files' -task :website => [:website_generate, :website_upload, :publish_docs] diff --git a/cloud/website/index.html b/cloud/website/index.html deleted file mode 100644 index e9a483a..0000000 --- a/cloud/website/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - cloud - - - -

This page has not yet been created for RubyGem cloud

-

To the developer: To generate it, update website/index.txt and run the rake task website to generate this index.html file.

- - diff --git a/cloud/website/index.txt b/cloud/website/index.txt deleted file mode 100644 index f7fdf9d..0000000 --- a/cloud/website/index.txt +++ /dev/null @@ -1,39 +0,0 @@ -h1. cloud - -h1. → 'cloud' - - -h2. What - - -h2. Installing - -
sudo gem install cloud
- -h2. The basics - - -h2. Demonstration of usage - - - -h2. Forum - -"http://groups.google.com/group/cloud":http://groups.google.com/group/cloud - -TODO - create Google Group - cloud - -h2. How to submit patches - -Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above. - -The trunk repository is svn://rubyforge.org/var/svn/cloud/trunk for anonymous access. - -h2. License - -This code is free to use under the terms of the MIT license. - -h2. Contact - -Comments are welcome. Send an email to "Brenton Leanhardt":mailto:bleanhar@redhat.com via the "forum":http://groups.google.com/group/cloud - diff --git a/cloud/website/javascripts/rounded_corners_lite.inc.js b/cloud/website/javascripts/rounded_corners_lite.inc.js deleted file mode 100644 index afc3ea3..0000000 --- a/cloud/website/javascripts/rounded_corners_lite.inc.js +++ /dev/null @@ -1,285 +0,0 @@ - - /**************************************************************** - * * - * curvyCorners * - * ------------ * - * * - * This script generates rounded corners for your divs. * - * * - * Version 1.2.9 * - * Copyright (c) 2006 Cameron Cooke * - * By: Cameron Cooke and Tim Hutchison. * - * * - * * - * Website: http://www.curvycorners.net * - * Email: info@totalinfinity.com * - * Forum: http://www.curvycorners.net/forum/ * - * * - * * - * This library is free software; you can redistribute * - * it and/or modify it under the terms of the GNU * - * Lesser General Public License as published by the * - * Free Software Foundation; either version 2.1 of the * - * License, or (at your option) any later version. * - * * - * This library 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 Lesser General Public * - * License for more details. * - * * - * You should have received a copy of the GNU Lesser * - * General Public License along with this library; * - * Inc., 59 Temple Place, Suite 330, Boston, * - * MA 02111-1307 USA * - * * - ****************************************************************/ - -var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners() -{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string") -{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);} -else -{ var startIndex = 1; var boxCol = arguments;} -var curvyCornersCol = new Array(); if(arguments[0].validTags) -var validElements = arguments[0].validTags; else -var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++) -{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false) -{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);} -} -this.objects = curvyCornersCol; this.applyCornersToAll = function() -{ for(var x = 0, k = this.objects.length; x < k; x++) -{ this.objects[x].applyCorners();} -} -} -function curvyObject() -{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0) -this.box.innerHTML = ""; this.applyCorners = function() -{ for(var t = 0; t < 2; t++) -{ switch(t) -{ case 0: -if(this.settings.tl || this.settings.tr) -{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);} -break; case 1: -if(this.settings.bl || this.settings.br) -{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);} -break;} -} -if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners) -{ if(i > -1 < 4) -{ var cc = corners[i]; if(!this.settings[cc]) -{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null)) -{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "") -newCorner.style.backgroundColor = this.boxColour; else -newCorner.style.backgroundImage = this.backgroundImage; switch(cc) -{ case "tl": -newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr": -newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl": -newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br": -newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px" -newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;} -} -} -else -{ if(this.masterCorners[this.settings[cc].radius]) -{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);} -else -{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++) -{ if((intx +1) >= borderRadius) -var y1 = -1; else -var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j) -{ if((intx) >= borderRadius) -var y2 = -1; else -var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j) -var y3 = -1; else -var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);} -if((intx) >= j) -var y4 = -1; else -var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j) -{ for(var inty = (y1 + 1); inty < y2; inty++) -{ if(this.settings.antiAlias) -{ if(this.backgroundImage != "") -{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30) -{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);} -else -{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);} -} -else -{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);} -} -} -if(this.settings.antiAlias) -{ if(y3 >= y2) -{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);} -} -else -{ if(y3 >= y1) -{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);} -} -var outsideColour = this.borderColour;} -else -{ var outsideColour = this.boxColour; var y3 = y1;} -if(this.settings.antiAlias) -{ for(var inty = (y3 + 1); inty < y4; inty++) -{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);} -} -} -this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);} -if(cc != "br") -{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++) -{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";} -if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";} -switch(cc) -{ case "tr": -pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl": -pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl": -pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;} -} -} -} -if(newCorner) -{ switch(cc) -{ case "tl": -if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr": -if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl": -if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br": -if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;} -} -} -} -var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius) -radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff) -{ if(z == "t" || z == "b") -{ if(radiusDiff[z]) -{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px" -newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType) -{ case "tl": -newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr": -newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl": -newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br": -newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;} -} -var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z) -{ case "t": -if(this.topContainer) -{ if(this.settings.tl.radius && this.settings.tr.radius) -{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "") -newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);} -this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";} -break; case "b": -if(this.bottomContainer) -{ if(this.settings.bl.radius && this.settings.br.radius) -{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "") -newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);} -} -break;} -} -} -if(this.settings.autoPad == true && this.boxPadding > 0) -{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding) -contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding) -contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);} -} -this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) -{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "") -{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";} -else -{ pixel.style.backgroundColor = colour;} -if (transAmount != 100) -setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);} -} -function insertAfter(parent, node, referenceNode) -{ parent.insertBefore(node, referenceNode.nextSibling);} -function BlendColour(Col1, Col2, Col1Fraction) -{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);} -function IntToHex(strNum) -{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;} -function MakeHex(x) -{ if((x >= 0) && (x <= 9)) -{ return x;} -else -{ switch(x) -{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";} -} -} -function pixelFraction(x, y, r) -{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1))) -{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;} -var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1))) -{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;} -var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1))) -{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;} -var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1))) -{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;} -switch (whatsides) -{ case "LeftRight": -pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight": -pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom": -pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom": -pixelfraction = (yvalues[0]*xvalues[1])/2; break; default: -pixelfraction = 1;} -return pixelfraction;} -function rgb2Hex(rgbColour) -{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);} -catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");} -return hexColour;} -function rgb2Array(rgbColour) -{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;} -function setOpacity(obj, opacity) -{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME") -{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";} -else if(typeof(obj.style.opacity) != "undefined") -{ obj.style.opacity = opacity/100;} -else if(typeof(obj.style.MozOpacity) != "undefined") -{ obj.style.MozOpacity = opacity/100;} -else if(typeof(obj.style.filter) != "undefined") -{ obj.style.filter = "alpha(opacity:" + opacity + ")";} -else if(typeof(obj.style.KHTMLOpacity) != "undefined") -{ obj.style.KHTMLOpacity = opacity/100;} -} -function inArray(array, value) -{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;} -return false;} -function inArrayKey(array, value) -{ for(key in array){ if(key === value) return true;} -return false;} -function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;} -else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;} -else { elm['on' + evType] = fn;} -} -function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");} -} -function format_colour(colour) -{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent") -{ if(colour.substr(0, 3) == "rgb") -{ returnColour = rgb2Hex(colour);} -else if(colour.length == 4) -{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);} -else -{ returnColour = colour;} -} -return returnColour;} -function get_style(obj, property, propertyNS) -{ try -{ if(obj.currentStyle) -{ var returnVal = eval("obj.currentStyle." + property);} -else -{ if(isSafari && obj.style.display == "none") -{ obj.style.display = ""; var wasHidden = true;} -var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden) -{ obj.style.display = "none";} -} -} -catch(e) -{ } -return returnVal;} -function getElementsByClass(searchClass, node, tag) -{ var classElements = new Array(); if(node == null) -node = document; if(tag == null) -tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++) -{ if(pattern.test(els[i].className)) -{ classElements[j] = els[i]; j++;} -} -return classElements;} -function newCurvyError(errorMessage) -{ return new Error("curvyCorners Error:\n" + errorMessage) -} diff --git a/cloud/website/stylesheets/screen.css b/cloud/website/stylesheets/screen.css deleted file mode 100644 index 2c84cd0..0000000 --- a/cloud/website/stylesheets/screen.css +++ /dev/null @@ -1,138 +0,0 @@ -body { - background-color: #E1D1F1; - font-family: "Georgia", sans-serif; - font-size: 16px; - line-height: 1.6em; - padding: 1.6em 0 0 0; - color: #333; -} -h1, h2, h3, h4, h5, h6 { - color: #444; -} -h1 { - font-family: sans-serif; - font-weight: normal; - font-size: 4em; - line-height: 0.8em; - letter-spacing: -0.1ex; - margin: 5px; -} -li { - padding: 0; - margin: 0; - list-style-type: square; -} -a { - color: #5E5AFF; - background-color: #DAC; - font-weight: normal; - text-decoration: underline; -} -blockquote { - font-size: 90%; - font-style: italic; - border-left: 1px solid #111; - padding-left: 1em; -} -.caps { - font-size: 80%; -} - -#main { - width: 45em; - padding: 0; - margin: 0 auto; -} -.coda { - text-align: right; - color: #77f; - font-size: smaller; -} - -table { - font-size: 90%; - line-height: 1.4em; - color: #ff8; - background-color: #111; - padding: 2px 10px 2px 10px; - border-style: dashed; -} - -th { - color: #fff; -} - -td { - padding: 2px 10px 2px 10px; -} - -.success { - color: #0CC52B; -} - -.failed { - color: #E90A1B; -} - -.unknown { - color: #995000; -} -pre, code { - font-family: monospace; - font-size: 90%; - line-height: 1.4em; - color: #ff8; - background-color: #111; - padding: 2px 10px 2px 10px; -} -.comment { color: #aaa; font-style: italic; } -.keyword { color: #eff; font-weight: bold; } -.punct { color: #eee; font-weight: bold; } -.symbol { color: #0bb; } -.string { color: #6b4; } -.ident { color: #ff8; } -.constant { color: #66f; } -.regex { color: #ec6; } -.number { color: #F99; } -.expr { color: #227; } - -#version { - float: right; - text-align: right; - font-family: sans-serif; - font-weight: normal; - background-color: #B3ABFF; - color: #141331; - padding: 15px 20px 10px 20px; - margin: 0 auto; - margin-top: 15px; - border: 3px solid #141331; -} - -#version .numbers { - display: block; - font-size: 4em; - line-height: 0.8em; - letter-spacing: -0.1ex; - margin-bottom: 15px; -} - -#version p { - text-decoration: none; - color: #141331; - background-color: #B3ABFF; - margin: 0; - padding: 0; -} - -#version a { - text-decoration: none; - color: #141331; - background-color: #B3ABFF; -} - -.clickable { - cursor: pointer; - cursor: hand; -} - diff --git a/cloud/website/template.html.erb b/cloud/website/template.html.erb deleted file mode 100644 index b279c36..0000000 --- a/cloud/website/template.html.erb +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - <%= title %> - - - - - - -
- -

<%= title %>

-
-

Get Version

- <%= version %> -
- <%= body %> -

- Brenton Leanhardt, <%= modified.pretty %>
- Theme extended from Paul Battley -

-
- - - - - diff --git a/cloudmasterd/.gitignore b/cloudmasterd/.gitignore new file mode 100644 index 0000000..3567727 --- /dev/null +++ b/cloudmasterd/.gitignore @@ -0,0 +1,2 @@ +pkg* +*.gem diff --git a/cloudmasterd/History.txt b/cloudmasterd/History.txt new file mode 100644 index 0000000..59ce905 --- /dev/null +++ b/cloudmasterd/History.txt @@ -0,0 +1,4 @@ +== 0.0.1 2008-04-09 + +* 1 major enhancement: + * Initial release diff --git a/cloudmasterd/License.txt b/cloudmasterd/License.txt new file mode 100644 index 0000000..7a2ed3c --- /dev/null +++ b/cloudmasterd/License.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008 Brenton Leanhardt + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/cloudmasterd/Manifest.txt b/cloudmasterd/Manifest.txt new file mode 100644 index 0000000..44bf240 --- /dev/null +++ b/cloudmasterd/Manifest.txt @@ -0,0 +1,31 @@ +History.txt +License.txt +Manifest.txt +README.txt +Rakefile +bin/cloudmasterd +bin/cloudmasterd-ctl +config.example.yml +config/hoe.rb +config/requirements.rb +extra/cloudmasterd.redhat +lib/cloudmasterd.rb +lib/cloudmasterd/version.rb +log/debug.log +script/console +script/destroy +script/generate +script/txt2html +setup.rb +spec/cloudmasterd.rb +spec/spec.opts +spec/spec_helper.rb +tasks/deployment.rake +tasks/environment.rake +tasks/rspec.rake +tasks/website.rake +website/index.html +website/index.txt +website/javascripts/rounded_corners_lite.inc.js +website/stylesheets/screen.css +website/template.html.erb diff --git a/cloudmasterd/README.txt b/cloudmasterd/README.txt new file mode 100644 index 0000000..6add78b --- /dev/null +++ b/cloudmasterd/README.txt @@ -0,0 +1,48 @@ += cloudmasterd + +* FIX (url) + +== DESCRIPTION: + +FIX (describe your package) + +== FEATURES/PROBLEMS: + +* FIX (list of features or problems) + +== SYNOPSIS: + + FIX (code sample of usage) + +== REQUIREMENTS: + +* FIX (list of requirements) + +== INSTALL: + +* FIX (sudo gem install, anything else) + +== LICENSE: + +(The MIT License) + +Copyright (c) 2008 FIX + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cloudmasterd/Rakefile b/cloudmasterd/Rakefile new file mode 100644 index 0000000..e469154 --- /dev/null +++ b/cloudmasterd/Rakefile @@ -0,0 +1,4 @@ +require 'config/requirements' +require 'config/hoe' # setup Hoe + all gem configuration + +Dir['tasks/**/*.rake'].each { |rake| load rake } \ No newline at end of file diff --git a/cloudmasterd/bin/cloudmasterd b/cloudmasterd/bin/cloudmasterd new file mode 100644 index 0000000..21b1f22 --- /dev/null +++ b/cloudmasterd/bin/cloudmasterd @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# +# Created by Brenton Leanhardt on 2008-4-9. +# Copyright (c) 2008. All rights reserved. + +require 'rubygems' +require 'picnic/cli' + +cli = Picnic::Cli.new( + 'cloudmasterd', + :app_path => File.expand_path(File.dirname(File.expand_path(__FILE__))) +) + +cli.handle_cli_input diff --git a/cloudmasterd/bin/cloudmasterd-ctl b/cloudmasterd/bin/cloudmasterd-ctl new file mode 100644 index 0000000..5a79c24 --- /dev/null +++ b/cloudmasterd/bin/cloudmasterd-ctl @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'picnic/service_control' + +ctl = Picnic::ServiceControl.new('cloudmasterd') + +ctl.handle_cli_input diff --git a/cloudmasterd/config.example.yml b/cloudmasterd/config.example.yml new file mode 100644 index 0000000..fdfc900 --- /dev/null +++ b/cloudmasterd/config.example.yml @@ -0,0 +1,88 @@ +# AN IMPORTANT NOTE ABOUT YAML CONFIGURATION FILES: +# !!! Be sure to use spaces instead of tabs for indentation, as YAML is very +# !!! sensitive to white-space inconsistencies! + +##### HTTP SERVER ##################################################################### + +# Under what HTTP environment are you running the Everestd server? The following methods +# are currently supported: +# +# webrick -- simple stand-alone HTTP server; this is the default method +# mongrel -- fast stand-alone HTTP server; much faster than webrick, but +# you'll have to first install the mongrel gem +# + +### webrick example + +server: webrick +port: 8107 + +### webrick SSL example + +#server: webrick +#port: 443 +#ssl_cert: /path/to/your/ssl.pem + +# if the private key is separate from cert: +#ssl_key: /path/to/your/private_key.pem + + +### mongrel example + +#server: mongrel +#port: 8106 + +# It is possible to run mongrel over SSL, but you will need to use a reverse proxy +# (try Pound or Apache). + + +##### DATABASE ######################################################################## + +# The Blog needs a database to store its records. +# +# By default, we use MySQL, since it is widely used and does not require any additional +# ruby libraries besides ActiveRecord. +# +# With MySQL, your config would be something like the following: +# (be sure to create the blog database in MySQL beforehand, +# i.e. `mysqladmin -u root create blog`) + +#database: +# adapter: mysql +# database: blog +# username: root +# password: +# host: localhost + + +# Instead of MySQL you can use SQLite3, PostgreSQL, MSSQL, or anything else supported +# by ActiveRecord. +# +# If you do not have a database server available, you can try using the SQLite3 +# back-end. SQLite3 does not require it's own server. Instead all data is stored +# in local files. For SQLite3, your configuration would look something like the +# following (don't forget to install the 'sqlite3-ruby' gem first!): +# +#database: +# adapter: sqlite3 +# dbfile: /var/lib/blog.db + +##### EVERESTD ######################################################################## + + +##### LOGGING ######################################################################### + +# This log is where you'll want to look in case of problems. +# +# By default, we will try to create a log file named 'blog.log' in the current +# directory (the directory where you're running the blog from). A better place to put +# the log is in /var/log, but you will have to run blog as root or otherwise give +# it permissions. +# +# Set the level to DEBUG if you want more detailed logging. Other options are +# INFO, WARN, and ERROR (DEBUG is most verbose, ERROR is least). + +log: + level: DEBUG + file: /var/log/cloudmasterd.log +# level: INFO diff --git a/cloudmasterd/config/hoe.rb b/cloudmasterd/config/hoe.rb new file mode 100644 index 0000000..f76e707 --- /dev/null +++ b/cloudmasterd/config/hoe.rb @@ -0,0 +1,70 @@ +require 'cloudmasterd/version' + +AUTHOR = 'Brenton Leanhardt' # can also be an array of Authors +EMAIL = "bleanhar@redhat.com" +DESCRIPTION = "daemon for machine configuration" +GEM_NAME = 'cloudmasterd' # what ppl will type to install your gem +RUBYFORGE_PROJECT = 'cloudmasterd' # The unix name for your project +HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org" +DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}" + +@config_file = "~/.rubyforge/user-config.yml" +@config = nil +RUBYFORGE_USERNAME = "unknown" +def rubyforge_username + unless @config + begin + @config = YAML.load(File.read(File.expand_path(@config_file))) + rescue + puts <<-EOS +ERROR: No rubyforge config file found: #{@config_file} +Run 'rubyforge setup' to prepare your env for access to Rubyforge + - See http://newgem.rubyforge.org/rubyforge.html for more details + EOS + exit + end + end + RUBYFORGE_USERNAME.replace @config["username"] +end + + +REV = nil +# UNCOMMENT IF REQUIRED: +# REV = YAML.load(`svn info`)['Revision'] +VERS = Everestd::VERSION::STRING + (REV ? ".#{REV}" : "") +RDOC_OPTS = ['--quiet', '--title', 'cloudmasterd documentation', + "--opname", "index.html", + "--line-numbers", + "--main", "README", + "--inline-source"] + +class Hoe + def extra_deps + @extra_deps.reject! { |x| Array(x).first == 'hoe' } + @extra_deps + end +end + +# Generate all the Rake tasks +# Run 'rake -T' to see list of generated tasks (from gem root directory) +$hoe = Hoe.new(GEM_NAME, VERS) do |p| + p.developer(AUTHOR, EMAIL) + p.description = DESCRIPTION + p.summary = DESCRIPTION + p.url = HOMEPATH + p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT + p.test_globs = ["test/**/test_*.rb"] + p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] + + # == Optional + p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n") + p.extra_deps = ['picnic', 'activesupport', ['reststop', '>= 0.2.1'], 'everest'] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ] + + p.spec_extras = {:executables => ['cloudmasterd', 'cloudmasterd-ctl']} # A hash of extra values to set in the gemspec. + +end + +CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n") +PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}" +$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc') +$hoe.rsync_args = '-av --delete --ignore-errors' diff --git a/cloudmasterd/config/requirements.rb b/cloudmasterd/config/requirements.rb new file mode 100644 index 0000000..9292b69 --- /dev/null +++ b/cloudmasterd/config/requirements.rb @@ -0,0 +1,15 @@ +require 'fileutils' +include FileUtils + +require 'rubygems' +%w[rake hoe newgem rubigen].each do |req_gem| + begin + require req_gem + rescue LoadError + puts "This Rakefile requires the '#{req_gem}' RubyGem." + puts "Installation: gem install #{req_gem} -y" + exit + end +end + +$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib])) diff --git a/cloudmasterd/extra/cloudmasterd.redhat b/cloudmasterd/extra/cloudmasterd.redhat new file mode 100755 index 0000000..5059c72 --- /dev/null +++ b/cloudmasterd/extra/cloudmasterd.redhat @@ -0,0 +1,43 @@ +#!/bin/bash +# +# cloudmasterd: Init script for Cloud daemon. +# +# chkconfig: 35 91 03 +# +# description: Deamon for creating cloud machines in an everest framework +# +# +# + +# Source function library. +. /etc/init.d/functions + +CTL=cloudmasterd-ctl + +[ -z "$HOME" ] && export HOME=/ + +case "$1" in + start) + echo -n $"Starting cloudmasterd: " + $CTL start + RETVAL=$? + ;; + stop) + echo -n $"Stopping cloudmasterd: " + $CTL stop + RETVAL=$? + ;; + restart) + $0 stop + $0 start + ;; + status) + $CTL status + RETVAL=$? + ;; + *) + echo $"Usage: $0 {start|stop|status|restart}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/cloudmasterd/extra/cloudmasterd.spec b/cloudmasterd/extra/cloudmasterd.spec new file mode 100644 index 0000000..704c618 --- /dev/null +++ b/cloudmasterd/extra/cloudmasterd.spec @@ -0,0 +1,67 @@ +# Generated from cloudmasterd-0.1.0.gem by gem2rpm -*- rpm-spec -*- +%define ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']") +%define gemdir %(ruby -rubygems -e 'puts Gem::dir' 2>/dev/null) +%define gemname cloudmasterd +%define geminstdir %{gemdir}/gems/%{gemname}-%{version} + +Summary: daemon for machine configuration +Name: rubygem-%{gemname} +Version: 0.1.1 +Release: 6%{?dist} +Group: Development/Languages +License: GPLv2+ or Ruby +URL: http://cloudmasterd.rubyforge.org +Source0: %{gemname}-%{version}.gem +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Requires: rubygems +Requires: rubygem(picnic) +Requires: rubygem(activesupport) +Requires: rubygem(reststop) >= 0.2.1 +Requires: rubygem(everest) +BuildRequires: rubygems +BuildArch: noarch +Provides: rubygem(%{gemname}) = %{version} + +%description +daemon for machine configuration + + +%prep + +%build + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{gemdir} %{buildroot}/etc/init.d %{buildroot}/etc/cloudmasterd +gem install --local --install-dir %{buildroot}%{gemdir} \ + --force --rdoc %{SOURCE0} +mkdir -p %{buildroot}/%{_bindir} +mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir} +mv %{buildroot}%{geminstdir}/extra/cloudmasterd.redhat %{buildroot}/etc/init.d/cloudmasterd +mv %{buildroot}%{geminstdir}/config.example.yml %{buildroot}/etc/cloudmasterd/config.yml +rmdir %{buildroot}%{gemdir}/bin +find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x + +%clean +rm -rf %{buildroot} + +%files +%{_bindir}/cloudmasterd +%{_bindir}/cloudmasterd-ctl +%{gemdir}/gems/%{gemname}-%{version}/ +%doc %{gemdir}/doc/%{gemname}-%{version} +%doc %{geminstdir}/History.txt +%doc %{geminstdir}/License.txt +%doc %{geminstdir}/Manifest.txt +%doc %{geminstdir}/README.txt +%doc %{geminstdir}/website/index.txt +%{gemdir}/cache/%{gemname}-%{version}.gem +%{gemdir}/specifications/%{gemname}-%{version}.gemspec +%config /etc/cloudmasterd/config.yml + +%defattr(755, root, root, -) +/etc/init.d/cloudmasterd + +%changelog +* Thu Apr 24 2008 - 0.1.0-1 +- Initial package diff --git a/cloudmasterd/lib/cloudmasterd.rb b/cloudmasterd/lib/cloudmasterd.rb new file mode 100644 index 0000000..14f9fcd --- /dev/null +++ b/cloudmasterd/lib/cloudmasterd.rb @@ -0,0 +1,170 @@ +$: << File.dirname(File.expand_path(__FILE__)) + +gem 'reststop', '~> 0.2' + +require 'yaml' +require 'fileutils' +require 'rubygems' +require 'picnic' +require 'reststop' +require 'everest' +require 'restr' +require 'xmlrpc/client' + +Camping.goes :Cloudmasterd +Cloudmasterd.picnic! + +module Cloudmasterd::Model + +end + +module Cloudmasterd::Helpers + class Cobblerd + def initialize(repo) + @repo = repo + @xmlrpc = XMLRPC::Client.new2("http://#{@repo}:25152") + @token = @xmlrpc.call2("login", "cobbler", "password")[1] + end + + def _call(method, *args) + return @xmlrpc.call2(method, *args)[1] + end + + def distros + _call("get_distros", @token) + end + + def profiles + _call("get_profiles", @token) + end + + def systems + _call("get_systems", @token) + end + + def repos + _call("get_repos", @token) + end + + def distro(name) + _call("get_distro", name, @token) + end + + def distro_for_koan(name) + _call("get_distro_for_koan", name, @token) + end + + def profile(name) + _call("get_profile", name, @token) + end + + def profile_for_koan(name) + _call("get_profile_for_koan", name, @token) + end + + def system(name) + _call("get_system", name, @token) + end + + def system_for_koan(name) + _call("get_system_for_koan", name, @token) + end + + def repo(name) + _call("get_repo", name, @token) + end + + def repo_for_koan(name) + _call("get_repo_for_koan", name, @token) + end + + end +end + +module Cloudmasterd::Controllers + class Koan < REST 'koan' + # Retrieve the cobbler profile for the given profile name + def _get_cobbler_profile(system_name, repo) + cobblerd = Cloudmasterd::Helpers::Cobblerd.new(repo) + cobbler_system = cobblerd.system(system_name) + return cobblerd.profile(cobbler_system["profile"]) + end + + # Find the best host on which to create a VM that requires + # the given "disk_size" and "ram" + def _get_best_host(disk_size, ram) + return `func-find-resources -m #{ram} -d #{disk_size}`.split(':')[0] + end + + # run the appropriate koan command to create the given "fqdn" + # on the given "host" and "vol_group" + def _koan(host, fqdn, repo) + # Run the koan process + func_cmd = "func \"#{host}\" call virt install #{repo} #{fqdn} True #{fqdn} /images" + puts `#{func_cmd}` + + # Make the new host autostart + func_cmd = "func \"#{host}\" call command run \"ln -s /etc/xen/#{fqdn.split('.')[0]} /etc/xen/auto/\"" + puts `#{func_cmd}` + end + + # POST /koan + def create + machine_fqdn = input.machine_fqdn + repo = input.repo + + cobbler_profile = _get_cobbler_profile(machine_fqdn, repo) + @host = _get_best_host(cobbler_profile["virt_file_size"], cobbler_profile["virt_ram"]) + _koan(@host, machine_fqdn, repo) + render :_koan + end + end +end + +module Cloudmasterd::Views + def initialize(*args) + super(*args) + @x = Builder::XmlMarkup.new(:indent => 1) + end + + module HTML + def layout + html do + head do + title 'Everest Cloud Master Controller' + #link :rel => 'stylesheet', :type => 'text/css', + #:href => self/'/styles.css', :media => 'screen' + end + body do + div.content do + self << yield + end + end + end + end + + def _koan + @host + end + end + default_format :HTML + + module YAML + CONTENT_TYPE = 'text/plain' + + def layout + yield + end + end + + module XML + def layout + yield + end + end +end + +# Required by picnic +def Cloudmasterd.create; end + +Cloudmasterd.start_picnic diff --git a/cloudmasterd/lib/cloudmasterd/version.rb b/cloudmasterd/lib/cloudmasterd/version.rb new file mode 100644 index 0000000..ec2eb9c --- /dev/null +++ b/cloudmasterd/lib/cloudmasterd/version.rb @@ -0,0 +1,9 @@ +module Cloudmasterd #:nodoc: + module VERSION #:nodoc: + MAJOR = 0 + MINOR = 1 + TINY = 1 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end diff --git a/cloudmasterd/log/debug.log b/cloudmasterd/log/debug.log new file mode 100644 index 0000000..e69de29 diff --git a/cloudmasterd/script/console b/cloudmasterd/script/console new file mode 100755 index 0000000..cc9f73f --- /dev/null +++ b/cloudmasterd/script/console @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +# File: script/console +irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb' + +libs = " -r irb/completion" +# Perhaps use a console_lib to store any extra methods I may want available in the cosole +# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}" +libs << " -r #{File.dirname(__FILE__) + '/../lib/cloudmasterd.rb'}" +puts "Loading cloudmasterd gem" +exec "#{irb} #{libs} --simple-prompt" diff --git a/cloudmasterd/script/destroy b/cloudmasterd/script/destroy new file mode 100755 index 0000000..e48464d --- /dev/null +++ b/cloudmasterd/script/destroy @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) + +begin + require 'rubigen' +rescue LoadError + require 'rubygems' + require 'rubigen' +end +require 'rubigen/scripts/destroy' + +ARGV.shift if ['--help', '-h'].include?(ARGV[0]) +RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] +RubiGen::Scripts::Destroy.new.run(ARGV) diff --git a/cloudmasterd/script/generate b/cloudmasterd/script/generate new file mode 100755 index 0000000..c27f655 --- /dev/null +++ b/cloudmasterd/script/generate @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) + +begin + require 'rubigen' +rescue LoadError + require 'rubygems' + require 'rubigen' +end +require 'rubigen/scripts/generate' + +ARGV.shift if ['--help', '-h'].include?(ARGV[0]) +RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] +RubiGen::Scripts::Generate.new.run(ARGV) diff --git a/cloudmasterd/script/txt2html b/cloudmasterd/script/txt2html new file mode 100755 index 0000000..1682173 --- /dev/null +++ b/cloudmasterd/script/txt2html @@ -0,0 +1,74 @@ +#!/usr/bin/env ruby + +require 'rubygems' +begin + require 'newgem' +rescue LoadError + puts "\n\nGenerating the website requires the newgem RubyGem" + puts "Install: gem install newgem\n\n" + exit(1) +end +require 'redcloth' +require 'syntax/convertors/html' +require 'erb' +require File.dirname(__FILE__) + '/../lib/cloudmasterd/version.rb' + +version = Everestd::VERSION::STRING +download = 'http://rubyforge.org/projects/cloudmasterd' + +class Fixnum + def ordinal + # teens + return 'th' if (10..19).include?(self % 100) + # others + case self % 10 + when 1: return 'st' + when 2: return 'nd' + when 3: return 'rd' + else return 'th' + end + end +end + +class Time + def pretty + return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}" + end +end + +def convert_syntax(syntax, source) + return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^
|
$!,'') +end + +if ARGV.length >= 1 + src, template = ARGV + template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb') + +else + puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html") + exit! +end + +template = ERB.new(File.open(template).read) + +title = nil +body = nil +File.open(src) do |fsrc| + title_text = fsrc.readline + body_text = fsrc.read + syntax_items = [] + body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)!m){ + ident = syntax_items.length + element, syntax, source = $1, $2, $3 + syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}" + "syntax-temp-#{ident}" + } + title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip + body = RedCloth.new(body_text).to_html + body.gsub!(%r!(?:
)?syntax-temp-(\d+)(?:
)?!){ syntax_items[$1.to_i] } +end +stat = File.stat(src) +created = stat.ctime +modified = stat.mtime + +$stdout << template.result(binding) diff --git a/cloudmasterd/setup.rb b/cloudmasterd/setup.rb new file mode 100644 index 0000000..424a5f3 --- /dev/null +++ b/cloudmasterd/setup.rb @@ -0,0 +1,1585 @@ +# +# setup.rb +# +# Copyright (c) 2000-2005 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU LGPL, Lesser General Public License version 2.1. +# + +unless Enumerable.method_defined?(:map) # Ruby 1.4.6 + module Enumerable + alias map collect + end +end + +unless File.respond_to?(:read) # Ruby 1.6 + def File.read(fname) + open(fname) {|f| + return f.read + } + end +end + +unless Errno.const_defined?(:ENOTEMPTY) # Windows? + module Errno + class ENOTEMPTY + # We do not raise this exception, implementation is not needed. + end + end +end + +def File.binread(fname) + open(fname, 'rb') {|f| + return f.read + } +end + +# for corrupted Windows' stat(2) +def File.dir?(path) + File.directory?((path[-1,1] == '/') ? path : path + '/') +end + + +class ConfigTable + + include Enumerable + + def initialize(rbconfig) + @rbconfig = rbconfig + @items = [] + @table = {} + # options + @install_prefix = nil + @config_opt = nil + @verbose = true + @no_harm = false + end + + attr_accessor :install_prefix + attr_accessor :config_opt + + attr_writer :verbose + + def verbose? + @verbose + end + + attr_writer :no_harm + + def no_harm? + @no_harm + end + + def [](key) + lookup(key).resolve(self) + end + + def []=(key, val) + lookup(key).set val + end + + def names + @items.map {|i| i.name } + end + + def each(&block) + @items.each(&block) + end + + def key?(name) + @table.key?(name) + end + + def lookup(name) + @table[name] or setup_rb_error "no such config item: #{name}" + end + + def add(item) + @items.push item + @table[item.name] = item + end + + def remove(name) + item = lookup(name) + @items.delete_if {|i| i.name == name } + @table.delete_if {|name, i| i.name == name } + item + end + + def load_script(path, inst = nil) + if File.file?(path) + MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path + end + end + + def savefile + '.config' + end + + def load_savefile + begin + File.foreach(savefile()) do |line| + k, v = *line.split(/=/, 2) + self[k] = v.strip + end + rescue Errno::ENOENT + setup_rb_error $!.message + "\n#{File.basename($0)} config first" + end + end + + def save + @items.each {|i| i.value } + File.open(savefile(), 'w') {|f| + @items.each do |i| + f.printf "%s=%s\n", i.name, i.value if i.value? and i.value + end + } + end + + def load_standard_entries + standard_entries(@rbconfig).each do |ent| + add ent + end + end + + def standard_entries(rbconfig) + c = rbconfig + + rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) + + major = c['MAJOR'].to_i + minor = c['MINOR'].to_i + teeny = c['TEENY'].to_i + version = "#{major}.#{minor}" + + # ruby ver. >= 1.4.4? + newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + + if c['rubylibdir'] + # V > 1.6.3 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = c['rubylibdir'] + librubyverarch = c['archdir'] + siteruby = c['sitedir'] + siterubyver = c['sitelibdir'] + siterubyverarch = c['sitearchdir'] + elsif newpath_p + # 1.4.4 <= V <= 1.6.3 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = "#{c['prefix']}/lib/ruby/#{version}" + librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" + siteruby = c['sitedir'] + siterubyver = "$siteruby/#{version}" + siterubyverarch = "$siterubyver/#{c['arch']}" + else + # V < 1.4.4 + libruby = "#{c['prefix']}/lib/ruby" + librubyver = "#{c['prefix']}/lib/ruby/#{version}" + librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" + siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" + siterubyver = siteruby + siterubyverarch = "$siterubyver/#{c['arch']}" + end + parameterize = lambda {|path| + path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') + } + + if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } + makeprog = arg.sub(/'/, '').split(/=/, 2)[1] + else + makeprog = 'make' + end + + [ + ExecItem.new('installdirs', 'std/site/home', + 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ + {|val, table| + case val + when 'std' + table['rbdir'] = '$librubyver' + table['sodir'] = '$librubyverarch' + when 'site' + table['rbdir'] = '$siterubyver' + table['sodir'] = '$siterubyverarch' + when 'home' + setup_rb_error '$HOME was not set' unless ENV['HOME'] + table['prefix'] = ENV['HOME'] + table['rbdir'] = '$libdir/ruby' + table['sodir'] = '$libdir/ruby' + end + }, + PathItem.new('prefix', 'path', c['prefix'], + 'path prefix of target environment'), + PathItem.new('bindir', 'path', parameterize.call(c['bindir']), + 'the directory for commands'), + PathItem.new('libdir', 'path', parameterize.call(c['libdir']), + 'the directory for libraries'), + PathItem.new('datadir', 'path', parameterize.call(c['datadir']), + 'the directory for shared data'), + PathItem.new('mandir', 'path', parameterize.call(c['mandir']), + 'the directory for man pages'), + PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), + 'the directory for system configuration files'), + PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), + 'the directory for local state data'), + PathItem.new('libruby', 'path', libruby, + 'the directory for ruby libraries'), + PathItem.new('librubyver', 'path', librubyver, + 'the directory for standard ruby libraries'), + PathItem.new('librubyverarch', 'path', librubyverarch, + 'the directory for standard ruby extensions'), + PathItem.new('siteruby', 'path', siteruby, + 'the directory for version-independent aux ruby libraries'), + PathItem.new('siterubyver', 'path', siterubyver, + 'the directory for aux ruby libraries'), + PathItem.new('siterubyverarch', 'path', siterubyverarch, + 'the directory for aux ruby binaries'), + PathItem.new('rbdir', 'path', '$siterubyver', + 'the directory for ruby scripts'), + PathItem.new('sodir', 'path', '$siterubyverarch', + 'the directory for ruby extentions'), + PathItem.new('rubypath', 'path', rubypath, + 'the path to set to #! line'), + ProgramItem.new('rubyprog', 'name', rubypath, + 'the ruby program using for installation'), + ProgramItem.new('makeprog', 'name', makeprog, + 'the make program to compile ruby extentions'), + SelectItem.new('shebang', 'all/ruby/never', 'ruby', + 'shebang line (#!) editing mode'), + BoolItem.new('without-ext', 'yes/no', 'no', + 'does not compile/install ruby extentions') + ] + end + private :standard_entries + + def load_multipackage_entries + multipackage_entries().each do |ent| + add ent + end + end + + def multipackage_entries + [ + PackageSelectionItem.new('with', 'name,name...', '', 'ALL', + 'package names that you want to install'), + PackageSelectionItem.new('without', 'name,name...', '', 'NONE', + 'package names that you do not want to install') + ] + end + private :multipackage_entries + + ALIASES = { + 'std-ruby' => 'librubyver', + 'stdruby' => 'librubyver', + 'rubylibdir' => 'librubyver', + 'archdir' => 'librubyverarch', + 'site-ruby-common' => 'siteruby', # For backward compatibility + 'site-ruby' => 'siterubyver', # For backward compatibility + 'bin-dir' => 'bindir', + 'bin-dir' => 'bindir', + 'rb-dir' => 'rbdir', + 'so-dir' => 'sodir', + 'data-dir' => 'datadir', + 'ruby-path' => 'rubypath', + 'ruby-prog' => 'rubyprog', + 'ruby' => 'rubyprog', + 'make-prog' => 'makeprog', + 'make' => 'makeprog' + } + + def fixup + ALIASES.each do |ali, name| + @table[ali] = @table[name] + end + @items.freeze + @table.freeze + @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ + end + + def parse_opt(opt) + m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" + m.to_a[1,2] + end + + def dllext + @rbconfig['DLEXT'] + end + + def value_config?(name) + lookup(name).value? + end + + class Item + def initialize(name, template, default, desc) + @name = name.freeze + @template = template + @value = default + @default = default + @description = desc + end + + attr_reader :name + attr_reader :description + + attr_accessor :default + alias help_default default + + def help_opt + "--#{@name}=#{@template}" + end + + def value? + true + end + + def value + @value + end + + def resolve(table) + @value.gsub(%r<\$([^/]+)>) { table[$1] } + end + + def set(val) + @value = check(val) + end + + private + + def check(val) + setup_rb_error "config: --#{name} requires argument" unless val + val + end + end + + class BoolItem < Item + def config_type + 'bool' + end + + def help_opt + "--#{@name}" + end + + private + + def check(val) + return 'yes' unless val + case val + when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' + when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' + else + setup_rb_error "config: --#{@name} accepts only yes/no for argument" + end + end + end + + class PathItem < Item + def config_type + 'path' + end + + private + + def check(path) + setup_rb_error "config: --#{@name} requires argument" unless path + path[0,1] == '$' ? path : File.expand_path(path) + end + end + + class ProgramItem < Item + def config_type + 'program' + end + end + + class SelectItem < Item + def initialize(name, selection, default, desc) + super + @ok = selection.split('/') + end + + def config_type + 'select' + end + + private + + def check(val) + unless @ok.include?(val.strip) + setup_rb_error "config: use --#{@name}=#{@template} (#{val})" + end + val.strip + end + end + + class ExecItem < Item + def initialize(name, selection, desc, &block) + super name, selection, nil, desc + @ok = selection.split('/') + @action = block + end + + def config_type + 'exec' + end + + def value? + false + end + + def resolve(table) + setup_rb_error "$#{name()} wrongly used as option value" + end + + undef set + + def evaluate(val, table) + v = val.strip.downcase + unless @ok.include?(v) + setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" + end + @action.call v, table + end + end + + class PackageSelectionItem < Item + def initialize(name, template, default, help_default, desc) + super name, template, default, desc + @help_default = help_default + end + + attr_reader :help_default + + def config_type + 'package' + end + + private + + def check(val) + unless File.dir?("packages/#{val}") + setup_rb_error "config: no such package: #{val}" + end + val + end + end + + class MetaConfigEnvironment + def initialize(config, installer) + @config = config + @installer = installer + end + + def config_names + @config.names + end + + def config?(name) + @config.key?(name) + end + + def bool_config?(name) + @config.lookup(name).config_type == 'bool' + end + + def path_config?(name) + @config.lookup(name).config_type == 'path' + end + + def value_config?(name) + @config.lookup(name).config_type != 'exec' + end + + def add_config(item) + @config.add item + end + + def add_bool_config(name, default, desc) + @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) + end + + def add_path_config(name, default, desc) + @config.add PathItem.new(name, 'path', default, desc) + end + + def set_config_default(name, default) + @config.lookup(name).default = default + end + + def remove_config(name) + @config.remove(name) + end + + # For only multipackage + def packages + raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer + @installer.packages + end + + # For only multipackage + def declare_packages(list) + raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer + @installer.packages = list + end + end + +end # class ConfigTable + + +# This module requires: #verbose?, #no_harm? +module FileOperations + + def mkdir_p(dirname, prefix = nil) + dirname = prefix + File.expand_path(dirname) if prefix + $stderr.puts "mkdir -p #{dirname}" if verbose? + return if no_harm? + + # Does not check '/', it's too abnormal. + dirs = File.expand_path(dirname).split(%r<(?=/)>) + if /\A[a-z]:\z/i =~ dirs[0] + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless File.dir?(path) + end + end + + def rm_f(path) + $stderr.puts "rm -f #{path}" if verbose? + return if no_harm? + force_remove_file path + end + + def rm_rf(path) + $stderr.puts "rm -rf #{path}" if verbose? + return if no_harm? + remove_tree path + end + + def remove_tree(path) + if File.symlink?(path) + remove_file path + elsif File.dir?(path) + remove_tree0 path + else + force_remove_file path + end + end + + def remove_tree0(path) + Dir.foreach(path) do |ent| + next if ent == '.' + next if ent == '..' + entpath = "#{path}/#{ent}" + if File.symlink?(entpath) + remove_file entpath + elsif File.dir?(entpath) + remove_tree0 entpath + else + force_remove_file entpath + end + end + begin + Dir.rmdir path + rescue Errno::ENOTEMPTY + # directory may not be empty + end + end + + def move_file(src, dest) + force_remove_file dest + begin + File.rename src, dest + rescue + File.open(dest, 'wb') {|f| + f.write File.binread(src) + } + File.chmod File.stat(src).mode, dest + File.unlink src + end + end + + def force_remove_file(path) + begin + remove_file path + rescue + end + end + + def remove_file(path) + File.chmod 0777, path + File.unlink path + end + + def install(from, dest, mode, prefix = nil) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix ? prefix + File.expand_path(dest) : dest + realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) + str = File.binread(from) + if diff?(str, realdest) + verbose_off { + rm_f realdest if File.exist?(realdest) + } + File.open(realdest, 'wb') {|f| + f.write str + } + File.chmod mode, realdest + + File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| + if prefix + f.puts realdest.sub(prefix, '') + else + f.puts realdest + end + } + end + end + + def diff?(new_content, path) + return true unless File.exist?(path) + new_content != File.binread(path) + end + + def command(*args) + $stderr.puts args.join(' ') if verbose? + system(*args) or raise RuntimeError, + "system(#{args.map{|a| a.inspect }.join(' ')}) failed" + end + + def ruby(*args) + command config('rubyprog'), *args + end + + def make(task = nil) + command(*[config('makeprog'), task].compact) + end + + def extdir?(dir) + File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") + end + + def files_of(dir) + Dir.open(dir) {|d| + return d.select {|ent| File.file?("#{dir}/#{ent}") } + } + end + + DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) + + def directories_of(dir) + Dir.open(dir) {|d| + return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT + } + end + +end + + +# This module requires: #srcdir_root, #objdir_root, #relpath +module HookScriptAPI + + def get_config(key) + @config[key] + end + + alias config get_config + + # obsolete: use metaconfig to change configuration + def set_config(key, val) + @config[key] = val + end + + # + # srcdir/objdir (works only in the package directory) + # + + def curr_srcdir + "#{srcdir_root()}/#{relpath()}" + end + + def curr_objdir + "#{objdir_root()}/#{relpath()}" + end + + def srcfile(path) + "#{curr_srcdir()}/#{path}" + end + + def srcexist?(path) + File.exist?(srcfile(path)) + end + + def srcdirectory?(path) + File.dir?(srcfile(path)) + end + + def srcfile?(path) + File.file?(srcfile(path)) + end + + def srcentries(path = '.') + Dir.open("#{curr_srcdir()}/#{path}") {|d| + return d.to_a - %w(. ..) + } + end + + def srcfiles(path = '.') + srcentries(path).select {|fname| + File.file?(File.join(curr_srcdir(), path, fname)) + } + end + + def srcdirectories(path = '.') + srcentries(path).select {|fname| + File.dir?(File.join(curr_srcdir(), path, fname)) + } + end + +end + + +class ToplevelInstaller + + Version = '3.4.1' + Copyright = 'Copyright (c) 2000-2005 Minero Aoki' + + TASKS = [ + [ 'all', 'do config, setup, then install' ], + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles ruby extentions and others' ], + [ 'install', 'installs files' ], + [ 'test', 'run all tests in test/' ], + [ 'clean', "does `make clean' for each extention" ], + [ 'distclean',"does `make distclean' for each extention" ] + ] + + def ToplevelInstaller.invoke + config = ConfigTable.new(load_rbconfig()) + config.load_standard_entries + config.load_multipackage_entries if multipackage? + config.fixup + klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) + klass.new(File.dirname($0), config).invoke + end + + def ToplevelInstaller.multipackage? + File.dir?(File.dirname($0) + '/packages') + end + + def ToplevelInstaller.load_rbconfig + if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } + ARGV.delete(arg) + load File.expand_path(arg.split(/=/, 2)[1]) + $".push 'rbconfig.rb' + else + require 'rbconfig' + end + ::Config::CONFIG + end + + def initialize(ardir_root, config) + @ardir = File.expand_path(ardir_root) + @config = config + # cache + @valid_task_re = nil + end + + def config(key) + @config[key] + end + + def inspect + "#<#{self.class} #{__id__()}>" + end + + def invoke + run_metaconfigs + case task = parsearg_global() + when nil, 'all' + parsearg_config + init_installers + exec_config + exec_setup + exec_install + else + case task + when 'config', 'test' + ; + when 'clean', 'distclean' + @config.load_savefile if File.exist?(@config.savefile) + else + @config.load_savefile + end + __send__ "parsearg_#{task}" + init_installers + __send__ "exec_#{task}" + end + end + + def run_metaconfigs + @config.load_script "#{@ardir}/metaconfig" + end + + def init_installers + @installer = Installer.new(@config, @ardir, File.expand_path('.')) + end + + # + # Hook Script API bases + # + + def srcdir_root + @ardir + end + + def objdir_root + '.' + end + + def relpath + '.' + end + + # + # Option Parsing + # + + def parsearg_global + while arg = ARGV.shift + case arg + when /\A\w+\z/ + setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) + return arg + when '-q', '--quiet' + @config.verbose = false + when '--verbose' + @config.verbose = true + when '--help' + print_usage $stdout + exit 0 + when '--version' + puts "#{File.basename($0)} version #{Version}" + exit 0 + when '--copyright' + puts Copyright + exit 0 + else + setup_rb_error "unknown global option '#{arg}'" + end + end + nil + end + + def valid_task?(t) + valid_task_re() =~ t + end + + def valid_task_re + @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ + end + + def parsearg_no_options + unless ARGV.empty? + task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) + setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" + end + end + + alias parsearg_show parsearg_no_options + alias parsearg_setup parsearg_no_options + alias parsearg_test parsearg_no_options + alias parsearg_clean parsearg_no_options + alias parsearg_distclean parsearg_no_options + + def parsearg_config + evalopt = [] + set = [] + @config.config_opt = [] + while i = ARGV.shift + if /\A--?\z/ =~ i + @config.config_opt = ARGV.dup + break + end + name, value = *@config.parse_opt(i) + if @config.value_config?(name) + @config[name] = value + else + evalopt.push [name, value] + end + set.push name + end + evalopt.each do |name, value| + @config.lookup(name).evaluate value, @config + end + # Check if configuration is valid + set.each do |n| + @config[n] if @config.value_config?(n) + end + end + + def parsearg_install + @config.no_harm = false + @config.install_prefix = '' + while a = ARGV.shift + case a + when '--no-harm' + @config.no_harm = true + when /\A--prefix=/ + path = a.split(/=/, 2)[1] + path = File.expand_path(path) unless path[0,1] == '/' + @config.install_prefix = path + else + setup_rb_error "install: unknown option #{a}" + end + end + end + + def print_usage(out) + out.puts 'Typical Installation Procedure:' + out.puts " $ ruby #{File.basename $0} config" + out.puts " $ ruby #{File.basename $0} setup" + out.puts " # ruby #{File.basename $0} install (may require root privilege)" + out.puts + out.puts 'Detailed Usage:' + out.puts " ruby #{File.basename $0} " + out.puts " ruby #{File.basename $0} [] []" + + fmt = " %-24s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, ' --help', 'print this message' + out.printf fmt, ' --version', 'print version and quit' + out.printf fmt, ' --copyright', 'print copyright and quit' + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf fmt, name, desc + end + + fmt = " %-24s %s [%s]\n" + out.puts + out.puts 'Options for CONFIG or ALL:' + @config.each do |item| + out.printf fmt, item.help_opt, item.description, item.help_default + end + out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" + out.puts + out.puts 'Options for INSTALL:' + out.printf fmt, '--no-harm', 'only display what to do if given', 'off' + out.printf fmt, '--prefix=path', 'install path prefix', '' + out.puts + end + + # + # Task Handlers + # + + def exec_config + @installer.exec_config + @config.save # must be final + end + + def exec_setup + @installer.exec_setup + end + + def exec_install + @installer.exec_install + end + + def exec_test + @installer.exec_test + end + + def exec_show + @config.each do |i| + printf "%-20s %s\n", i.name, i.value if i.value? + end + end + + def exec_clean + @installer.exec_clean + end + + def exec_distclean + @installer.exec_distclean + end + +end # class ToplevelInstaller + + +class ToplevelInstallerMulti < ToplevelInstaller + + include FileOperations + + def initialize(ardir_root, config) + super + @packages = directories_of("#{@ardir}/packages") + raise 'no package exists' if @packages.empty? + @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) + end + + def run_metaconfigs + @config.load_script "#{@ardir}/metaconfig", self + @packages.each do |name| + @config.load_script "#{@ardir}/packages/#{name}/metaconfig" + end + end + + attr_reader :packages + + def packages=(list) + raise 'package list is empty' if list.empty? + list.each do |name| + raise "directory packages/#{name} does not exist"\ + unless File.dir?("#{@ardir}/packages/#{name}") + end + @packages = list + end + + def init_installers + @installers = {} + @packages.each do |pack| + @installers[pack] = Installer.new(@config, + "#{@ardir}/packages/#{pack}", + "packages/#{pack}") + end + with = extract_selection(config('with')) + without = extract_selection(config('without')) + @selected = @installers.keys.select {|name| + (with.empty? or with.include?(name)) \ + and not without.include?(name) + } + end + + def extract_selection(list) + a = list.split(/,/) + a.each do |name| + setup_rb_error "no such package: #{name}" unless @installers.key?(name) + end + a + end + + def print_usage(f) + super + f.puts 'Inluded packages:' + f.puts ' ' + @packages.sort.join(' ') + f.puts + end + + # + # Task Handlers + # + + def exec_config + run_hook 'pre-config' + each_selected_installers {|inst| inst.exec_config } + run_hook 'post-config' + @config.save # must be final + end + + def exec_setup + run_hook 'pre-setup' + each_selected_installers {|inst| inst.exec_setup } + run_hook 'post-setup' + end + + def exec_install + run_hook 'pre-install' + each_selected_installers {|inst| inst.exec_install } + run_hook 'post-install' + end + + def exec_test + run_hook 'pre-test' + each_selected_installers {|inst| inst.exec_test } + run_hook 'post-test' + end + + def exec_clean + rm_f @config.savefile + run_hook 'pre-clean' + each_selected_installers {|inst| inst.exec_clean } + run_hook 'post-clean' + end + + def exec_distclean + rm_f @config.savefile + run_hook 'pre-distclean' + each_selected_installers {|inst| inst.exec_distclean } + run_hook 'post-distclean' + end + + # + # lib + # + + def each_selected_installers + Dir.mkdir 'packages' unless File.dir?('packages') + @selected.each do |pack| + $stderr.puts "Processing the package `#{pack}' ..." if verbose? + Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") + Dir.chdir "packages/#{pack}" + yield @installers[pack] + Dir.chdir '../..' + end + end + + def run_hook(id) + @root_installer.run_hook id + end + + # module FileOperations requires this + def verbose? + @config.verbose? + end + + # module FileOperations requires this + def no_harm? + @config.no_harm? + end + +end # class ToplevelInstallerMulti + + +class Installer + + FILETYPES = %w( bin lib ext data conf man ) + + include FileOperations + include HookScriptAPI + + def initialize(config, srcroot, objroot) + @config = config + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{self.class} #{File.basename(@srcdir)}>" + end + + def noop(rel) + end + + # + # Hook Script API base methods + # + + def srcdir_root + @srcdir + end + + def objdir_root + @objdir + end + + def relpath + @currdir + end + + # + # Config Access + # + + # module FileOperations requires this + def verbose? + @config.verbose? + end + + # module FileOperations requires this + def no_harm? + @config.no_harm? + end + + def verbose_off + begin + save, @config.verbose = @config.verbose?, false + yield + ensure + @config.verbose = save + end + end + + # + # TASK config + # + + def exec_config + exec_task_traverse 'config' + end + + alias config_dir_bin noop + alias config_dir_lib noop + + def config_dir_ext(rel) + extconf if extdir?(curr_srcdir()) + end + + alias config_dir_data noop + alias config_dir_conf noop + alias config_dir_man noop + + def extconf + ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt + end + + # + # TASK setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin(rel) + files_of(curr_srcdir()).each do |fname| + update_shebang_line "#{curr_srcdir()}/#{fname}" + end + end + + alias setup_dir_lib noop + + def setup_dir_ext(rel) + make if extdir?(curr_srcdir()) + end + + alias setup_dir_data noop + alias setup_dir_conf noop + alias setup_dir_man noop + + def update_shebang_line(path) + return if no_harm? + return if config('shebang') == 'never' + old = Shebang.load(path) + if old + $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 + new = new_shebang(old) + return if new.to_s == old.to_s + else + return unless config('shebang') == 'all' + new = Shebang.new(config('rubypath')) + end + $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? + open_atomic_writer(path) {|output| + File.open(path, 'rb') {|f| + f.gets if old # discard + output.puts new.to_s + output.print f.read + } + } + end + + def new_shebang(old) + if /\Aruby/ =~ File.basename(old.cmd) + Shebang.new(config('rubypath'), old.args) + elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' + Shebang.new(config('rubypath'), old.args[1..-1]) + else + return old unless config('shebang') == 'all' + Shebang.new(config('rubypath')) + end + end + + def open_atomic_writer(path, &block) + tmpfile = File.basename(path) + '.tmp' + begin + File.open(tmpfile, 'wb', &block) + File.rename tmpfile, File.basename(path) + ensure + File.unlink tmpfile if File.exist?(tmpfile) + end + end + + class Shebang + def Shebang.load(path) + line = nil + File.open(path) {|f| + line = f.gets + } + return nil unless /\A#!/ =~ line + parse(line) + end + + def Shebang.parse(line) + cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') + new(cmd, args) + end + + def initialize(cmd, args = []) + @cmd = cmd + @args = args + end + + attr_reader :cmd + attr_reader :args + + def to_s + "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") + end + end + + # + # TASK install + # + + def exec_install + rm_f 'InstalledFiles' + exec_task_traverse 'install' + end + + def install_dir_bin(rel) + install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 + end + + def install_dir_lib(rel) + install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 + end + + def install_dir_ext(rel) + return unless extdir?(curr_srcdir()) + install_files rubyextentions('.'), + "#{config('sodir')}/#{File.dirname(rel)}", + 0555 + end + + def install_dir_data(rel) + install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 + end + + def install_dir_conf(rel) + # FIXME: should not remove current config files + # (rename previous file to .old/.org) + install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 + end + + def install_dir_man(rel) + install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 + end + + def install_files(list, dest, mode) + mkdir_p dest, @config.install_prefix + list.each do |fname| + install fname, dest, mode, @config.install_prefix + end + end + + def libfiles + glob_reject(%w(*.y *.output), targetfiles()) + end + + def rubyextentions(dir) + ents = glob_select("*.#{@config.dllext}", targetfiles()) + if ents.empty? + setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" + end + ents + end + + def targetfiles + mapdir(existfiles() - hookfiles()) + end + + def mapdir(ents) + ents.map {|ent| + if File.exist?(ent) + then ent # objdir + else "#{curr_srcdir()}/#{ent}" # srcdir + end + } + end + + # picked up many entries from cvs-1.11.1/src/ignore.c + JUNK_FILES = %w( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + ) + + def existfiles + glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) + end + + def hookfiles + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| + %w( config setup install clean ).map {|t| sprintf(fmt, t) } + }.flatten + end + + def glob_select(pat, ents) + re = globs2re([pat]) + ents.select {|ent| re =~ ent } + end + + def glob_reject(pats, ents) + re = globs2re(pats) + ents.reject {|ent| re =~ ent } + end + + GLOB2REGEX = { + '.' => '\.', + '$' => '\$', + '#' => '\#', + '*' => '.*' + } + + def globs2re(pats) + /\A(?:#{ + pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') + })\z/ + end + + # + # TASK test + # + + TESTDIR = 'test' + + def exec_test + unless File.directory?('test') + $stderr.puts 'no test in this package' if verbose? + return + end + $stderr.puts 'Running tests...' if verbose? + begin + require 'test/unit' + rescue LoadError + setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' + end + runner = Test::Unit::AutoRunner.new(true) + runner.to_run << TESTDIR + runner.run + end + + # + # TASK clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f @config.savefile + rm_f 'InstalledFiles' + end + + alias clean_dir_bin noop + alias clean_dir_lib noop + alias clean_dir_data noop + alias clean_dir_conf noop + alias clean_dir_man noop + + def clean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'clean' if File.file?('Makefile') + end + + # + # TASK distclean + # + + def exec_distclean + exec_task_traverse 'distclean' + rm_f @config.savefile + rm_f 'InstalledFiles' + end + + alias distclean_dir_bin noop + alias distclean_dir_lib noop + + def distclean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'distclean' if File.file?('Makefile') + end + + alias distclean_dir_data noop + alias distclean_dir_conf noop + alias distclean_dir_man noop + + # + # Traversing + # + + def exec_task_traverse(task) + run_hook "pre-#{task}" + FILETYPES.each do |type| + if type == 'ext' and config('without-ext') == 'yes' + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, "#{task}_dir_#{type}" + end + run_hook "post-#{task}" + end + + def traverse(task, rel, mid) + dive_into(rel) { + run_hook "pre-#{task}" + __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') + directories_of(curr_srcdir()).each do |d| + traverse task, "#{rel}/#{d}", mid + end + run_hook "post-#{task}" + } + end + + def dive_into(rel) + return unless File.dir?("#{@srcdir}/#{rel}") + + dir = File.basename(rel) + Dir.mkdir dir unless File.dir?(dir) + prevdir = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir prevdir + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + + def run_hook(id) + path = [ "#{curr_srcdir()}/#{id}", + "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } + return unless path + begin + instance_eval File.read(path), path, 1 + rescue + raise if $DEBUG + setup_rb_error "hook #{path} failed:\n" + $!.message + end + end + +end # class Installer + + +class SetupError < StandardError; end + +def setup_rb_error(msg) + raise SetupError, msg +end + +if $0 == __FILE__ + begin + ToplevelInstaller.invoke + rescue SetupError + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." + exit 1 + end +end diff --git a/cloudmasterd/spec/cloudmasterd_spec.rb b/cloudmasterd/spec/cloudmasterd_spec.rb new file mode 100644 index 0000000..a52055a --- /dev/null +++ b/cloudmasterd/spec/cloudmasterd_spec.rb @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/spec_helper.rb' + +# Time to add your specs! +# http://rspec.info/ +describe "Place your specs here" do + + it "find this spec in spec directory" do + violated "Be sure to write your specs" + end + +end diff --git a/cloudmasterd/spec/spec.opts b/cloudmasterd/spec/spec.opts new file mode 100644 index 0000000..53607ea --- /dev/null +++ b/cloudmasterd/spec/spec.opts @@ -0,0 +1 @@ +--colour diff --git a/cloudmasterd/spec/spec_helper.rb b/cloudmasterd/spec/spec_helper.rb new file mode 100644 index 0000000..ecb7350 --- /dev/null +++ b/cloudmasterd/spec/spec_helper.rb @@ -0,0 +1,10 @@ +begin + require 'spec' +rescue LoadError + require 'rubygems' + gem 'rspec' + require 'spec' +end + +$:.unshift(File.dirname(__FILE__) + '/../lib') +require 'cloudmasterd' diff --git a/cloudmasterd/tasks/deployment.rake b/cloudmasterd/tasks/deployment.rake new file mode 100644 index 0000000..2f43742 --- /dev/null +++ b/cloudmasterd/tasks/deployment.rake @@ -0,0 +1,34 @@ +desc 'Release the website and new gem version' +task :deploy => [:check_version, :website, :release] do + puts "Remember to create SVN tag:" + puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " + + "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} " + puts "Suggested comment:" + puts "Tagging release #{CHANGES}" +end + +desc 'Runs tasks website_generate and install_gem as a local deployment of the gem' +task :local_deploy => [:website_generate, :install_gem] + +task :check_version do + unless ENV['VERSION'] + puts 'Must pass a VERSION=x.y.z release version' + exit + end + unless ENV['VERSION'] == VERS + puts "Please update your version.rb to match the release version, currently #{VERS}" + exit + end +end + +desc 'Install the package as a gem, without generating documentation(ri/rdoc)' +task :install_gem_no_doc => [:clean, :package] do + sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri" +end + +namespace :manifest do + desc 'Recreate Manifest.txt to include ALL files' + task :refresh do + `rake check_manifest | patch -p0 > Manifest.txt` + end +end \ No newline at end of file diff --git a/cloudmasterd/tasks/environment.rake b/cloudmasterd/tasks/environment.rake new file mode 100644 index 0000000..691ed3b --- /dev/null +++ b/cloudmasterd/tasks/environment.rake @@ -0,0 +1,7 @@ +task :ruby_env do + RUBY_APP = if RUBY_PLATFORM =~ /java/ + "jruby" + else + "ruby" + end unless defined? RUBY_APP +end diff --git a/cloudmasterd/tasks/rspec.rake b/cloudmasterd/tasks/rspec.rake new file mode 100644 index 0000000..2415fa4 --- /dev/null +++ b/cloudmasterd/tasks/rspec.rake @@ -0,0 +1,21 @@ +begin + require 'spec' +rescue LoadError + require 'rubygems' + require 'spec' +end +begin + require 'spec/rake/spectask' +rescue LoadError + puts <<-EOS +To use rspec for testing you must install rspec gem: + gem install rspec +EOS + exit(0) +end + +desc "Run the specs under spec/models" +Spec::Rake::SpecTask.new do |t| + t.spec_opts = ['--options', "spec/spec.opts"] + t.spec_files = FileList['spec/**/*_spec.rb'] +end diff --git a/cloudmasterd/tasks/website.rake b/cloudmasterd/tasks/website.rake new file mode 100644 index 0000000..93e03fa --- /dev/null +++ b/cloudmasterd/tasks/website.rake @@ -0,0 +1,17 @@ +desc 'Generate website files' +task :website_generate => :ruby_env do + (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt| + sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} } + end +end + +desc 'Upload website files to rubyforge' +task :website_upload do + host = "#{rubyforge_username}@rubyforge.org" + remote_dir = "/var/www/gforge-projects/#{PATH}/" + local_dir = 'website' + sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}} +end + +desc 'Generate and upload website files' +task :website => [:website_generate, :website_upload, :publish_docs] diff --git a/cloudmasterd/website/index.html b/cloudmasterd/website/index.html new file mode 100644 index 0000000..524cdcb --- /dev/null +++ b/cloudmasterd/website/index.html @@ -0,0 +1,11 @@ + + + + cloudmasterd + + + +

This page has not yet been created for RubyGem cloudmasterd

+

To the developer: To generate it, update website/index.txt and run the rake task website to generate this index.html file.

+ + diff --git a/cloudmasterd/website/index.txt b/cloudmasterd/website/index.txt new file mode 100644 index 0000000..64f06c2 --- /dev/null +++ b/cloudmasterd/website/index.txt @@ -0,0 +1,39 @@ +h1. cloudmasterd + +h1. → 'cloudmasterd' + + +h2. What + + +h2. Installing + +
sudo gem install cloudmasterd
+ +h2. The basics + + +h2. Demonstration of usage + + + +h2. Forum + +"http://groups.google.com/group/cloudmasterd":http://groups.google.com/group/cloudmasterd + +TODO - create Google Group - cloudmasterd + +h2. How to submit patches + +Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above. + +The trunk repository is svn://rubyforge.org/var/svn/cloudmasterd/trunk for anonymous access. + +h2. License + +This code is free to use under the terms of the MIT license. + +h2. Contact + +Comments are welcome. Send an email to "Brenton Leanhardt":mailto:bleanhar@redhat.com via the "forum":http://groups.google.com/group/cloudmasterd + diff --git a/cloudmasterd/website/javascripts/rounded_corners_lite.inc.js b/cloudmasterd/website/javascripts/rounded_corners_lite.inc.js new file mode 100644 index 0000000..afc3ea3 --- /dev/null +++ b/cloudmasterd/website/javascripts/rounded_corners_lite.inc.js @@ -0,0 +1,285 @@ + + /**************************************************************** + * * + * curvyCorners * + * ------------ * + * * + * This script generates rounded corners for your divs. * + * * + * Version 1.2.9 * + * Copyright (c) 2006 Cameron Cooke * + * By: Cameron Cooke and Tim Hutchison. * + * * + * * + * Website: http://www.curvycorners.net * + * Email: info@totalinfinity.com * + * Forum: http://www.curvycorners.net/forum/ * + * * + * * + * This library is free software; you can redistribute * + * it and/or modify it under the terms of the GNU * + * Lesser General Public License as published by the * + * Free Software Foundation; either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * This library 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 Lesser General Public * + * License for more details. * + * * + * You should have received a copy of the GNU Lesser * + * General Public License along with this library; * + * Inc., 59 Temple Place, Suite 330, Boston, * + * MA 02111-1307 USA * + * * + ****************************************************************/ + +var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners() +{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string") +{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);} +else +{ var startIndex = 1; var boxCol = arguments;} +var curvyCornersCol = new Array(); if(arguments[0].validTags) +var validElements = arguments[0].validTags; else +var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++) +{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false) +{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);} +} +this.objects = curvyCornersCol; this.applyCornersToAll = function() +{ for(var x = 0, k = this.objects.length; x < k; x++) +{ this.objects[x].applyCorners();} +} +} +function curvyObject() +{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0) +this.box.innerHTML = ""; this.applyCorners = function() +{ for(var t = 0; t < 2; t++) +{ switch(t) +{ case 0: +if(this.settings.tl || this.settings.tr) +{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);} +break; case 1: +if(this.settings.bl || this.settings.br) +{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);} +break;} +} +if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners) +{ if(i > -1 < 4) +{ var cc = corners[i]; if(!this.settings[cc]) +{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null)) +{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "") +newCorner.style.backgroundColor = this.boxColour; else +newCorner.style.backgroundImage = this.backgroundImage; switch(cc) +{ case "tl": +newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr": +newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl": +newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br": +newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px" +newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;} +} +} +else +{ if(this.masterCorners[this.settings[cc].radius]) +{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);} +else +{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++) +{ if((intx +1) >= borderRadius) +var y1 = -1; else +var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j) +{ if((intx) >= borderRadius) +var y2 = -1; else +var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j) +var y3 = -1; else +var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);} +if((intx) >= j) +var y4 = -1; else +var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j) +{ for(var inty = (y1 + 1); inty < y2; inty++) +{ if(this.settings.antiAlias) +{ if(this.backgroundImage != "") +{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30) +{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);} +else +{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);} +} +else +{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);} +} +} +if(this.settings.antiAlias) +{ if(y3 >= y2) +{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);} +} +else +{ if(y3 >= y1) +{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);} +} +var outsideColour = this.borderColour;} +else +{ var outsideColour = this.boxColour; var y3 = y1;} +if(this.settings.antiAlias) +{ for(var inty = (y3 + 1); inty < y4; inty++) +{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);} +} +} +this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);} +if(cc != "br") +{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++) +{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";} +if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";} +switch(cc) +{ case "tr": +pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl": +pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl": +pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;} +} +} +} +if(newCorner) +{ switch(cc) +{ case "tl": +if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr": +if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl": +if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br": +if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;} +} +} +} +var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius) +radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff) +{ if(z == "t" || z == "b") +{ if(radiusDiff[z]) +{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px" +newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType) +{ case "tl": +newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr": +newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl": +newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br": +newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;} +} +var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z) +{ case "t": +if(this.topContainer) +{ if(this.settings.tl.radius && this.settings.tr.radius) +{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "") +newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);} +this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";} +break; case "b": +if(this.bottomContainer) +{ if(this.settings.bl.radius && this.settings.br.radius) +{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "") +newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);} +} +break;} +} +} +if(this.settings.autoPad == true && this.boxPadding > 0) +{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding) +contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding) +contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);} +} +this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) +{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "") +{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";} +else +{ pixel.style.backgroundColor = colour;} +if (transAmount != 100) +setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);} +} +function insertAfter(parent, node, referenceNode) +{ parent.insertBefore(node, referenceNode.nextSibling);} +function BlendColour(Col1, Col2, Col1Fraction) +{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);} +function IntToHex(strNum) +{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;} +function MakeHex(x) +{ if((x >= 0) && (x <= 9)) +{ return x;} +else +{ switch(x) +{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";} +} +} +function pixelFraction(x, y, r) +{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1))) +{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;} +var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1))) +{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;} +var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1))) +{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;} +var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1))) +{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;} +switch (whatsides) +{ case "LeftRight": +pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight": +pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom": +pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom": +pixelfraction = (yvalues[0]*xvalues[1])/2; break; default: +pixelfraction = 1;} +return pixelfraction;} +function rgb2Hex(rgbColour) +{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);} +catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");} +return hexColour;} +function rgb2Array(rgbColour) +{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;} +function setOpacity(obj, opacity) +{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME") +{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";} +else if(typeof(obj.style.opacity) != "undefined") +{ obj.style.opacity = opacity/100;} +else if(typeof(obj.style.MozOpacity) != "undefined") +{ obj.style.MozOpacity = opacity/100;} +else if(typeof(obj.style.filter) != "undefined") +{ obj.style.filter = "alpha(opacity:" + opacity + ")";} +else if(typeof(obj.style.KHTMLOpacity) != "undefined") +{ obj.style.KHTMLOpacity = opacity/100;} +} +function inArray(array, value) +{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;} +return false;} +function inArrayKey(array, value) +{ for(key in array){ if(key === value) return true;} +return false;} +function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;} +else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;} +else { elm['on' + evType] = fn;} +} +function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");} +} +function format_colour(colour) +{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent") +{ if(colour.substr(0, 3) == "rgb") +{ returnColour = rgb2Hex(colour);} +else if(colour.length == 4) +{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);} +else +{ returnColour = colour;} +} +return returnColour;} +function get_style(obj, property, propertyNS) +{ try +{ if(obj.currentStyle) +{ var returnVal = eval("obj.currentStyle." + property);} +else +{ if(isSafari && obj.style.display == "none") +{ obj.style.display = ""; var wasHidden = true;} +var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden) +{ obj.style.display = "none";} +} +} +catch(e) +{ } +return returnVal;} +function getElementsByClass(searchClass, node, tag) +{ var classElements = new Array(); if(node == null) +node = document; if(tag == null) +tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++) +{ if(pattern.test(els[i].className)) +{ classElements[j] = els[i]; j++;} +} +return classElements;} +function newCurvyError(errorMessage) +{ return new Error("curvyCorners Error:\n" + errorMessage) +} diff --git a/cloudmasterd/website/stylesheets/screen.css b/cloudmasterd/website/stylesheets/screen.css new file mode 100644 index 0000000..2c84cd0 --- /dev/null +++ b/cloudmasterd/website/stylesheets/screen.css @@ -0,0 +1,138 @@ +body { + background-color: #E1D1F1; + font-family: "Georgia", sans-serif; + font-size: 16px; + line-height: 1.6em; + padding: 1.6em 0 0 0; + color: #333; +} +h1, h2, h3, h4, h5, h6 { + color: #444; +} +h1 { + font-family: sans-serif; + font-weight: normal; + font-size: 4em; + line-height: 0.8em; + letter-spacing: -0.1ex; + margin: 5px; +} +li { + padding: 0; + margin: 0; + list-style-type: square; +} +a { + color: #5E5AFF; + background-color: #DAC; + font-weight: normal; + text-decoration: underline; +} +blockquote { + font-size: 90%; + font-style: italic; + border-left: 1px solid #111; + padding-left: 1em; +} +.caps { + font-size: 80%; +} + +#main { + width: 45em; + padding: 0; + margin: 0 auto; +} +.coda { + text-align: right; + color: #77f; + font-size: smaller; +} + +table { + font-size: 90%; + line-height: 1.4em; + color: #ff8; + background-color: #111; + padding: 2px 10px 2px 10px; + border-style: dashed; +} + +th { + color: #fff; +} + +td { + padding: 2px 10px 2px 10px; +} + +.success { + color: #0CC52B; +} + +.failed { + color: #E90A1B; +} + +.unknown { + color: #995000; +} +pre, code { + font-family: monospace; + font-size: 90%; + line-height: 1.4em; + color: #ff8; + background-color: #111; + padding: 2px 10px 2px 10px; +} +.comment { color: #aaa; font-style: italic; } +.keyword { color: #eff; font-weight: bold; } +.punct { color: #eee; font-weight: bold; } +.symbol { color: #0bb; } +.string { color: #6b4; } +.ident { color: #ff8; } +.constant { color: #66f; } +.regex { color: #ec6; } +.number { color: #F99; } +.expr { color: #227; } + +#version { + float: right; + text-align: right; + font-family: sans-serif; + font-weight: normal; + background-color: #B3ABFF; + color: #141331; + padding: 15px 20px 10px 20px; + margin: 0 auto; + margin-top: 15px; + border: 3px solid #141331; +} + +#version .numbers { + display: block; + font-size: 4em; + line-height: 0.8em; + letter-spacing: -0.1ex; + margin-bottom: 15px; +} + +#version p { + text-decoration: none; + color: #141331; + background-color: #B3ABFF; + margin: 0; + padding: 0; +} + +#version a { + text-decoration: none; + color: #141331; + background-color: #B3ABFF; +} + +.clickable { + cursor: pointer; + cursor: hand; +} + diff --git a/cloudmasterd/website/template.html.erb b/cloudmasterd/website/template.html.erb new file mode 100644 index 0000000..b279c36 --- /dev/null +++ b/cloudmasterd/website/template.html.erb @@ -0,0 +1,48 @@ + + + + + + + <%= title %> + + + + + + +
+ +

<%= title %>

+
+

Get Version

+ <%= version %> +
+ <%= body %> +

+ Brenton Leanhardt, <%= modified.pretty %>
+ Theme extended from Paul Battley +

+
+ + + + + -- cgit