├── .gitignore ├── .rvmrc ├── .travis.yml ├── Gemfile ├── Guardfile ├── README.md ├── Rakefile ├── bin ├── mccloud └── mccloud_old ├── doc └── old-README.md ├── lib ├── mccloud.rb └── mccloud │ ├── cli.rb │ ├── command.rb │ ├── command │ ├── balance.rb │ ├── base.rb │ ├── bootstrap.rb │ ├── define.rb │ ├── destroy.rb │ ├── forward.rb │ ├── group_base.rb │ ├── halt.rb │ ├── helpers.rb │ ├── image.rb │ ├── init.rb │ ├── init_vagrant.rb │ ├── ip.rb │ ├── ips.rb │ ├── keypair.rb │ ├── keystore.rb │ ├── lb.rb │ ├── named_base.rb │ ├── package.rb │ ├── provider.rb │ ├── provision.rb │ ├── reload.rb │ ├── sorry.rb │ ├── ssh.rb │ ├── status.rb │ ├── template.rb │ ├── undefine.rb │ ├── up.rb │ ├── version.rb │ └── vm.rb │ ├── config.rb │ ├── config │ ├── collection.rb │ ├── component.rb │ ├── definition.rb │ ├── keypair.rb │ ├── mccloud.rb │ ├── provider.rb │ └── template.rb │ ├── definition.rb │ ├── definitions.rb │ ├── environment.rb │ ├── error.rb │ ├── generator.rb │ ├── keypair.rb │ ├── mccloudfile.rb │ ├── provider │ ├── aws │ │ ├── image.rb │ │ ├── ip.rb │ │ ├── ip │ │ │ └── associate.rb │ │ ├── keystore.rb │ │ ├── lb.rb │ │ ├── lb │ │ │ ├── associate.rb │ │ │ └── sorry.rb │ │ ├── provider.rb │ │ ├── provider │ │ │ ├── image_destroy.rb │ │ │ ├── image_list.rb │ │ │ ├── ip_list.rb │ │ │ ├── keystore_list.rb │ │ │ ├── keystore_sync.rb │ │ │ ├── lb_list.rb │ │ │ ├── old_deregister.rb │ │ │ ├── old_flavors.rb │ │ │ ├── old_ips.rb │ │ │ ├── old_loadbalance.rb │ │ │ ├── old_package.rb │ │ │ ├── old_sorry.rb │ │ │ ├── old_status.rb │ │ │ ├── old_validate.rb │ │ │ └── status.rb │ │ ├── stack.rb │ │ ├── stack │ │ │ ├── old_destroy.rb │ │ │ ├── old_up.rb │ │ │ └── old_vm.rb │ │ ├── vm.rb │ │ └── vm │ │ │ ├── bootstrap.rb │ │ │ ├── destroy.rb │ │ │ ├── forward.rb │ │ │ ├── halt.rb │ │ │ ├── package.rb │ │ │ ├── provision.rb │ │ │ ├── reload.rb │ │ │ ├── resume.rb │ │ │ ├── rsync.rb │ │ │ ├── scp.rb │ │ │ ├── ssh.rb │ │ │ ├── suspend.rb │ │ │ └── up.rb │ ├── core │ │ ├── forwarding.rb │ │ ├── ip.rb │ │ ├── keystore.rb │ │ ├── lb.rb │ │ ├── provider.rb │ │ ├── vm.rb │ │ └── vm │ │ │ ├── old_halt.rb │ │ │ ├── old_init.rb │ │ │ ├── old_multi.rb │ │ │ ├── old_reload.rb │ │ │ ├── old_server.rb │ │ │ ├── old_ssh_command.rb │ │ │ ├── old_suspend.rb │ │ │ ├── old_wizard.rb │ │ │ ├── rsync.rb │ │ │ ├── ssh.rb │ │ │ ├── ssh_bootstrap.rb │ │ │ └── ssh_forward.rb │ ├── fog │ │ ├── fogconfig.rb │ │ └── provider.rb │ ├── host │ │ ├── provider.rb │ │ ├── provider │ │ │ └── status.rb │ │ ├── vm.rb │ │ └── vm │ │ │ ├── bootstrap.rb │ │ │ ├── forward.rb │ │ │ ├── provision.rb │ │ │ ├── scp.rb │ │ │ └── ssh.rb │ ├── libvirt │ │ ├── provider.rb │ │ ├── provider │ │ │ └── status.rb │ │ ├── vm.rb │ │ └── vm │ │ │ ├── bootstrap.rb │ │ │ ├── destroy.rb │ │ │ ├── forward.rb │ │ │ ├── halt.rb │ │ │ ├── provision.rb │ │ │ ├── reload.rb │ │ │ ├── rsync.rb │ │ │ ├── scp.rb │ │ │ ├── ssh.rb │ │ │ └── up.rb │ ├── script │ │ ├── provider.rb │ │ ├── provider │ │ │ └── status.rb │ │ └── vm.rb │ ├── vagrant │ │ ├── provider.rb │ │ ├── provider │ │ │ └── status.rb │ │ ├── vm.rb │ │ └── vm │ │ │ ├── destroy.rb │ │ │ ├── forward.rb │ │ │ ├── halt.rb │ │ │ ├── provision.rb │ │ │ ├── reload.rb │ │ │ ├── resume.rb │ │ │ ├── ssh.rb │ │ │ ├── suspend.rb │ │ │ └── up.rb │ └── vmfusion │ │ ├── provider.rb │ │ ├── provider │ │ └── status.rb │ │ ├── vm.rb │ │ └── vm │ │ ├── forward.rb │ │ ├── halt.rb │ │ ├── resume.rb │ │ ├── suspend.rb │ │ └── up.rb │ ├── provisioner │ ├── chef_solo.rb │ ├── puppet.rb │ └── shell.rb │ ├── template.rb │ ├── templates.rb │ ├── templates │ ├── Mccloudfile.erb │ ├── bootstrap │ │ ├── bootstrap-centos-rubysource-1.8.7.sh │ │ ├── bootstrap-centos-rvm-1.8.7.sh │ │ ├── bootstrap-centos-rvm-1.9.2.sh │ │ ├── bootstrap-centos-rvm-ree-1.8.7.sh │ │ ├── bootstrap-chef-omnibus.sh │ │ ├── bootstrap-custom.sh │ │ ├── bootstrap-ubuntu-rvm-1.8.7.sh │ │ └── bootstrap-ubuntu-system.sh │ ├── locales │ │ └── en.yml │ └── vm.erb │ ├── ui.rb │ ├── util │ ├── platform.rb │ ├── rostruct.rb │ ├── ssh.rb │ └── sshkey.rb │ ├── version.rb │ ├── vm.rb │ └── vms.rb ├── mccloud.gemspec ├── samples ├── Mccloudfile ├── bitnami_drupal_cloud.json ├── bootstrap-ubuntu-system.sh ├── mcollective_cloud.json ├── stack_cloud.json └── stacks.txt ├── spec ├── commands │ ├── define_spec.rb │ └── init_spec.rb ├── environment │ └── environment_spec.rb ├── generator_spec.rb ├── keypair_spec.rb ├── provider │ └── aws │ │ └── credentials_spec.rb ├── provisioner │ └── puppet │ │ ├── Mccloud-puppet-test │ │ └── puppet_spec.rb └── spec_helper.rb └── templates └── ubuntu-10.10-server-amd64 ├── aws.json ├── bootstrap.sh ├── definition.old └── mccloud.erb /.gitignore: -------------------------------------------------------------------------------- 1 | Mccloudfile* 2 | .mccloud 3 | puppet/* 4 | manifests/* 5 | vms/* 6 | definitions/* 7 | /^modules/ 8 | ^chef/* 9 | .fog 10 | /^bootstrap*/ 11 | pkg/* 12 | *.swp 13 | Gemfile.lock 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /.rvmrc: -------------------------------------------------------------------------------- 1 | rvm use ruby-2.1 2 | #rvm use ruby-1.9.2 3 | rvm gemset use mccloud 4 | alias mccloud="bundle exec mccloud" 5 | alias irb="bundle exec irb" 6 | alias rake="bundle exec rake" 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0 4 | notifications: 5 | irc: "chat.freenode.net#mccloud" 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | #gem 'fog', :path => "/Users/patrick/imac/fog" 4 | #gem "fog", :git => 'git@github.com:geemus/fog.git',:branch => 'master' 5 | 6 | #http://www.deploymentzone.com/2011/05/24/guard-rspec-2-and-growl/ 7 | group :development do 8 | gem 'rspec', '>= 2.0' 9 | gem "rake" 10 | gem 'parallel_tests' 11 | end 12 | 13 | gem "mccloud", :path => "." 14 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :rspec, :version => 2, :cli => "--color --format documentation" do 2 | watch(%r{spec/.+_spec\.rb$}) 3 | watch(%r{^lib/(.+)\.rb$}) { "spec" } 4 | #watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 5 | watch(%r{spec/spec_helper\.rb$}) { "spec" } 6 | end 7 | 8 | guard :cucumber, :cli => "-s" do 9 | watch(%r{lib/(.+)\.rb$}) { "features" } 10 | end 11 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | Bundler::GemHelper.install_tasks 3 | 4 | desc 'Default: run tests' 5 | task :default => :test 6 | 7 | require 'rake' 8 | require 'rspec/core/rake_task' 9 | require 'rake/testtask' 10 | 11 | 12 | desc 'Tests not requiring an real box' 13 | Rake::TestTask.new do |t| 14 | t.libs << "test" 15 | t.pattern = 'test/**/*_test.rb' 16 | end 17 | 18 | desc 'Tests requiring an real providers' 19 | Rake::TestTask.new do |t| 20 | t.name="realtest" 21 | t.libs << "test" 22 | t.pattern = 'test/**/*_realtest.rb' 23 | end 24 | 25 | 26 | desc 'Specs' 27 | RSpec::Core::RakeTask.new(:spec) do |t| 28 | t.pattern = './spec/**/*_spec.rb' # don't need this, it's default 29 | t.verbose = true 30 | #t.rspec_opts = "--format documentation --color" 31 | # Put spec opts in a file named .rspec in root 32 | end 33 | -------------------------------------------------------------------------------- /bin/mccloud: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'mccloud' 3 | 4 | 5 | begin 6 | 7 | # Disable color if the proper argument was passed 8 | shell = ARGV.include?("--no-color") ? Thor::Shell::Basic.new : Thor::Base.shell.new 9 | 10 | 11 | # Start the CLI 12 | begin 13 | env = Mccloud::Environment.new(:cwd => ".") 14 | 15 | # # Attach the UI 16 | env.ui = ::Mccloud::UI::Shell.new(env, shell) 17 | 18 | ::Mccloud::CLI.start(ARGV,:env => env) 19 | rescue Mccloud::Error => ex 20 | env.ui.error "#{ex}" 21 | exit 1 22 | rescue Exception => ex 23 | puts "Something blew up Mccloud. Time for McGuyver:" 24 | puts "" 25 | puts "#{ex}" 26 | puts ex.backtrace 27 | exit 1 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /doc/old-README.md: -------------------------------------------------------------------------------- 1 | # This needs to be completely rewritten for the new version!!! 2 | 3 | 4 | ## Note: 5 | - This is a quick copy and paste job(weekend hacking), you should not consider it anything but experimental right now 6 | - But I wanted to share the idea already with others 7 | 8 | ## DISCLAIMER: 9 | this is alpha sofware . Don't trust it:) And don't complain if it removes all your EC instances at once.... 10 | 11 | ## Kudos to great stuff 12 | - [Vagrant](http://www.vagrantup.com) is great for testing machines on your local machines 13 | - [Fog](https://github.com/geemus/fog) is a great fog library for managing cloud systems 14 | 15 | Without those two, this project would not be possible. Kudos to the authors! 16 | 17 | This project tries to combine both: 18 | - Because your local machine might outgrow your complexity your local machine can handle 19 | - use the same vagrantfile for local dev, and cloud devel 20 | 21 | ## Some notes before you dive in 22 | 23 | - I could probably have integrated with vagrant code but this would have taken me longer to understand vagrant code 24 | - I didn't want the dependency on virtualbox 25 | - The machines it creates will have the prefix as defined in the Mccloudfile, so this should not pollute your stuff 26 | 27 | ## Todo: 28 | 29 | - provision to other providers than ec2 30 | - try to stay fully compatible with Vagrantfile 31 | 32 | ## How it will work/works 33 | 34 | ### Create a config file for fog. Note that these are spaces in front and no tabs 35 | $ cat $HOME/.fog 36 |
37 | :default:
38 |   :aws_access_key_id: 
39 |   :aws_secret_access_key: 
40 | 
41 | 42 | ### Create a Mccloud project 43 | $ mccloud init 44 | 45 | This will create a Mccloudfile 46 | 47 | ### Edit your Mccloud appropriate 48 | 49 |
50 | 
51 | 52 | ### Start your machines 53 | # If the machine does not yet exist, it will also run bootstrap 54 | $ mccloud up web 55 | 56 | ### Check the status 57 | $ mccloud status 58 | 59 | ### Bootstrap the machine 60 | $ mccloud bootstrap web 61 | 62 | ### (interactive) Login into the machine 63 | $ mccloud ssh web 64 | 65 | ### run a command on a machine 66 | $ mccloud command web "who am i" 67 | 68 | ### Halt the machine 69 | $ mccloud halt web 70 | 71 | ### Start the machine again 72 | $ mccloud up web 73 | 74 | ### Provision the machine 75 | $ mccloud provision web 76 | 77 | ### Port forwarding server 78 | $ mccloud server 79 | 80 | ### Destroy the machine again 81 | $ mccloud destroy web 82 | -------------------------------------------------------------------------------- /lib/mccloud.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | require 'i18n' 4 | require 'openssl' 5 | require 'pathname' 6 | 7 | module Mccloud 8 | # The source root is the path to the root directory of 9 | # the Mccloud gem. 10 | def self.source_root 11 | @source_root ||= Pathname.new(File.expand_path('../../', __FILE__)) 12 | end 13 | end 14 | 15 | # # Default I18n to load the en locale 16 | I18n.load_path << File.expand_path("lib/mccloud/templates/locales/en.yml", Mccloud.source_root) 17 | 18 | # Load the things which must be loaded before anything else 19 | require 'mccloud/cli' 20 | require 'mccloud/ui' 21 | require 'mccloud/command' 22 | require 'mccloud/error' 23 | #require 'mccloud/logger' 24 | require 'mccloud/environment' 25 | require 'mccloud/version' 26 | -------------------------------------------------------------------------------- /lib/mccloud/cli.rb: -------------------------------------------------------------------------------- 1 | require 'thor' 2 | 3 | module Mccloud 4 | # Entrypoint for the Mccloud CLI. This class should never be 5 | # initialized directly (like a typical Thor class). Instead, 6 | # use {Environment#cli} to invoke the CLI. 7 | # 8 | # # Defining Custom CLI Commands 9 | # 10 | # If you're looking to define custom CLI commands, then look at 11 | # one of the two following classes: 12 | # 13 | # * {Command::Base} - Implementing a single command such as `mccloud up`, e.g. 14 | # one without subcommands. Also take a look at {Command::NamedBase}. 15 | # * {Command::GroupBase} - Implementing a command with subcommands, such as 16 | # `mccloud box`, which has the `list`, `add`, etc. subcommands. 17 | # 18 | # The above linked classes contain the main documentation for each 19 | # type of command. 20 | class CLI < Thor 21 | # Registers the given class with the CLI so it can be accessed. 22 | # The class must be a subclass of either {Command::Base} or {Command::GroupBase}. 23 | # Don't call this method directly, instead call the {Command::Base.register} 24 | # or {Command::GroupBase.register} methods. 25 | # 26 | # @param [Class] klass Command class 27 | # @param [String] name Command name, accessed at `mccloud NAME` 28 | # @param [String] usage Command usage, such as "mccloud NAME [--option]" 29 | # @param [String] description Description of the command shown during the 30 | # command listing. 31 | # @param [Hash] opts Other options (not gone into detail here, look at 32 | # the source instead). 33 | def self.register(klass, name, usage, description, opts=nil) 34 | opts ||= {} 35 | 36 | if klass <= Command::GroupBase 37 | # A subclass of GroupBase is a subcommand, since it contains 38 | # many smaller commands within it. 39 | desc usage, description, opts 40 | subcommand name, klass 41 | elsif klass <= Command::Base 42 | # A subclass of Base is a single command, since it 43 | # is invoked as a whole (as Thor::Group) 44 | desc usage, description, opts 45 | define_method(name) { |*args| invoke klass, args } 46 | end 47 | 48 | if opts[:alias] 49 | # Alises are defined for this command, so properly alias the 50 | # newly defined method/subcommand: 51 | map opts[:alias] => name 52 | end 53 | end 54 | end 55 | end #Mccloud -------------------------------------------------------------------------------- /lib/mccloud/command.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | autoload :Base, 'mccloud/command/base' 4 | autoload :GroupBase, 'mccloud/command/group_base' 5 | autoload :Helpers, 'mccloud/command/helpers' 6 | autoload :NamedBase, 'mccloud/command/named_base' 7 | end 8 | end 9 | 10 | # The built-in commands must always be loaded 11 | require 'mccloud/command/status' 12 | #require 'mccloud/command/init' 13 | require 'mccloud/command/keypair' 14 | require 'mccloud/command/up' 15 | require 'mccloud/command/bootstrap' 16 | require 'mccloud/command/ssh' 17 | require 'mccloud/command/provision' 18 | require 'mccloud/command/destroy' 19 | require 'mccloud/command/halt' 20 | require 'mccloud/command/ip' 21 | require 'mccloud/command/ips' 22 | require 'mccloud/command/sorry' 23 | require 'mccloud/command/lb' 24 | require 'mccloud/command/vm' 25 | require 'mccloud/command/image' 26 | require 'mccloud/command/balance' 27 | require 'mccloud/command/reload' 28 | require 'mccloud/command/keystore' 29 | #require 'mccloud/command/suspend' 30 | require 'mccloud/command/package' 31 | #require 'mccloud/command/resume' 32 | require 'mccloud/command/forward' 33 | require 'mccloud/command/version' 34 | require 'mccloud/command/template' 35 | require 'mccloud/command/define' 36 | #require 'mccloud/command/undefine' 37 | -------------------------------------------------------------------------------- /lib/mccloud/command/balance.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class BalanceCommand < Base 4 | 5 | register "balance [LB-NAME]", "Balances loadbalancers" 6 | argument :selection, :type => :string, :optional => true, :default => nil 7 | 8 | def execute 9 | env.load! 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to associate to #{selection}") 12 | provider.on_selected_components("lb",selection) do |id,lb| 13 | lb.associate(options) 14 | end 15 | end 16 | end 17 | 18 | end 19 | 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/mccloud/command/bootstrap.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class BootstrapCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => true, :default => nil 6 | argument :command, :type => :string, :optional => true, :default => nil 7 | 8 | register "bootstrap [NAME] [FILENAME]", "Executes the bootstrap sequence" 9 | 10 | def execute 11 | env.load! 12 | env.config.providers.each do |name,provider| 13 | env.logger.debug("Asking provider #{name} to boostrap box #{box_name}") 14 | provider.bootstrap(box_name,command,options) 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/mccloud/command/define.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | module Mccloud 3 | module Command 4 | class DefineCommand < Base 5 | 6 | register "define NAME TEMPLATE-NAME", "Creates a new definition based on a tempate" 7 | argument :name, :type => :string, :optional => false, :default => nil 8 | argument :template, :type => :string, :optional => false, :default => nil 9 | 10 | def execute 11 | env.ui.info "Define #{name} with template #{template}" 12 | env.config.definitions.define(name,template) 13 | end 14 | 15 | end 16 | 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/mccloud/command/destroy.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class DestroyCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => false, :default => nil 6 | 7 | register "destroy [NAME]", "Destroys the machine" 8 | 9 | def execute 10 | env.load! 11 | env.config.providers.each do |name,provider| 12 | env.logger.debug("Asking provider #{name} to destroy box #{box_name}") 13 | provider.destroy(box_name,options) 14 | end 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/mccloud/command/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class ForwardCommand < Base 4 | 5 | register "forward [NAME]", "Forwards ports from a machine to localhost" 6 | argument :selection, :type => :string, :optional => true, :default => nil 7 | 8 | def execute 9 | env.load! 10 | threads=Array.new 11 | env.config.providers.each do |name,provider| 12 | env.logger.debug("Asking provider #{name} to forward ports from #{selection} to localhost") 13 | trap("INT") { puts "You've hit CTRL-C . Stopping server now"; exit } 14 | provider.on_selected_components("vm",selection) do |id,vm| 15 | fwds=vm.forward(options) 16 | unless fwds.nil? 17 | fwds.each do |f| 18 | threads << f 19 | end 20 | end 21 | threads.each { |thr| thr.join} 22 | end 23 | 24 | end 25 | 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/mccloud/command/halt.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class HaltCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => true, :default => nil 6 | 7 | register "halt [NAME]", "Shutdown the machine" 8 | def execute 9 | env.load! 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to halt box #{box_name}") 12 | provider.halt(box_name,options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/command/helpers.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | module Helpers 4 | # Initializes the environment by pulling the environment out of 5 | # the configuration hash and sets up the UI if necessary. 6 | def initialize_environment(args, options, config) 7 | raise ::Mccloud::Error,"CLI Missing Environment" if !config[:env] 8 | @env = config[:env] 9 | end 10 | 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mccloud/command/image.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class ImageCommand < Mccloud::Command::GroupBase 4 | register "image", "Subcommand to manage images" 5 | 6 | desc "list [IMAGE-NAME]", "List Images" 7 | def list(selection=nil) 8 | env.load! 9 | 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to list image #{selection}") 12 | provider.image_list(selection,options) 13 | end 14 | end 15 | 16 | desc "create [SERVER-NAME]", "Create Image from Server" 17 | def create(selection=nil) 18 | env.load! 19 | 20 | env.ui.error "Not yet implemented" 21 | end 22 | 23 | desc "destroy IMAGE-NAME","Destroy image" 24 | def destroy(selection) 25 | env.load! 26 | 27 | env.config.providers.each do |name,provider| 28 | env.logger.debug("Asking provider #{name} to destroy image #{selection}") 29 | provider.image_destroy(selection,options) 30 | end 31 | 32 | end 33 | 34 | end #Class 35 | 36 | end #Module 37 | end # Module 38 | -------------------------------------------------------------------------------- /lib/mccloud/command/init.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class InitCommand < Base 4 | 5 | register "init", "Initializes a new Mccloud project" 6 | class_option :provider, :type => :string , :default => "aws", :aliases => "-p" 7 | 8 | def execute 9 | env.generator.generate(options) 10 | end 11 | 12 | end #Class 13 | end #Module 14 | end #Module 15 | -------------------------------------------------------------------------------- /lib/mccloud/command/init_vagrant.rb: -------------------------------------------------------------------------------- 1 | module Vagrant 2 | module Command 3 | class InitCommand < Base 4 | argument :box_name, :type => :string, :optional => true, :default => "base" 5 | argument :box_url, :type => :string, :optional => true 6 | source_root File.expand_path("templates/commands/init", Vagrant.source_root) 7 | register "init [box_name] [box_url]", "Initializes the current folder for Vagrant usage" 8 | 9 | def execute 10 | template "Vagrantfile.erb", "Vagrantfile" 11 | end 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/mccloud/command/ip.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class IpCommand < Mccloud::Command::GroupBase 4 | register "ip", "Subcommand to manage IP's" 5 | 6 | desc "associate [IP-NAME]", "Associate IP addresses" 7 | def associate(selection=nil) 8 | env.load! 9 | 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to associate to #{selection}") 12 | provider.on_selected_components("ip",selection) do |id,ip| 13 | ip.associate(options) 14 | end 15 | end 16 | end 17 | 18 | desc "list [IP-NAME]", "List IP addresses" 19 | #method_options :test => :boolean 20 | def list(selection=nil) 21 | env.load! 22 | 23 | env.config.providers.each do |name,provider| 24 | env.logger.debug("Asking provider #{name} to list ip #{selection}") 25 | provider.ip_list(selection,options) 26 | end 27 | end 28 | 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/mccloud/command/ips.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class IpsCommand < Base 4 | 5 | register "ips [NAME]", "Associate IP addresses" 6 | argument :selection, :type => :string, :optional => true, :default => nil 7 | 8 | def execute 9 | env.load! 10 | 11 | env.config.providers.each do |name,provider| 12 | env.logger.debug("Asking provider #{name} to associate to #{selection}") 13 | provider.on_selected_components("ip",selection) do |id,ip| 14 | ip.associate(options) 15 | end 16 | end 17 | end 18 | 19 | end 20 | 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/mccloud/command/keypair.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/sshkey' 2 | 3 | module Mccloud 4 | module Command 5 | class KeypairCommand < Mccloud::Command::GroupBase 6 | register "keypair", "Subcommand to manage keypairs" 7 | 8 | desc "list", "List defined keypairs" 9 | #method_options :test => :boolean 10 | def list(selection=nil) 11 | 12 | env.config.keypairs.each do |name,provider| 13 | env.ui.info("Keypair name:#{name}") 14 | end 15 | end 16 | 17 | desc "generate", "Generate a keypair" 18 | def generate(name=nil) 19 | rsa_key=::Mccloud::Util::SSHKey.generate({ :comment => "mykey"}) 20 | env.ui.info rsa_key.ssh_public_key 21 | env.ui.info rsa_key.rsa_private_key 22 | end 23 | end 24 | 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /lib/mccloud/command/keystore.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class KeystoreCommand < Mccloud::Command::GroupBase 4 | register "keystore", "Subcommand to manage keystores" 5 | 6 | desc "list [KEY-NAME]", "List Keys in Keystore" 7 | #method_options :test => :boolean 8 | def list(selection=nil) 9 | 10 | env.config.providers.each do |name,provider| 11 | env.ui.info("Asking provider #{name} to list keystore #{selection}") 12 | provider.keystore_list(selection,options) 13 | end 14 | end 15 | 16 | desc "sync [KEY-NAME]", "Syncs Local keys with Remote Keystore" 17 | method_options :overwrite=> :boolean 18 | def sync(selection=nil) 19 | 20 | env.config.providers.each do |name,provider| 21 | env.ui.info("Asking provider #{name} to sync keystore #{selection}") 22 | provider.keystore_sync(selection,options) 23 | end 24 | end 25 | 26 | end 27 | 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/mccloud/command/lb.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class LbCommand < Mccloud::Command::GroupBase 4 | register "lb", "Subcommand to manage Loadbalancers" 5 | 6 | desc "list [LB-NAME]", "List loadbalancers" 7 | method_options :test => :boolean 8 | def list(selection=nil) 9 | env.config.providers.each do |name,provider| 10 | env.logger.debug("Asking provider #{name} to list lb #{selection}") 11 | provider.lb_list(selection,options) 12 | end 13 | end 14 | 15 | desc "associate [LB-NAME]", "Associate LB addresses" 16 | def associate(selection=nil) 17 | env.config.providers.each do |name,provider| 18 | env.logger.debug("Asking provider #{name} to associate lb #{selection}") 19 | provider.on_selected_components("lb",selection) do |id,lb| 20 | lb.associate(options) 21 | end 22 | end 23 | end 24 | 25 | desc "sorry [LB-NAME]", "Put loadbalancers in a sorry state" 26 | def sorry(selection=nil) 27 | env.config.providers.each do |name,provider| 28 | env.logger.debug("Asking provider #{name} to sorry lb #{selection}") 29 | provider.on_selected_components("lb",selection) do |id,lb| 30 | lb.sorry(options) 31 | end 32 | end 33 | end 34 | 35 | end #Class 36 | 37 | end #Module 38 | end # Module 39 | -------------------------------------------------------------------------------- /lib/mccloud/command/named_base.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | # Same as {Base} except adds the `name` argument for you. This superclass 4 | # is useful if you're creating a command which should be able to target 5 | # a specific VM in a multi-VM environment. For example, in a multi-VM 6 | # environment, `vagrant up` "ups" all defined VMs, but you can specify a 7 | # name such as `vagrant up web` to target only a specific VM. That name 8 | # argument is from {NamedBase}. Of course, you can always add it manually 9 | # yourself, as well. 10 | class NamedBase < Base 11 | argument :name, :type => :string, :optional => true 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/mccloud/command/package.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class PackageCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => false, :default => nil 6 | 7 | register "package [NAME]", "Packages the machine" 8 | 9 | def execute 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to package box #{box_name}") 12 | provider.package(box_name,options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/command/provider.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module EnvironmentCommand 3 | 4 | def boot(selection=nil,options=nil) 5 | @config.providers.each do |name,provider| 6 | provider.boot(selection,command,options) 7 | end 8 | end 9 | 10 | def bootstrap(selection=nil,options=nil) 11 | @config.providers.each do |name,provider| 12 | provider.bootstrap(selection,options) 13 | end 14 | end 15 | 16 | def halt(selection,options) 17 | @config.providers.each do |name,provider| 18 | provider.halt(selection,options) 19 | end 20 | end 21 | 22 | def rsync(selection,path,options) 23 | @config.providers.each do |name,provider| 24 | provider.rsync(selection,path,options) 25 | end 26 | end 27 | 28 | 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/mccloud/command/provision.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class ProvisionCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => false, :default => nil 6 | 7 | register "provision [NAME]", "Provisions the machine" 8 | 9 | def execute 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to provision box #{box_name}") 12 | provider.provision(box_name,options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/command/reload.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class ReloadCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => true, :default => nil 6 | 7 | register "reload [NAME]", "Reboots the machine" 8 | 9 | def execute 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to reload box #{box_name}") 12 | provider.reload(box_name,options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/command/sorry.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class SorryCommand < Base 4 | 5 | register "sorry [LB-NAME]", "Puts loadbalancers in a sorry state" 6 | argument :selection, :type => :string, :optional => true, :default => nil 7 | 8 | def execute 9 | env.config.providers.each do |name,provider| 10 | env.logger.debug("Asking provider #{name} to sorry #{selection}") 11 | provider.on_selected_components("lb",selection) do |id,lb| 12 | lb.sorry(options) 13 | end 14 | end 15 | end 16 | 17 | end 18 | 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/mccloud/command/ssh.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class SshCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => false, :default => nil 6 | argument :command, :type => :string, :optional => true, :default => nil 7 | 8 | register "ssh [NAME] [COMMAND]", "Ssh-shes into the box" 9 | 10 | def execute 11 | env.config.providers.each do |name,provider| 12 | env.logger.debug("Asking provider #{name} to ssh into box #{box_name}") 13 | provider.ssh(box_name,command,options) 14 | end 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/mccloud/command/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class StatusCommand < Base 4 | 5 | class_option :force, :type => :boolean, :default => false, :aliases => "-f" 6 | class_option :debug,:type => :boolean , :default => false, :aliases => "-d", :desc => "enable debugging" 7 | class_option :provider, :type => :string, :optional => true, :default => nil 8 | argument :name, :type => :string, :optional => true, :default => nil 9 | register "status [name]", "Shows the status of the current Mccloud environment" 10 | 11 | def execute 12 | env.load! 13 | env.config.providers.each do |provider_name,provider_instance| 14 | provider_instance.status(name,options) 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/mccloud/command/template.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class TemplateCommand < Mccloud::Command::GroupBase 4 | register "template", "Subcommand to manage templates" 5 | 6 | desc "list [TEMPLATE-NAME]", "List templates" 7 | def list(selection=nil) 8 | env.config.templates.each do |name,template| 9 | env.ui.info template.to_s 10 | end 11 | end 12 | 13 | end 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/mccloud/command/undefine.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | module Mccloud 3 | module Command 4 | class UnDefineCommand < Base 5 | 6 | register "undefine NAME", "Undefines a machine" 7 | argument :name, :type => :string, :optional => false, :default => nil 8 | 9 | def execute 10 | env.ui.info "Undefine machine #{name}" 11 | filename=File.join("vms","#{name}.rb") 12 | if File.exists?(filename) 13 | env.ui.info "Removing #{filename}" 14 | FileUtils.rm(filename) 15 | else 16 | env.ui.info "Machine #{name} has not yet defined" 17 | end 18 | end 19 | 20 | end 21 | 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/mccloud/command/up.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class UpCommand < Base 4 | 5 | argument :box_name, :type => :string, :optional => true, :default => nil 6 | 7 | register "up [NAME]", "Starts the machine and provisions it" 8 | 9 | def execute 10 | env.config.providers.each do |name,provider| 11 | env.logger.debug("Asking provider #{name} to up box #{box_name}") 12 | provider.up(box_name,options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/command/version.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class VersionCommand < Base 4 | 5 | register "version", "Prints the Mccloud version information" 6 | 7 | def execute 8 | env.ui.info "Version : #{Mccloud::VERSION} - use at your own risk" 9 | end 10 | 11 | end 12 | 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/mccloud/command/vm.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | class VmCommand < Mccloud::Command::GroupBase 4 | register "vm", "Subcommand to manage vms" 5 | 6 | desc "define [VM-NAME] [DEFINITION-NAME]", "define a new vm based on a definition" 7 | def define(vm_name,definition_name) 8 | env.config.vms.define(vm_name,definition_name) 9 | end 10 | 11 | desc "list", "list all known vms" 12 | def list 13 | vms = env.config.vms.sort 14 | printf("%-30s|%-20s|%-15s|%-15s\n","alias","provider","ip-address","private-address") 15 | 80.times do 16 | print '-' 17 | end 18 | puts 19 | vms.each do |name,vm| 20 | printf("%-30s|%-20s|%-15s|%-15s\n",name,vm.provider.name,vm.ip_address,vm.private_ip_address) 21 | end 22 | end 23 | 24 | end #Class 25 | 26 | end #Module 27 | end # Module 28 | -------------------------------------------------------------------------------- /lib/mccloud/config/collection.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/config/component' 2 | require 'ostruct' 3 | 4 | module Mccloud 5 | class Config 6 | class Collection 7 | 8 | attr_accessor :components 9 | attr_accessor :type 10 | attr_accessor :config 11 | 12 | attr_reader :env 13 | 14 | def initialize(type,config) 15 | @type=type 16 | @components=Hash.new 17 | @providers=config.providers 18 | @config=config 19 | @env=config.env 20 | end 21 | 22 | def define(name) 23 | # We do this for vagrant syntax 24 | # Depending on type, we create a variable of that type 25 | # f.i. component_stub.vm or component_stub.lb 26 | component_stub=OpenStruct.new 27 | component_stub.send("#{@type}=",::Mccloud::Config::Component.new(config)) 28 | 29 | env.logger.info("config collection"){ "First pass of reading the config"} 30 | # Now we can 'execute' the config file using our stub component 31 | # For guessing the provider type 32 | yield component_stub 33 | 34 | env.logger.debug("config collection"){ "Stubs collection type #{@type} is loaded"} 35 | 36 | # After processing we extract the component again 37 | component=component_stub.send("#{@type}") 38 | 39 | 40 | # Checking if this component has a base definition 41 | provider_name=nil 42 | if component.provider.nil? 43 | env.logger.debug("config collection"){ "We got an empty provider here"} 44 | env.logger.debug("config collection"){ "Trying if there is a definition provider"} 45 | unless component.definition.nil? 46 | provider_name=env.config.definitions[component.definition].provider 47 | end 48 | else 49 | provider_name=component.provider.to_s 50 | end 51 | 52 | provider=@providers[provider_name] 53 | 54 | env.logger.debug("config collection"){ "We get here"} 55 | 56 | if provider.nil? 57 | env.ui.warn "Provider #{component.provider.to_s} does not (yet) exist" 58 | env.ui.warn "Skipping definition of #{name}" 59 | return 60 | end 61 | 62 | unless component.definition.nil? 63 | real_component=env.config.definitions[component.definition].to_vm("blub") 64 | else 65 | real_component=provider.get_component(@type.capitalize,env) 66 | end 67 | 68 | begin 69 | 70 | # And repeat the same process with a real component 71 | env.logger.debug("config collection"){ "Component of #{@type}"} 72 | 73 | component_stub.send("#{@type}=",real_component) 74 | 75 | yield component_stub 76 | # After processing we extract the component again 77 | component=component_stub.send("#{@type}") 78 | # And we set the name 79 | component.name=name 80 | 81 | # We set the provider for this component 82 | component.provider=provider 83 | 84 | # And register this component with the provider 85 | # if it is a vm, we add to the hash vms 86 | # if it is an ip, we add it to the hash ips 87 | provider_collection=provider.instance_variable_get("@#{@type}s") 88 | env.logger.debug("registering #{name} with provider #{provider.name}") 89 | provider_collection[name]=component 90 | 91 | # And we also add it to the global config element 92 | # So we can have all components of a similar type in one place 93 | config_collection=@config.instance_variable_get("@#{@type}s") 94 | config_collection[name]=component 95 | 96 | # Now we can ask the component to validate itself 97 | #component_stub.validate 98 | components[name.to_s]=component 99 | 100 | rescue Error => e 101 | env.ui.error "Error loading component with #{name} of type #{@type} for provider #{component.provider.type}" 102 | end 103 | end 104 | 105 | end 106 | end 107 | end #Module Mccloud 108 | -------------------------------------------------------------------------------- /lib/mccloud/config/component.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | class Config 3 | class Component 4 | 5 | attr_accessor :provider 6 | attr_accessor :definition 7 | 8 | attr_reader :env 9 | 10 | def initialize(config) 11 | @env=config.env 12 | end 13 | 14 | def method_missing(m, *args, &block) 15 | # env.ui.info "There's no method called #{m} here -- please try again." 16 | end 17 | 18 | end 19 | end 20 | end #Module Mccloud 21 | -------------------------------------------------------------------------------- /lib/mccloud/config/definition.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/config/component' 2 | require 'mccloud/definition' 3 | require 'ostruct' 4 | 5 | module Mccloud 6 | class Config 7 | class Definition 8 | 9 | attr_accessor :components 10 | attr_reader :env 11 | 12 | def initialize(config) 13 | @env=config.env 14 | @components=Hash.new 15 | end 16 | 17 | def define(name) 18 | # We do this for vagrant syntax 19 | # Depending on type, we create a variable of that type 20 | # f.i. component_stub.vm or component_stub.lb 21 | definition_stub=OpenStruct.new 22 | definition_stub.definition=::Mccloud::Definition.new(name,env) 23 | 24 | env.logger.debug("config definitions"){ "Start reading definitions"} 25 | 26 | yield definition_stub 27 | 28 | env.logger.debug("config definitions"){ "End reading definition #{definition_stub.definition.name}"} 29 | 30 | components[name.to_s]=definition_stub.definition 31 | end 32 | 33 | end 34 | end 35 | end #Module Mccloud 36 | -------------------------------------------------------------------------------- /lib/mccloud/config/keypair.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/config/component' 2 | require 'mccloud/keypair' 3 | require 'ostruct' 4 | 5 | module Mccloud 6 | class Config 7 | class Keypair 8 | 9 | attr_accessor :components 10 | attr_reader :env 11 | 12 | def initialize(config) 13 | @env=config.env 14 | @components=Hash.new 15 | env.logger.debug("initalizing keypair") 16 | end 17 | 18 | def define(name) 19 | # We do this for vagrant syntax 20 | # Depending on type, we create a variable of that type 21 | # f.i. component_stub.vm or component_stub.lb 22 | keypair_stub=OpenStruct.new 23 | keypair_stub.keypair=::Mccloud::Keypair.new(name,env) 24 | 25 | env.logger.debug("config keypair"){ "Start reading keypair"} 26 | 27 | yield keypair_stub 28 | 29 | env.logger.debug("config keypair"){ "End reading keypair #{keypair_stub.keypair.name}"} 30 | 31 | components[name.to_s]=keypair_stub.keypair 32 | end 33 | 34 | end 35 | end 36 | end #Module Mccloud 37 | -------------------------------------------------------------------------------- /lib/mccloud/config/mccloud.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | class Config 3 | class Mccloud 4 | 5 | attr_reader :env 6 | 7 | attr_accessor :prefix 8 | attr_accessor :environment 9 | attr_accessor :identity 10 | 11 | attr_accessor :delimiter 12 | attr_accessor :loglevel 13 | 14 | attr_accessor :template_path 15 | attr_accessor :definition_path 16 | attr_accessor :vm_path 17 | 18 | def initialize(config) 19 | @env=config.env 20 | 21 | @prefix="mccloud" 22 | @environment="" 23 | @identity="" 24 | 25 | @delimiter="-" 26 | @loglevel=:info 27 | 28 | @template_path=File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','templates')) 29 | @definition_path=File.join(@env.root_path,"definitions") 30 | @vm_path=File.join(@env.root_path,"vms") 31 | 32 | env.logger.debug("done loading the mccloud setting") 33 | 34 | end 35 | 36 | 37 | end #Class 38 | end #Module 39 | end #Module 40 | -------------------------------------------------------------------------------- /lib/mccloud/config/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/config/component' 2 | require 'ostruct' 3 | 4 | module Mccloud 5 | class Config 6 | class Provider 7 | 8 | attr_accessor :components 9 | attr_reader :env 10 | 11 | def initialize(config) 12 | @env=config.env 13 | @components=Hash.new 14 | end 15 | 16 | def define(name) 17 | # We do this for vagrant syntax 18 | # Depending on type, we create a variable of that type 19 | # f.i. component_stub.vm or component_stub.lb 20 | provider_stub=OpenStruct.new 21 | provider_stub.provider=OpenStruct.new 22 | 23 | env.logger.debug("config provider"){ "Start stubbing provider"} 24 | 25 | # Now we can 'execute' the config file using our stub component 26 | # For guessing the provider type 27 | yield provider_stub 28 | 29 | env.logger.debug("config provider"){ "End stubbing provider"} 30 | 31 | # After processing we extract the provider type and options again 32 | provider_type=provider_stub.provider.flavor 33 | env.logger.debug("config provider"){ "Found provider of type #{provider_type}"} 34 | provider_options=provider_stub.provider.options 35 | 36 | begin 37 | # Now that we know the actual provider, we can check if the provider has this type of component 38 | require_path='mccloud/provider/'+provider_type.to_s.downcase+"/provider" 39 | require require_path 40 | 41 | # Now we can create the real provider 42 | real_provider=Object.const_get("Mccloud").const_get("Provider").const_get(provider_type.to_s.capitalize).const_get("Provider").new(name,provider_options,env) 43 | provider_stub.provider=real_provider 44 | yield provider_stub 45 | 46 | env.logger.debug("config provider"){ "Instantiating provider #{name.to_s}"} 47 | components[name.to_s]=provider_stub.provider 48 | rescue ::Mccloud::Error => ex 49 | raise ::Mccloud::Error, "Error loading provider with #{name}\n#{ex}" 50 | end 51 | end 52 | 53 | end 54 | end 55 | end #Module Mccloud 56 | -------------------------------------------------------------------------------- /lib/mccloud/config/template.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/config/component' 2 | require 'mccloud/template' 3 | require 'ostruct' 4 | 5 | module Mccloud 6 | class Config 7 | class Template 8 | 9 | attr_accessor :components 10 | attr_reader :env 11 | 12 | def initialize(config) 13 | @env=config.env 14 | @components=Hash.new 15 | end 16 | 17 | def define(name) 18 | # We do this for vagrant syntax 19 | # Depending on type, we create a variable of that type 20 | # f.i. component_stub.vm or component_stub.lb 21 | template_stub=OpenStruct.new 22 | template_stub.template=::Mccloud::Template.new(name,env) 23 | 24 | env.logger.debug("config template"){ "Start reading template"} 25 | 26 | yield template_stub 27 | 28 | env.logger.debug("config template"){ "End reading template #{template_stub.template.name}"} 29 | 30 | components[name.to_s]=template_stub.template 31 | end 32 | 33 | end 34 | end 35 | end #Module Mccloud 36 | -------------------------------------------------------------------------------- /lib/mccloud/definition.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | 3 | class Definition 4 | 5 | attr_accessor :name 6 | attr_reader :env 7 | attr_reader :provider 8 | 9 | def initialize(name,env) 10 | @name=name 11 | @env=env 12 | @type="vm" 13 | end 14 | 15 | def provider=(name) 16 | @provider=name 17 | @raw=env.config.providers[name].get_component(@type.capitalize,env) 18 | end 19 | 20 | def method_missing(m, *args, &block) 21 | #puts "There's no method called #{m} here -- please try again." 22 | @raw.send(m,*args) 23 | end 24 | 25 | def valid? 26 | File.exists?(self.definition_path) 27 | end 28 | 29 | def exists? 30 | File.directory?(self.path) 31 | end 32 | 33 | def path 34 | File.join(@env.config.mccloud.definition_path,@name) 35 | end 36 | 37 | def definition_path 38 | File.join(self.path,"mccloud.rb") 39 | end 40 | 41 | def load! 42 | self.validate 43 | 44 | content=File.read(self.definition_path) 45 | mccloud_configurator=env.config 46 | content.gsub!("Mccloud::Config.run","mccloud_configurator.define") 47 | 48 | begin 49 | env.config.instance_eval(content) 50 | rescue Error => ex 51 | raise ::Mccloud::Error, "Error reading definition from file #{definition_file}#{ex}" 52 | end 53 | end 54 | 55 | def to_vm(name) 56 | vm=@raw.dup 57 | vm.name=name 58 | return vm 59 | end 60 | 61 | def validate 62 | raise ::Mccloud::Error, "Definition #{@name} does not yet exist" unless self.exists? 63 | end 64 | 65 | 66 | def copy_template(templatename) 67 | raise ::Mccloud::Error, "Definition #{@name} already exists" if self.exists? 68 | raise ::Mccloud::Error, "Template #{templatename} does not exist" unless @env.config.templates[templatename].exists? 69 | 70 | begin 71 | t=@env.config.templates[templatename] 72 | @env.logger.info "Copying template #{t.path} to definition #{self.path}" 73 | FileUtils.cp_r(t.path,self.path) 74 | save_mccloud_rb 75 | FileUtils.rm(File.join(self.path,"mccloud.erb")) 76 | rescue Exception => ex 77 | raise ::Mccloud::Error, "Error copying template #{templatename} to definition #{@name}:\n#{ex}" 78 | end 79 | 80 | end 81 | 82 | def save_mccloud_rb 83 | begin 84 | unless File.exists?(self.definition_path) 85 | File.open(self.definition_path,'w'){ |f| f.write(self.to_template(@name))} 86 | else 87 | raise ::Mccloud::Error, "Definition file #{self.definition_path} already exists" 88 | end 89 | rescue Error => ex 90 | raise ::Mccloud::Error, "Error writing mccloud.rb" 91 | end 92 | end 93 | 94 | def to_template(templatename) 95 | result="" 96 | t=@env.config.templates[templatename] 97 | filename=File.join(self.path,'mccloud.erb') 98 | env.logger.info "Opening vm template file #{@file}" 99 | template=File.new(filename).read 100 | result=ERB.new(template).result(binding) 101 | return result 102 | end 103 | end 104 | end 105 | -------------------------------------------------------------------------------- /lib/mccloud/definitions.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/definition.rb' 2 | 3 | module Mccloud 4 | class Definitions < Hash 5 | 6 | attr_reader :env 7 | 8 | def initialize(env) 9 | @env=env 10 | end 11 | 12 | def define(name,templatename) 13 | # Check if template exists 14 | unless env.config.templates.registered?(templatename) 15 | raise ::Mccloud::Error, "Template #{templatename} does not exist" 16 | end 17 | # Create the definitions dir if needed 18 | unless self.exists? 19 | self.create 20 | end 21 | 22 | definition=::Mccloud::Definition.new(name,env) 23 | unless definition.exists? 24 | definition.copy_template(templatename) 25 | end 26 | end 27 | 28 | def load! 29 | if self.exists? 30 | Dir[File.join(self.path,"**")].each do |dir| 31 | definition_name=File.basename(dir) 32 | d=Definition.new(definition_name,env) 33 | if d.valid? 34 | d.load! 35 | else 36 | env.logger.info "Skipping loading of definitions #{dir}" 37 | end 38 | end 39 | else 40 | env.logger.info "Skipping loading of definitions as the definition_path does exist" 41 | end 42 | end 43 | 44 | def path 45 | @env.config.mccloud.definition_path 46 | end 47 | 48 | def exists? 49 | File.directory?(self.path) 50 | end 51 | 52 | def registered?(name) 53 | return self.has_key?(name) 54 | end 55 | 56 | def create 57 | begin 58 | unless self.exists? 59 | env.logger.info "Creating the definitions directory #{self.path} as it doesn't exist yet" 60 | FileUtils.mkdir(self.path) 61 | end 62 | rescue Exception => ex 63 | raise ::Mccloud::Error, "Error creating definitions directory #{self.path}: \n#{ex}" 64 | end 65 | end 66 | 67 | end 68 | end 69 | 70 | ## Checking for name already defined 71 | # env.ui.warn "#{name} was already defined" unless env.config.vms[name].nil? 72 | # t=env.config.templates[template] 73 | # 74 | # # Template was not found 75 | # unless t.nil? 76 | # unless File.exists?("vms") && File.directory?("vms") 77 | #>> env.logger.info ("Creating the vms directory as it doesn't exist yet") 78 | # FileUtils.mkdir("vms") 79 | # end 80 | # filename=File.join("vms","#{name}.rb") 81 | # unless File.exists?(filename) 82 | # File.open(filename,'w'){ |f| f.write(t.to_template(name))} 83 | # else 84 | # env.ui.error "Definition #{name} already exists. Undefine it first:" 85 | # env.ui.error "mccloud undefine '#{name}'" 86 | # 87 | # end 88 | # else 89 | # env.ui.error "Template #{template} does not exist" 90 | # end 91 | # 92 | -------------------------------------------------------------------------------- /lib/mccloud/error.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | class Error < StandardError 3 | attr_reader :orginal 4 | def initialize(msg, original=$!) 5 | super(msg) 6 | @original = original; end 7 | end 8 | end 9 | 10 | #Usage (from the exceptional ruby book) 11 | #begin 12 | # begin 13 | # raise "Error A" 14 | # rescue => error 15 | # raise MyError, "Error B" 16 | # end 17 | #rescue => error. 18 | # puts "Current failure: #{error.inspect}" 19 | # puts "Original failure: #{error.original.inspect}" 20 | #end 21 | -------------------------------------------------------------------------------- /lib/mccloud/generator.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/mccloudfile' 2 | require 'mccloud/keypair' 3 | 4 | module Mccloud 5 | 6 | # This takes care of initializing a new Mccloud project 7 | class Generator 8 | 9 | attr_accessor :env 10 | 11 | def initialize(env) 12 | @env=env 13 | @generators=[:aws,:kvm,:host] 14 | end 15 | 16 | def generate(options={}) 17 | defaults={ :provider => :aws, :force => false} 18 | options=defaults.merge(options) 19 | provider=options[:provider].to_sym 20 | raise ::Mccloud::Error, "Unsupported provider #{provider}" unless @generators.include?(provider) 21 | generate_mccloudfile(options) 22 | generate_mccloud_sshkey(options) 23 | end 24 | 25 | def generate_mccloudfile(options) 26 | begin 27 | f=Mccloud::Mccloudfile.new(File.join(env.root_path,"Mccloudfile")) 28 | if f.exists? 29 | env.ui.error "Mccloudfile already exists" 30 | else 31 | env.ui.info "Creating a new Mccloudfile" 32 | f.generate(options) 33 | end 34 | rescue Error => ex 35 | raise ::Mccloud::Error, "Error creating Mccloudfile.\n#{ex}" 36 | end 37 | end 38 | 39 | def generate_mccloud_sshkey(options) 40 | k=Mccloud::Keypair.new("mccloud",env) 41 | if k.exists? 42 | env.ui.info "Re-using existing mccloud RSA key in #{k.public_key_path}" 43 | else 44 | k.generate(options) 45 | end 46 | end 47 | 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/mccloud/keypair.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/sshkey' 2 | 3 | module Mccloud 4 | class Keypair 5 | attr_accessor :public_key_path 6 | attr_accessor :private_key_path 7 | attr_accessor :name 8 | attr_accessor :env 9 | 10 | def initialize(name,env) 11 | @name=name 12 | @env=env 13 | @private_key_path=File.join(env.ssh_key_path,"#{name}_rsa") 14 | @public_key_path=File.join(env.ssh_key_path,"#{name}_rsa.pub") 15 | return self 16 | end 17 | 18 | def exists? 19 | return false unless File.exists?(@public_key_path) 20 | return false unless File.exists?(@private_key_path) 21 | return true 22 | end 23 | 24 | def generate(options={:force => false}) 25 | force=options[:force] 26 | if exists? && force==false 27 | env.ui.error "Keypair: #{@name} already exists" 28 | env.ui.error "- #{@public_key_path}" 29 | env.ui.error "- #{@private_key_path}" 30 | raise ::Mccloud::Error, "Keypair #{@name} already exists" 31 | else 32 | env.ui.info "Generating Keypair: #{@name}" 33 | env.ui.info "- #{@public_key_path}" 34 | env.ui.info "- #{@private_key_path}" 35 | env.ui.info "" 36 | env.ui.warn "Make sure you make a backup!!" 37 | rsa_key=::Mccloud::Util::SSHKey.generate({ :comment => "Key generated by mccloud #{@name}"}) 38 | begin 39 | File.open(@public_key_path,'w'){|f| f.write(rsa_key.ssh_public_key)} 40 | File.open(@private_key_path,'w'){|f| f.write(rsa_key.rsa_private_key)} 41 | rescue Exception => ex 42 | env.ui.error "Error generating keypair : #{ex}" 43 | end 44 | end 45 | end 46 | 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/mccloud/mccloudfile.rb: -------------------------------------------------------------------------------- 1 | require 'erb' 2 | module Mccloud 3 | class Mccloudfile 4 | 5 | attr_accessor :path 6 | attr_accessor :sections 7 | 8 | def initialize(path) 9 | # Path to the file 10 | @path=path 11 | 12 | end 13 | 14 | def exists? 15 | return File.exists?(@path) 16 | end 17 | 18 | # Bindings in ERB http://www.stuartellis.eu/articles/erb/ 19 | # Links: 20 | # * Trimming whitespace in ERB 21 | # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/242656 22 | # * Appending to ERB output 23 | # http://blog.jayfields.com/2007/01/appending-to-erb-output-from-block.html 24 | def uncomment(selection) 25 | 26 | cur_pos=@output.length 27 | yield 28 | new_pos=@output.length 29 | 30 | if exclude_section?(selection) 31 | # Extract the block 32 | block_text=@output[cur_pos..new_pos] 33 | 34 | # Remove the block 35 | @output[cur_pos..new_pos]='' 36 | 37 | # Comment the block, with leading spaces into account 38 | block_text.gsub!(/^(\s)*/,'\1# ') 39 | 40 | # Re-insert the block 41 | @output=@output.insert cur_pos, block_text 42 | end 43 | end 44 | 45 | def exclude_section?(section) 46 | section.each do |s| 47 | return false if @sections.include?(s) 48 | end 49 | return true 50 | end 51 | 52 | def generate(options={:force => false}) 53 | force=options[:force] 54 | provider=options[:provider] 55 | raise Mccloud::Error, "You need to specify a provider to generate a Mccloudfile" if provider.nil? 56 | 57 | @sections=[provider.to_sym] 58 | # We need at least one provider 59 | 60 | if exists? && force==false 61 | raise Mccloud::Error, "Error Mccloudfile already exists." 62 | else 63 | begin 64 | File.open(@path,'w'){ |f| f.write(self.to_s)} 65 | rescue Exception => ex 66 | raise Mccloud::Error, "Error saving Mccloudfile: #{ex}" 67 | end 68 | end 69 | end 70 | 71 | def to_s 72 | template=File.new(File.join(File.dirname(__FILE__),"templates","Mccloudfile.erb")).read 73 | result=::ERB.new(template,nil,"-","@output").result(binding) 74 | return result 75 | end 76 | 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/image.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | 4 | class Image 5 | attr_accessor :provider 6 | attr_accessor :name 7 | 8 | def raw 9 | end 10 | 11 | def package(selection=nil,options=nil) 12 | 13 | if selection.nil? 14 | env.ui.info "[Error] We need at least a name of a machine." 15 | exit 16 | end 17 | 18 | 19 | #f=Fog::Compute.new({ :region => "eu-west-1", :provider => "AWS"}) 20 | # i=f.create_image("i-c1ac2bb7","name","description") 21 | # f.images.all({ "Owner" => "self"}) 22 | # f.deregister_image("ami-796d5b0d") 23 | 24 | on_selected_machines(selection) do |id,vm| 25 | 26 | time=Time.new 27 | strtime=time.strftime("%Y-%m-%d-%H-%M-%S") 28 | name="" 29 | 30 | if options["name"].nil? 31 | name="#{vm.name}-#{strtime}" 32 | else 33 | name=options["name"] 34 | end 35 | 36 | description="" 37 | if options["description"].nil? 38 | description="Autogenerated snapshot from machine #{vm.name}" 39 | else 40 | description=options["description"] 41 | end 42 | 43 | filter=@environment.config.mccloud.filter 44 | fullname="#{@environment.config.mccloud.filter}#{name}" 45 | 46 | provider= @environment.config.providers[vm.provider] 47 | begin 48 | result=provider.create_image(id,name,description) 49 | imageId=result.body["imageId"] 50 | env.ui.info "[#{vm.name}] image #{imageId} with #{description} being created" 51 | 52 | unless options["dontwait"] 53 | sleep 3 54 | counter=0 55 | max_tries=5 56 | #Pending 57 | state="pending" 58 | until state!="pending" do 59 | print "." 60 | sleep 2 61 | image=provider.images.get(imageId) 62 | 63 | if image.nil? 64 | sleep 3 65 | print "." 66 | else 67 | state=image.state 68 | end 69 | end 70 | env.ui.info "" 71 | env.ui.info "[#{vm.name}] creation done!" 72 | end 73 | rescue Fog::Service::Error => fogerror 74 | env.ui.info "[Error] #{fogerror}" 75 | 76 | end 77 | # vm.instance.start 78 | end 79 | end 80 | 81 | def register 82 | #f=Fog::Compute.new({ :region => "eu-west-1", :provider => "AWS"}) 83 | # i=f.create_image("i-c1ac2bb7","name","description") 84 | # f.images.all({ "Owner" => "self"}) 85 | # f.deregister_image("ami-796d5b0d") 86 | 87 | env.ui.info "Looking for imageId: #{imageId}" 88 | @environment.config.providers.each do |name,provider| 89 | begin 90 | image=provider.images.get(imageId) 91 | if image.nil? 92 | env.ui.info "[#{name}] - ImageId #{imageId} not found" 93 | else 94 | env.ui.info "[#{name}] - ImageId #{imageId} found" 95 | env.ui.info "[#{name}] - Deregistering #{imageId} now" 96 | begin 97 | provider.deregister_image(imageId) 98 | rescue Fog::Service::Error => fogerror 99 | env.ui.info "[Error] #{fogerror}" 100 | end 101 | end 102 | end 103 | end 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/ip.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/ip' 2 | require 'mccloud/provider/aws/ip/associate' 3 | 4 | module Mccloud::Provider 5 | module Aws 6 | 7 | class Ip < ::Mccloud::Provider::Core::Ip 8 | 9 | #Inherits :name 10 | # :provider 11 | attr_accessor :vmname 12 | attr_accessor :address 13 | 14 | include Mccloud::Provider::Aws::IpCommand 15 | 16 | def initialize(env) 17 | super(env) 18 | end 19 | 20 | def raw 21 | if @raw.nil? 22 | rawname="#{@provider.filter}#{@name}" 23 | @raw=@provider.raw.addresses.all('public-ip' => self.address).first 24 | env.logger.info("IP found #{@raw.server_id} #{@raw.public_ip}") 25 | end 26 | return @raw 27 | end 28 | 29 | end #Class 30 | end #module Type 31 | end #Module Mccloud 32 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/ip/associate.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module IpCommand 4 | 5 | def associate(options) 6 | unless raw.nil? 7 | env.ui.info "[#{@name}] Attempting to associate ip #{@name} with vm name #{@vmname}" 8 | vm=env.config.vms[@vmname] 9 | if vm.nil? 10 | env.ui.error "[#{@name}] vm #{@vmname} is not defined" 11 | return 12 | else 13 | if vm.id.nil? 14 | env.ui.error "[#{@name}] vm #{@vmname} is not yet instantiated" 15 | return 16 | else 17 | env.ui.info "[#{@name}] The ipaddress currently has server_id #{raw.server_id} associated" unless raw.server_id.nil? 18 | if raw.server_id==vm.id 19 | env.ui.info "[#{@name}] #{@address} is already associated with #{@vmname} #{vm.id}" 20 | else 21 | env.ui.info "[#{@name}] Associating #{@address} with #{@vmname} #{vm.id}" 22 | raw.server=vm.raw 23 | end 24 | end 25 | end 26 | else 27 | env.ui.error "[#{ip.name}] Ipaddress does not (yet) exist" 28 | end 29 | end 30 | 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/keystore.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/keystore' 2 | 3 | module Mccloud::Provider 4 | module Aws 5 | 6 | class Keystore < ::Mccloud::Provider::Core::Keystore 7 | 8 | #Inherits 9 | #attr_accesor :name,:provider 10 | attr_accessor :keypairs 11 | 12 | # include Mccloud::Provider::Aws::KeystoreCommand 13 | 14 | def initialize(env) 15 | super(env) 16 | @keypairs=Array.new 17 | end 18 | 19 | end #Class 20 | end #module Type 21 | end #Module Mccloud 22 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/lb.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/lb' 2 | require 'mccloud/provider/aws/lb/associate' 3 | require 'mccloud/provider/aws/lb/sorry' 4 | 5 | module Mccloud::Provider 6 | module Aws 7 | 8 | class Lb < ::Mccloud::Provider::Core::Lb 9 | 10 | #Inherits :name 11 | # :provider 12 | attr_accessor :members 13 | attr_accessor :sorry_members 14 | 15 | include Mccloud::Provider::Aws::LbCommand 16 | 17 | def initialize(env) 18 | members=Array.new 19 | sorry_members=Array.new 20 | super(env) 21 | end 22 | 23 | def raw 24 | if @raw.nil? 25 | rawname="#{@name}" 26 | #rawname="#{@provider.filter}#{@name}" 27 | ::Fog.credential=@provider.credential 28 | @raw=::Fog::AWS::ELB.new({:region => provider.region}.merge(provider.options)).load_balancers.get(@name) 29 | env.logger.info("LB found #{@raw}") 30 | end 31 | return @raw 32 | end 33 | 34 | end 35 | 36 | end 37 | end #Module Mccloud 38 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/lb/associate.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module LbCommand 4 | 5 | def associate(options) 6 | balance(@members,options) 7 | end 8 | 9 | def balance(members,options) 10 | unless raw.nil? 11 | current_members=raw.instances 12 | cleanup_members=current_members 13 | members.each do |member_id| 14 | env.logger.info "Attempting to associate #{@name} with vm name #{member_id}" 15 | vm=env.config.vms[member_id] 16 | if vm.nil? 17 | env.ui.error "vm #{member_id} is not defined" 18 | else 19 | if vm.id.nil? 20 | env.ui.error "vm #{member_id} is not yet instantiated" 21 | else 22 | env.logger.info "The loadbalancer currently has members #{current_members.join(",")} associated" unless raw.instances.nil? 23 | 24 | # First add new members 25 | if current_members.include?(vm.id) 26 | cleanup_members=cleanup_members - [ vm.id ] 27 | env.ui.info "[#{@name}] Skipping associate #{vm.name} - #{vm.id} as it already is a member" 28 | else 29 | env.ui.info "[#{@name}] Associating #{vm.name} - #{vm.id}" 30 | raw.register_instances(vm.id) 31 | end 32 | 33 | end 34 | end 35 | end 36 | 37 | # And now remove old members 38 | #unless member_ids.include?(instance_id) 39 | #lb_instance=lb.instance 40 | require 'pp' 41 | cleanup_members.each do |member_id| 42 | env.ui.info "Cleanup of old member #{member_id}" 43 | raw.deregister_instances(member_id) 44 | end 45 | 46 | else 47 | env.ui.error "[#{@name}] Loadbalancer does not (yet) exist" 48 | end 49 | end 50 | 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/lb/sorry.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/aws/lb/associate' 2 | 3 | module Mccloud::Provider 4 | module Aws 5 | module LbCommand 6 | 7 | def sorry(options) 8 | balance(@sorry_members,options) 9 | end 10 | 11 | end 12 | end 13 | end 14 | 15 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/image_destroy.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Aws 4 | module ProviderCommand 5 | 6 | def image_destroy(imageId,options=nil) 7 | begin 8 | image=raw.images.get(imageId) 9 | if image.nil? 10 | env.ui.info "[#{name}] - ImageId #{imageId} not found" 11 | else 12 | env.ui.info "[#{name}] - ImageId #{imageId} found" 13 | env.ui.info "[#{name}] - Deregistering #{imageId} now" 14 | begin 15 | raw.deregister_image(imageId) 16 | rescue Fog::Service::Error => fogerror 17 | env.ui.error "[Error] #{fogerror}" 18 | end 19 | end 20 | end 21 | end 22 | 23 | end 24 | end 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/image_list.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Aws 4 | module ProviderCommand 5 | 6 | def image_list(selection=nil,options=nil) 7 | images=raw.images.all({"Owner" => "self"}) 8 | env.logger.info("#{selection} - #{options}") 9 | images.each do |image| 10 | require 'pp' 11 | env.ui.info "Id: #{image.id} Name: #{image.name}, Description: #{image.description}" 12 | end 13 | end 14 | 15 | end 16 | end 17 | end 18 | 19 | end 20 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/ip_list.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Aws 4 | module ProviderCommand 5 | 6 | def ip_list(selection=nil,options=nil) 7 | env.logger.info("#{selection} - #{options}") 8 | raw.addresses.each do |address| 9 | env.ui.info "Ip-address #{address.public_ip} - Server-Id #{address.server_id}" 10 | end 11 | end 12 | 13 | end 14 | end 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/keystore_list.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Aws 4 | module ProviderCommand 5 | 6 | def keystore_list(selection=nil,options=nil) 7 | 8 | if raw.key_pairs.empty? 9 | env.ui.info("No Keypairs found") 10 | else 11 | raw.key_pairs.each do |keypair| 12 | env.ui.info "KeyPair #{keypair.name} - #{keypair.fingerprint}" 13 | end 14 | end 15 | 16 | end 17 | 18 | end 19 | end 20 | end 21 | 22 | end 23 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/keystore_sync.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/sshkey' 2 | 3 | module Mccloud 4 | module Provider 5 | module Aws 6 | module ProviderCommand 7 | 8 | def keystore_sync(selection=nil,options=nil) 9 | 10 | env.config.keystores.each do |name,store| 11 | if store.keypairs.empty? 12 | env.ui.info "No Keypairs specified for keystore '#{name}'" 13 | else 14 | 15 | selected_keypairs=store.keypairs 16 | 17 | selected_keypairs.each do |defined_pair| 18 | keypair=env.config.keypairs[defined_pair[:keypair]] 19 | remote_name=defined_pair[:name] 20 | if keypair.nil? 21 | env.ui.error "Keypair #{defined_pair[:keypair]} is not defined" 22 | else 23 | name=keypair.name 24 | begin 25 | # Read key file 26 | key=File.read(keypair.public_key_path) 27 | 28 | # Check if key already exists 29 | existing_key=raw.key_pairs.get(remote_name) 30 | if existing_key.nil? 31 | # It does not exist, just create it 32 | env.ui.info "Creating Remote Key #{remote_name}" 33 | raw.key_pairs.create(:name => remote_name, :public_key => key) 34 | else 35 | if options.has_key?("overwrite") 36 | # Exists but overwrite was specified 37 | env.ui.info "Remote key '#{remote_name}' exists but --overwrite specified, removing key first" 38 | existing_key.destroy 39 | env.ui.info "Creating Remote Key #{remote_name}" 40 | raw.key_pairs.create(:name => defined_pair[:name], :public_key => key) 41 | else 42 | # Exists but overwrite was NOT specified 43 | env.ui.info "Remote Key '#{remote_name}' already exists. Use 'mccloud sync --overwrite'" 44 | end 45 | end 46 | rescue Errno::ENOENT => ex 47 | env.ui.error "Error: public_key_path does not exist : #{keypair.public_key_path}" 48 | rescue Error => ex 49 | env.ui.error "Error uploading key : #{ex}" 50 | end 51 | end 52 | end 53 | end 54 | 55 | end 56 | end 57 | 58 | end 59 | end 60 | end 61 | 62 | end 63 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/lb_list.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Aws 4 | module ProviderCommand 5 | 6 | def lb_list(selection=nil,options=nil) 7 | env.logger.info("#{selection} - #{options}") 8 | 9 | env.logger.info("Looking for loadbalancers in region #{@region}") 10 | ::Fog.credential = @credential 11 | elb=::Fog::AWS::ELB.new({:region => @region}.merge(@options)) 12 | elb.load_balancers.each do |lb| 13 | env.ui.info "Id #{lb.id} - DNS #{lb.dns_name} - Zones: #{lb.availability_zones.join(',')} - Instances #{lb.instances.join(',')} " 14 | end 15 | end 16 | 17 | end 18 | end 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_deregister.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | def deregister(imageId=nil,options=nil) 6 | 7 | if imageId.nil? 8 | puts "[Error] We need at least need an imageId." 9 | exit 10 | end 11 | 12 | 13 | #f=Fog::Compute.new({ :region => "eu-west-1", :provider => "AWS"}) 14 | # i=f.create_image("i-c1ac2bb7","name","description") 15 | # f.images.all({ "Owner" => "self"}) 16 | # f.deregister_image("ami-796d5b0d") 17 | 18 | puts "Looking for imageId: #{imageId}" 19 | @environment.config.providers.each do |name,provider| 20 | begin 21 | image=provider.images.get(imageId) 22 | if image.nil? 23 | puts "[#{name}] - ImageId #{imageId} not found" 24 | else 25 | puts "[#{name}] - ImageId #{imageId} found" 26 | puts "[#{name}] - Deregistering #{imageId} now" 27 | begin 28 | provider.deregister_image(imageId) 29 | rescue Fog::Service::Error => fogerror 30 | puts "[Error] #{fogerror}" 31 | end 32 | end 33 | end 34 | end 35 | 36 | 37 | end #def 38 | end #module 39 | end #module 40 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_flavors.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | def flavors() 4 | puts "" 5 | puts "Available flavors" 6 | provider=@provider.config.providers.first[1] 7 | flavors=provider.flavors 8 | formatting="%-12s %-35s %-6s %-6s %-6s %-6s\n" 9 | printf formatting,"id","name","bits","cores","disk", "ram" 10 | 80.times { |i| printf "=" } ; puts 11 | 12 | flavors.each do |flavor| 13 | printf formatting,flavor.id,flavor.name[0..34],flavor.bits,flavor.cores,flavor.disk, flavor.ram 14 | end 15 | 16 | end #def 17 | end #module 18 | end 19 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_ips.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | include Mccloud::Util 6 | 7 | def ips(selection, options) 8 | filter=@environment.config.mccloud.stackfilter 9 | 10 | on_selected_ips(selection) do |id,ip| 11 | ip_instance=ip.instance 12 | unless ip_instance.nil? 13 | vm=@environment.config.vms[ip.vmname] 14 | puts "[#{ip.name}] Associating #{ip.address} with #{ip.vmname}" 15 | ip_instance.server=vm.instance 16 | else 17 | puts "[#{ip.name}] Ipaddress does not (yet) exist" 18 | end 19 | # ipaddress=ip.instance 20 | 21 | # .each do |member| 22 | # vm=@environment.config.vms[member] 23 | # server_instance=vm.instance 24 | # unless server_instance.nil? 25 | # lb_instance=lb.instance 26 | # unless lb_instance.nil? 27 | # puts "[#{lb.name}] Registering #{vm.name} - #{server_instance.id} with loadbalancer " 28 | # lb_instance.register_instances(server_instance.id) 29 | # else 30 | # puts "[#{lb.name} Loadbalancer does not (yet) exist" 31 | # end 32 | # else 33 | # puts "[#{lb.name}] Member #{member} is not yet created. " 34 | # end 35 | # end 36 | # end 37 | 38 | end 39 | end 40 | 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_loadbalance.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | include Mccloud::Util 6 | 7 | def loadbalance(selection, options) 8 | filter=@environment.config.mccloud.stackfilter 9 | 10 | puts 11 | on_selected_lbs(selection) do |id,lb| 12 | 13 | member_ids=Array.new 14 | lb_instance=lb.instance 15 | #Adding new member first 16 | lb.members.each do |member| 17 | vm=@environment.config.vms[member] 18 | server_instance=vm.instance 19 | unless server_instance.nil? 20 | unless lb_instance.nil? 21 | puts "[#{lb.name}] Registering #{vm.name} - #{server_instance.id} with loadbalancer " 22 | lb_instance.register_instances(server_instance.id) 23 | member_ids << server_instance.id 24 | else 25 | puts "[#{lb.name} Loadbalancer does not (yet) exist" 26 | end 27 | else 28 | puts "[#{lb.name}] Member #{member} is not yet created. " 29 | end 30 | end 31 | 32 | #Removing old members 33 | lb_instance.instances.each do |instance_id| 34 | unless member_ids.include?(instance_id) 35 | lb_instance=lb.instance 36 | lb_instance.deregister_instances(instance_id) 37 | puts "[#{lb.name}] De-registering member #{instance_id} with loadbalancer " 38 | 39 | end 40 | end 41 | end 42 | 43 | end 44 | 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_package.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | def package(selection=nil,options=nil) 6 | 7 | if selection.nil? 8 | puts "[Error] We need at least a name of a machine." 9 | exit 10 | end 11 | 12 | 13 | #f=Fog::Compute.new({ :region => "eu-west-1", :provider => "AWS"}) 14 | # i=f.create_image("i-c1ac2bb7","name","description") 15 | # f.images.all({ "Owner" => "self"}) 16 | # f.deregister_image("ami-796d5b0d") 17 | 18 | on_selected_machines(selection) do |id,vm| 19 | 20 | time=Time.new 21 | strtime=time.strftime("%Y-%m-%d-%H-%M-%S") 22 | name="" 23 | 24 | if options["name"].nil? 25 | name="#{vm.name}-#{strtime}" 26 | else 27 | name=options["name"] 28 | end 29 | 30 | description="" 31 | if options["description"].nil? 32 | description="Autogenerated snapshot from machine #{vm.name}" 33 | else 34 | description=options["description"] 35 | end 36 | 37 | filter=@environment.config.mccloud.filter 38 | fullname="#{@environment.config.mccloud.filter}#{name}" 39 | 40 | provider= @environment.config.providers[vm.provider] 41 | begin 42 | result=provider.create_image(id,name,description) 43 | imageId=result.body["imageId"] 44 | puts "[#{vm.name}] image #{imageId} with #{description} being created" 45 | 46 | unless options["dontwait"] 47 | sleep 3 48 | counter=0 49 | max_tries=5 50 | #Pending 51 | state="pending" 52 | until state!="pending" do 53 | print "." 54 | sleep 2 55 | image=provider.images.get(imageId) 56 | 57 | if image.nil? 58 | sleep 3 59 | print "." 60 | else 61 | state=image.state 62 | end 63 | end 64 | puts "" 65 | puts "[#{vm.name}] creation done!" 66 | end 67 | rescue Fog::Service::Error => fogerror 68 | puts "[Error] #{fogerror}" 69 | 70 | end 71 | # vm.instance.start 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_sorry.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | include Mccloud::Util 6 | 7 | def sorry(selection, options) 8 | filter=@environment.config.mccloud.stackfilter 9 | 10 | puts 11 | on_selected_lbs(selection) do |id,lb| 12 | 13 | if lb.sorry_members.nil? 14 | puts "[#{lb.name}] has no sorry_members defined, skipping" 15 | else 16 | member_ids=Array.new 17 | lb_instance=lb.instance 18 | #Adding new member first 19 | lb.sorry_members.each do |member| 20 | vm=@environment.config.vms[member] 21 | server_instance=vm.instance 22 | unless server_instance.nil? 23 | unless lb_instance.nil? 24 | puts "[#{lb.name}] Registering #{vm.name} - #{server_instance.id} with loadbalancer " 25 | lb_instance.register_instances(server_instance.id) 26 | member_ids << server_instance.id 27 | else 28 | puts "[#{lb.name} Loadbalancer does not (yet) exist" 29 | end 30 | else 31 | puts "[#{lb.name}] Member #{member} is not yet created. " 32 | end 33 | end 34 | 35 | #Removing old members 36 | lb_instance.instances.each do |instance_id| 37 | unless member_ids.include?(instance_id) 38 | lb_instance=lb.instance 39 | lb_instance.deregister_instances(instance_id) 40 | puts "[#{lb.name}] De-registering member #{instance_id} with loadbalancer " 41 | 42 | end 43 | end 44 | end 45 | 46 | end 47 | 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/old_validate.rb: -------------------------------------------------------------------------------- 1 | if Mccloud.environment.config.mccloud.check_keypairs 2 | puts "Checking keypair(s)" 3 | #checking keypairs 4 | Mccloud.environment.config.stacks.each do |name,stack| 5 | stack.key_name.each do |name,key_name| 6 | 7 | stack_provider=@environment.config.providers["#{stack.provider+"-"+stack.provider_options[:region].to_s}"] 8 | pair=stack_provider.key_pairs.get("#{key_name}") 9 | if pair.nil? 10 | puts "#{key_name} does not exist at #{stack.provider} in region #{stack.provider_options[:region]}" 11 | puts "Key - #{key_name}" 12 | puts "File - #{stack.public_key[name]}" 13 | #reading private key 14 | public_key="" 15 | File.open("#{stack.public_key[name]}") {|f| public_key << f.read} 16 | 17 | stack_provider.key_pairs.create( 18 | :name => key_name, 19 | :public_key => public_key ) 20 | end 21 | end 22 | end 23 | 24 | 25 | @environment.config.vms.each do |name,vm| 26 | vm_provider=@environment.config.providers["#{vm.provider+"-"+vm.provider_options[:region].to_s}"] 27 | pair=vm_provider.key_pairs.get("#{vm.key_name}") 28 | if pair.nil? 29 | puts "Key - #{vm.key_name}" 30 | puts "#{key_name} does not exist at #{vm.provider} in region #{vm.provider_options[:region]}" 31 | end 32 | end 33 | end 34 | if Mccloud.environment.config.mccloud.check_securitygroups 35 | puts "Checking security group(s)" 36 | @environment.config.vms.each do |name,vm| 37 | vm_provider=@environment.config.providers["#{vm.provider+"-"+vm.provider_options[:region].to_s}"] 38 | 39 | mcgroup=vm_provider.security_groups.get("#{vm.create_options[:groups].first}") 40 | if mcgroup.nil? 41 | "#{vm.create_options[:groups].first} does not exist at region #{vm.provider_options[:region].to_s}" 42 | sg=vm_provider.security_groups.new 43 | sg.name="#{vm.create_options[:groups].first}" 44 | sg.description="#{vm.create_options[:groups].first}" 45 | sg.save 46 | 47 | puts "Authorizing access to port 22" 48 | sg.authorize_port_range(22..22) 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | env.ui.info "" 8 | env.ui.info "Server(s) - provider #{@name}" 9 | 10 | printf "%-10s %-12s %-20s %-15s %-8s\n", "Name", "Instance Id", "IP", "Type","Status" 11 | 80.times { |i| printf "=" } ; env.ui.info "" 12 | 13 | # List servers 14 | raw.servers.each do |vm| 15 | name="" 16 | if !vm.tags["Name"].nil? 17 | name=vm.tags["Name"].strip 18 | end #end if 19 | 20 | if name.start_with?(self.filter) 21 | unless self.filter=="" 22 | name[self.filter]="" 23 | printf "%-10s %-12s %-20s %-20s %-15s %-8s\n",name,vm.id, vm.public_ip_address, vm.private_ip_address,vm.flavor_id,vm.state 24 | else 25 | env.ui.info "Name: #{name}" 26 | env.ui.info "Instance Id: #{vm.id}" 27 | env.ui.info "Public Ip: #{vm.public_ip_address}" 28 | env.ui.info "Flavor: #{vm.flavor.name}" 29 | env.ui.info "State: #{vm.state}" 30 | 80.times { |i| printf "=" } ; env.ui.info "" 31 | end 32 | end 33 | end #End 1 provider 34 | 35 | # List images 36 | env.ui.info "" 37 | env.ui.info "Image(s) - provider #{@name}" 38 | 80.times { |i| printf "=" } ; env.ui.info "" 39 | images_list=raw.images.all({"Owner" => "self"}) 40 | images_list.each do |image| 41 | printf "%-10s %-10s %-10s %-20s\n",image.id,image.name.gsub(/"#{filter}"/,''),image.state, image.description.to_s[0..20] 42 | end 43 | 44 | # List volumes 45 | env.ui.info "" 46 | env.ui.info "Volume(s) - provider #{@name}" 47 | 80.times { |i| printf "=" } ; env.ui.info "" 48 | volume_list=raw.volumes.all() 49 | volume_list.each do |volume| 50 | printf "%-10s %-10s %-10s %-20s\n",volume.id,volume.device,volume.server_id, volume.size 51 | end 52 | env.ui.info "" 53 | 54 | end 55 | 56 | end #module 57 | end #module 58 | end #module 59 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/stack/old_destroy.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/iterator' 2 | 3 | module Mccloud 4 | module Command 5 | def destroy(selection=nil,options=nil) 6 | 7 | on_selected_stacks(selection) do |id,stack| 8 | stackfilter=@environment.config.mccloud.stackfilter 9 | stack_fullname="#{stackfilter}#{stack.name}" 10 | 11 | stack_exists=false 12 | provider=@environment.config.providers[stack.provider] 13 | cf = Fog::AWS::CloudFormation.new(stack.provider_options) 14 | 15 | begin 16 | cf.get_template("#{stack_fullname}") 17 | stack_exists=true 18 | rescue Exception => e 19 | #puts "[#{stack.name}] - Error\n #{e}" 20 | end 21 | 22 | if stack_exists 23 | begin 24 | puts "[#{stack.name}] - Deleting stack" 25 | cf.delete_stack(stack_fullname) 26 | events=cf.describe_stack_events(stack_fullname).body 27 | sorted_events=events['StackEvents'] 28 | sorted_events.reverse.each do |event| 29 | printf " %-25s %-30s %-30s %-20s %-15s\n", event['Timestamp'],event['ResourceType'],event['LogicalResourceId'], event['ResourceStatus'],event['ResourceStatusReason'] 30 | end 31 | rescue Excon::Errors::BadRequest => e 32 | puts "[#{stack.name}] - Error deleting the stacks:\n #{e.response.body}" 33 | end 34 | else 35 | puts "[#{stack.name}] - Stack does not exist" 36 | end 37 | 38 | 39 | end 40 | 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/stack/old_up.rb: -------------------------------------------------------------------------------- 1 | filter=@environment.config.mccloud.stackfilter 2 | 3 | # http://allanfeid.com/content/using-amazons-cloudformation-cloud-init-chef-and-fog-automate-infrastructure 4 | on_selected_stacks(selection) do |id,stack| 5 | stack_fullname="#{filter}#{stack.name}" 6 | stack_params=stack.params 7 | template_body=stack.json_rewrite 8 | 9 | provider=@environment.config.providers[stack.provider] 10 | unless (stack.exists?) 11 | cf = Fog::AWS::CloudFormation.new(stack.provider_options) 12 | 13 | begin 14 | cf.validate_template({'TemplateBody' => template_body}) 15 | rescue Excon::Errors::BadRequest => e 16 | puts "[#{stack.name}] - Error validating template #{stack.jsonfile}:\n #{e.response.body}" 17 | end 18 | 19 | template_exists=false 20 | begin 21 | cf.get_template("#{stack_fullname}") 22 | template_exists=true 23 | rescue Excon::Errors::BadRequest => e 24 | # puts "[#{stack.name}] - Error getting the remote template:\n #{e.response.body}" 25 | end 26 | 27 | unless template_exists 28 | #DisableRollback, TemplateURL, TimeoutInMinutes 29 | begin 30 | cf.create_stack(stack_fullname, {'TemplateBody' => template_body, 'Parameters' => stack_params}) 31 | puts "[#{stack.name}] - Stack creation started" 32 | rescue Excon::Errors::BadRequest => e 33 | puts "[#{stack.name}] - Error creating the stack:\n #{e.response.body}" 34 | end 35 | 36 | begin 37 | events=cf.describe_stack_events(stack_fullname).body 38 | sorted_events=events['StackEvents'] 39 | sorted_events.reverse.each do |event| 40 | printf " %-25s %-30s %-30s %-20s %-15s\n", event['Timestamp'],event['ResourceType'],event['LogicalResourceId'], event['ResourceStatus'],event['ResourceStatusReason'] 41 | end 42 | rescue Excon::Errors::BadRequest => e 43 | puts "[#{stack.name}] - Error fetching stack events:\n #{e.response.body}" 44 | end 45 | 46 | else 47 | puts "[#{stack.name}] - Already exists" 48 | 49 | events=cf.describe_stack_events(stack_fullname).body 50 | sorted_events=events['StackEvents'] 51 | sorted_events.reverse.each do |event| 52 | printf " %-25s %-30s %-30s %-20s %-15s\n", event['Timestamp'],event['ResourceType'],event['LogicalResourceId'], event['ResourceStatus'],event['ResourceStatusReason'] 53 | end 54 | end 55 | 56 | end 57 | 58 | end 59 | 60 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/stack/old_vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | require 'mccloud/provider/aws/vm/up.rb' 4 | require 'mccloud/provider/aws/vm/bootstrap.rb' 5 | require 'mccloud/provider/aws/vm/ssh.rb' 6 | require 'mccloud/provider/aws/vm/scp.rb' 7 | require 'mccloud/provider/aws/vm/rsync.rb' 8 | ##require 'mccloud/provider/aws/command/vm/halt.rb' 9 | require 'mccloud/provider/aws/vm/provision.rb' 10 | require 'mccloud/provider/aws/vm/destroy.rb' 11 | 12 | 13 | module Mccloud::Provider 14 | module Aws 15 | 16 | 17 | class Vm < ::Mccloud::Provider::Core::Vm 18 | 19 | attr_accessor :ami 20 | attr_accessor :key_name 21 | 22 | # attr_accessor :server_id 23 | 24 | include Mccloud::Provider::Aws::VmCommand 25 | 26 | end 27 | end 28 | end 29 | 30 | 31 | 32 | #attr_accessor :instance,:vm,:provider 33 | 34 | #def initialize(vm,provider) 35 | # @vm=vm 36 | # @provider=provider 37 | # found=@provider.raw_provider.servers.all(:name => @vm.name) 38 | # unless found.nil? 39 | # @instance=found.first 40 | # @instance.private_key_path=@vm.private_key 41 | # @instance.username = @vm.user 42 | # end 43 | #end 44 | 45 | unless server.state=="terminated" 46 | 47 | full_name="#{server.tags['Name']}" 48 | if full_name.start_with?(filter) 49 | 50 | temp_name=String.new(full_name) 51 | temp_name[filter]="" 52 | short_name=temp_name 53 | 54 | # if the VM was not declared 55 | unless !@environment.config.vms[short_name].nil? 56 | #puts "#{short_name} - has been not been declared as a vm" 57 | undeclared_vm=Mccloud::Type::Vm.new 58 | undeclared_vm.declared=false 59 | undeclared_vm.server_id=server.id 60 | @environment.config.vms[short_name]=undeclared_vm 61 | else 62 | 63 | end 64 | 65 | # Set the server.id of the vm 66 | @environment.config.vms[short_name].server_id=server.id 67 | @environment.config.vms[short_name].provider=name 68 | 69 | # Check if the server is part of a stack 70 | stack_name=server.tags['aws:cloudformation:stack-name'] 71 | 72 | unless stack_name.nil? 73 | filtered_stack_name=stack_name 74 | filtered_stack_name[stack_filter]="" 75 | # Lookup stack on our config 76 | #puts "Note: #{short_name} is part of #{filtered_stack_name} " 77 | 78 | if @environment.config.stacks.has_key?(filtered_stack_name) 79 | # If we found it, set the private, public and user appropriatly 80 | 81 | #puts " [#{short_name}] Adjusting public and private keys for stack" 82 | @environment.config.vms[short_name].private_key=@environment.config.stacks[filtered_stack_name].private_key_for_instance(short_name) 83 | @environment.config.vms[short_name].public_key=@environment.config.stacks[filtered_stack_name].public_key_for_instance(short_name) 84 | @environment.config.vms[short_name].user=@environment.config.stacks[filtered_stack_name].user_for_instance(short_name) 85 | 86 | else 87 | puts "Stack #{filtered_stack_name} is not defined " 88 | 89 | end 90 | 91 | 92 | 93 | end 94 | 95 | 96 | end 97 | end 98 | 99 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | require 'mccloud/provider/aws/vm/up' 4 | require 'mccloud/provider/aws/vm/bootstrap' 5 | require 'mccloud/provider/aws/vm/ssh' 6 | require 'mccloud/provider/aws/vm/scp' 7 | require 'mccloud/provider/aws/vm/rsync' 8 | require 'mccloud/provider/aws/vm/halt' 9 | require 'mccloud/provider/aws/vm/provision' 10 | require 'mccloud/provider/aws/vm/destroy' 11 | require 'mccloud/provider/aws/vm/reload' 12 | require 'mccloud/provider/aws/vm/resume' 13 | require 'mccloud/provider/aws/vm/suspend' 14 | require 'mccloud/provider/aws/vm/forward' 15 | require 'mccloud/provider/aws/vm/package' 16 | 17 | module Mccloud::Provider 18 | module Aws 19 | 20 | class Vm < ::Mccloud::Provider::Core::Vm 21 | 22 | #Inherits user, name,port 23 | # private_key_path, public_key_path 24 | # bootstrap, auto_selection 25 | # forwardings 26 | # provider 27 | attr_accessor :ami 28 | attr_accessor :tags 29 | attr_accessor :key_name 30 | attr_accessor :zone 31 | attr_accessor :security_groups 32 | attr_accessor :user_data 33 | attr_accessor :flavor 34 | 35 | include Mccloud::Provider::Aws::VmCommand 36 | 37 | def initialize(env) 38 | # Todo calculate the best default based 39 | # On provider region 40 | super(env) 41 | @key_name = [ "mccloud"] 42 | # Todo calculate the best default based 43 | # On provider region 44 | @zone="eu-west-1a" 45 | @security_groups=[ "mccloud"] 46 | @flavor="t1.micro" 47 | # Todo calculate the ubuntu one based 48 | # on provider region and flavor 49 | @ami="ami-e59ca991" 50 | 51 | # Empty tags, but on up the name get's added 52 | @tags = {} 53 | 54 | @user = "root" 55 | @user_data = nil 56 | 57 | end 58 | 59 | def running? 60 | if raw.nil? 61 | return false 62 | else 63 | return raw.ready? 64 | end 65 | end 66 | 67 | def id 68 | unless raw.nil? 69 | return raw.id 70 | else 71 | return nil 72 | end 73 | end 74 | def ip_address 75 | # For VPC 76 | ip = self.public_ip_address 77 | return ip unless ip.nil? 78 | ip = self.private_ip_address 79 | return ip unless ip.nil? 80 | return nil 81 | end 82 | 83 | def public_ip_address 84 | unless raw.nil? 85 | ip=raw.public_ip_address 86 | else 87 | ip=nil 88 | end 89 | return ip 90 | end 91 | 92 | def private_ip_address 93 | unless raw.nil? 94 | ip=raw.private_ip_address 95 | else 96 | ip=nil 97 | end 98 | return ip 99 | end 100 | 101 | 102 | def raw 103 | if @raw.nil? 104 | rawname="#{@provider.filter}#{@name}" 105 | @provider.raw.servers.each do |vm| 106 | name=nil 107 | name=vm.tags["Name"].strip unless vm.tags["Name"].nil? 108 | if name==rawname 109 | @raw=vm 110 | 111 | # Add it to make scp work the first time 112 | @raw.private_key_path=@private_key_path 113 | @raw.username = @user 114 | end 115 | end 116 | else 117 | # Refresh this every time it is referenced 118 | @raw.private_key_path=@private_key_path 119 | @raw.username = @user 120 | end 121 | 122 | return @raw 123 | end 124 | 125 | end 126 | end 127 | end 128 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/bootstrap.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/platform' 2 | 3 | module Mccloud::Provider 4 | module Aws 5 | module VmCommand 6 | 7 | def _bootstrap(command,options=nil) 8 | ssh_bootstrap(command,options) 9 | end 10 | 11 | end #module 12 | end #Module 13 | end #module 14 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/destroy.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def destroy(options) 6 | 7 | unless raw.nil? || raw.state == "shutting-down" || raw.state =="terminated" 8 | env.ui.info "[#{@name}] - Destroying machine (#{raw.id})" 9 | raw.destroy 10 | 11 | raw.wait_for { print "."; STDOUT.flush; state=="terminated"} 12 | env.ui.info "" 13 | else 14 | env.ui.info "[#{@name}] - Machine is already terminated #{@raw.id}" 15 | end 16 | 17 | end 18 | 19 | end #module 20 | end #module 21 | end #module 22 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def forward(command,options={}) 6 | @forward_threads=Array.new 7 | unless raw.nil? 8 | return self.ssh_forward(options) 9 | else 10 | env.ui.info "[#{self.name}] not yet created" 11 | return [] 12 | end 13 | end 14 | 15 | end #module 16 | end #module 17 | end #module 18 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/halt.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def halt(options) 6 | 7 | if self.running? 8 | env.ui.info "Halting machine #{@name}(#{@raw.id})" 9 | raw.stop 10 | raw.wait_for { printf "."; STDOUT.flush; state=="stopped"} 11 | env.ui.info "" 12 | else 13 | unless @raw.nil? 14 | env.ui.info "#{@name}(#{@raw.id}) is already halted." 15 | else 16 | env.ui.info "#{@name} is not yet created or was terminated" 17 | end 18 | end 19 | 20 | end 21 | 22 | end #module 23 | end #module 24 | end #module 25 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/package.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def package(options=nil) 6 | 7 | #f=Fog::Compute.new({ :region => "eu-west-1", :provider => "AWS"}) 8 | # i=f.create_image("i-c1ac2bb7","name","description") 9 | # f.images.all({ "Owner" => "self"}) 10 | # f.deregister_image("ami-796d5b0d") 11 | 12 | time=Time.new 13 | strtime=time.strftime("%Y-%m-%d-%H-%M-%S") 14 | name="" 15 | 16 | if options["name"].nil? 17 | name="#{@name}-#{strtime}" 18 | else 19 | name=options["name"] 20 | end 21 | 22 | description="" 23 | if options["description"].nil? 24 | description="Autogenerated snapshot from machine #{@name}" 25 | else 26 | description=options["description"] 27 | end 28 | 29 | begin 30 | puts raw.id 31 | result=@provider.raw.create_image(raw.id,name,description) 32 | imageId=result.body["imageId"] 33 | env.ui.info "[#{@name}] image #{imageId} with #{description} being created" 34 | unless options["dontwait"] 35 | sleep 3 36 | counter=0 37 | max_tries=5 38 | #Pending 39 | state="pending" 40 | until state!="pending" do 41 | print "." 42 | sleep 2 43 | image=@provider.raw.images.get(imageId) 44 | 45 | if image.nil? 46 | sleep 3 47 | print "." 48 | else 49 | state=image.state 50 | end 51 | end 52 | env.ui.info "" 53 | env.ui.info "[#{@name}] creation done!" 54 | end 55 | rescue Fog::Service::Error => fogerror 56 | env.ui.error "[Error] #{fogerror}" 57 | 58 | end 59 | end 60 | 61 | end #module 62 | end #module 63 | end #module 64 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/provision.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def _provision(options=nil) 6 | unless raw.nil? 7 | 8 | if raw.ready? 9 | self.share 10 | 11 | @provisioners.each do |provisioner| 12 | env.ui.info "[#{@name}] - starting provisioning with #{provisioner.name} as provisioner" 13 | provisioner.run(self) 14 | end 15 | else 16 | raise Mccloud::Error, "[#{@name}] - machine is not running, skipping provisioning" 17 | end 18 | else 19 | raise Mccloud::Error, "[#{@name}] - machine doesn't exit yet" 20 | end 21 | end 22 | 23 | end #module 24 | end #module 25 | end #module 26 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/reload.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | def reload(options) 5 | env.logger.info "Checking if #{@name} is running: #{self.running?}" 6 | if self.running? 7 | self.halt(options) 8 | end 9 | self.up(options) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/resume.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedi4ever/mccloud/5d1995e50ac558e23feb94b87dcb018878a9b501/lib/mccloud/provider/aws/vm/resume.rb -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/rsync.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def rsync(src,dest,options) 6 | super(src,dest,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/scp.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def transfer(src,dest,options = {}) 6 | scp(src,dest,options) 7 | end 8 | 9 | def scp(local_path, remote_path, scp_options = {}) 10 | unless File.exists?(local_path) 11 | raise Mccloud::Error,"scp failed: #{local_path} does not exist" 12 | end 13 | 14 | #@raw.scp(src,dest) 15 | scp_options[:key_data] = [@raw.private_key] if @raw.private_key 16 | 17 | ::Fog::SCP.new(self.ip_address, @raw.username, sanitize(scp_options)).upload(local_path, remote_path, {}) 18 | end 19 | 20 | # 21 | # sanitize the options by converting to a hash with 22 | # all keys converted to symbols as required by net/ssh 23 | # 24 | def sanitize(options) 25 | Hash[options.map{|(k,v)| [k.to_sym,v]}] 26 | end 27 | 28 | end #module 29 | end #module 30 | end #module 31 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/ssh.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Aws 3 | module VmCommand 4 | 5 | def ssh(command,options={}) 6 | super(command,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/aws/vm/suspend.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedi4ever/mccloud/5d1995e50ac558e23feb94b87dcb018878a9b501/lib/mccloud/provider/aws/vm/suspend.rb -------------------------------------------------------------------------------- /lib/mccloud/provider/core/forwarding.rb: -------------------------------------------------------------------------------- 1 | class Forwarding 2 | attr_accessor :name 3 | attr_accessor :local 4 | attr_accessor :remote 5 | 6 | attr_accessor :namespace 7 | 8 | 9 | def initialize(name,remote,local) 10 | @name=name 11 | @local=local 12 | @remote=remote 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/ip.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Core 4 | 5 | class Ip 6 | attr_reader :env 7 | attr_accessor :provider 8 | attr_accessor :name 9 | attr_accessor :auto_selection 10 | 11 | def initialize(env) 12 | @auto_selection=true 13 | @env=env 14 | end 15 | 16 | def auto_selected? 17 | return auto_selection 18 | end 19 | 20 | 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/keystore.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Core 4 | 5 | class Keystore 6 | attr_reader :env 7 | attr_accessor :provider 8 | attr_accessor :name 9 | attr_accessor :auto_selection 10 | 11 | def initialize(env) 12 | @auto_selection=true 13 | @env=env 14 | end 15 | 16 | def auto_selected? 17 | return auto_selection 18 | end 19 | 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/lb.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Core 4 | 5 | class Lb 6 | attr_reader :env 7 | attr_accessor :provider 8 | attr_accessor :name 9 | attr_accessor :auto_selection 10 | 11 | def initialize(env) 12 | @auto_selection=true 13 | @env=env 14 | end 15 | 16 | def auto_selected? 17 | return @auto_selection 18 | end 19 | 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/provider.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Core 4 | class Provider 5 | 6 | attr_reader :env 7 | 8 | attr_accessor :namespace 9 | 10 | def initialize(name,options,env) 11 | @env=env 12 | end 13 | 14 | def get_component(type,env) 15 | real_component=nil 16 | begin 17 | # Now that we know the actual provider, we can check if the provider has this type of component 18 | require_path='mccloud/provider/'+@flavor.to_s.downcase+"/"+type.to_s.downcase 19 | require require_path 20 | # Now we can create the real component 21 | 22 | env.logger.debug("provider #{@flavor} about to create component of type #{type}") 23 | 24 | real_component=Object.const_get("Mccloud").const_get("Provider").const_get(@flavor.to_s.capitalize).const_get(type.to_s.capitalize).new(env) 25 | 26 | rescue Error => e 27 | env.ui.error "Error getting component - #{e}" 28 | end 29 | return real_component 30 | end 31 | 32 | def on_selected_components(type,selection=nil) 33 | unless self.instance_variables.collect{|v| v.to_s}.include?("@vms") 34 | env.ui.info "There are no #{type}s defined for provider #{@name}" 35 | # Nothing to do here 36 | return 37 | end 38 | 39 | components=self.instance_variable_get("@#{type}s") 40 | 41 | unless components.nil? 42 | 43 | if selection.nil? || selection == "all" 44 | components.each do |name,component| 45 | if component.auto_selected? 46 | yield name,component 47 | else 48 | env.ui.info "[#{name}] Skipping because it has autoselection off" 49 | end 50 | end 51 | else # a specific component 52 | if components.has_key?(selection) 53 | yield name,components[selection] 54 | end 55 | end 56 | 57 | else 58 | env.ui.info "[#{name}] Has no components of type #{type}" 59 | end 60 | end 61 | 62 | def filter 63 | if @namespace.nil? || @namespace=="" 64 | return "" 65 | else 66 | return "#{@namespace}-" 67 | end 68 | end 69 | 70 | def hosts 71 | hostentries = Hash.new 72 | self.vms.each do |name,vm| 73 | hostentries[name] = Hash.new 74 | hostentries[name]['public_ip_address'] = vm.public_ip_address 75 | hostentries[name]['private_ip_address'] = vm.private_ip_address 76 | end 77 | return hostentries 78 | end 79 | 80 | #TODO this loading of gem , needs to be moved else where 81 | #This provider should only check what it needs 82 | 83 | def check_gem_availability(gems) 84 | 85 | gems.each do |gemname| 86 | availability_gem=false 87 | begin 88 | availability_gem=true unless Gem::Specification::find_by_name("#{gemname}").nil? 89 | rescue Gem::LoadError 90 | availability_gem=false 91 | rescue 92 | availability_gem=Gem.available?("#{gemname}") 93 | end 94 | unless availability_gem 95 | abort "The #{gemname} gem is not installed and is required by the #{@name.to_sym} provider" 96 | exit 97 | end 98 | end 99 | end 100 | 101 | def method_missing(m, *args, &block) 102 | env.logger.info "There's no method #{m} defined for provider #{@name}-- ignoring it" 103 | end 104 | 105 | end 106 | end 107 | end 108 | end 109 | 110 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provisioner/chef_solo' 2 | require 'mccloud/provisioner/puppet' 3 | require 'mccloud/provisioner/shell' 4 | 5 | require 'mccloud/provider/core/forwarding' 6 | 7 | require 'mccloud/provider/core/vm/ssh.rb' 8 | require 'mccloud/provider/core/vm/ssh_bootstrap.rb' 9 | require 'mccloud/provider/core/vm/ssh_forward.rb' 10 | require 'mccloud/provider/core/vm/rsync.rb' 11 | 12 | module Mccloud 13 | module Provider 14 | module Core 15 | 16 | class ShellResult 17 | attr_accessor :stdout 18 | attr_accessor :stderr 19 | attr_accessor :status 20 | 21 | def initialize(stdout,stderr,status) 22 | @stdout=stdout 23 | @stderr=stderr 24 | @status=status 25 | end 26 | end 27 | 28 | class Vm 29 | 30 | include Mccloud::Provider::Core::VmCommand 31 | 32 | attr_reader :env 33 | 34 | attr_accessor :provider 35 | attr_accessor :definition 36 | 37 | attr_accessor :create_options 38 | attr_accessor :name 39 | attr_accessor :user 40 | attr_accessor :port 41 | attr_accessor :private_key_path 42 | attr_accessor :public_key_path 43 | attr_accessor :agent_forwarding 44 | 45 | attr_accessor :auto_selection 46 | 47 | attr_accessor :bootstrap 48 | attr_accessor :bootstrap_user 49 | attr_accessor :bootstrap_password 50 | attr_accessor :provisioners 51 | 52 | attr_accessor :forwardings 53 | attr_accessor :shared_folders 54 | attr_accessor :shared_files 55 | attr_accessor :stacked 56 | attr_accessor :declared 57 | 58 | def initialize(env) 59 | @env=env 60 | @forwardings=Array.new 61 | @shared_folders = Array.new 62 | @shared_files = Array.new 63 | @stacked=false 64 | @auto_selection=true 65 | @declared=true 66 | @provisioners=Array.new 67 | @port=22 68 | @agent_forwarding=false 69 | @create_options={} 70 | @definition=nil 71 | end 72 | 73 | def declared? 74 | return declared 75 | end 76 | 77 | def stacked? 78 | return stacked 79 | end 80 | 81 | def auto_selected? 82 | return auto_selection 83 | end 84 | 85 | def provisioner 86 | if provisioners.nil? 87 | return nil 88 | else 89 | provisioners.first 90 | end 91 | end 92 | 93 | # This function is swapped with the component provision function 94 | # while reading the configuration 95 | def provision(type) 96 | if block_given? 97 | case type 98 | when :chef_solo 99 | @provisioners<< Mccloud::Provisioner::ChefSolo.new(env) 100 | when :puppet 101 | @provisioners< true, :desc => 'Mccloud Prefix' 17 | option :mcEnvironment, :required => true, :desc => 'Mccloud Environment' 18 | option :mcIdentity, :required => true, :desc => 'Mccloud Identity' 19 | 20 | option :imageId, :required => true, :desc => 'Image ID' 21 | option :userName, :required => true, :desc => 'User Name' 22 | option :flavorId, :required => true, :desc => 'Flavor Id' 23 | option :providerId, :required => true, :desc => 'Provider Id' 24 | option :securityGroup, :required => true, :desc => 'Security Group' 25 | option :keyName, :required => true, :desc => 'Key Name' 26 | option :publicKeyPath, :required => false, :desc => 'Path to Public Key' 27 | option :privateKeyPath, :required => true, :desc => 'Path to Private Key' 28 | 29 | option :availabilityZone, :required => true, :desc => 'Availability Zone' 30 | 31 | template :mccloudfile, 'Mccloudfile' 32 | 33 | end 34 | 35 | desc "Generators to simplify the creation of a Mccloud Project" 36 | add :init, InitGenerator 37 | 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/old_multi.rb: -------------------------------------------------------------------------------- 1 | require 'net/ssh/multi' 2 | 3 | module Mccloud 4 | module Command 5 | #http://stackoverflow.com/questions/1383282/netsshmulti-using-the-environment-exec-how-do-you-get-the-output-straight-away 6 | #https://gist.github.com/700730 7 | def multi(selection=nil,command="who am i",options=nil) 8 | trap("INT") { puts "we hit CTRL_C"; exit } 9 | 10 | 11 | Net::SSH::Multi.start do |environment| 12 | # Connect to remote machines 13 | ip2name=Hash.new 14 | on_selected_machines(selection) do |id,vm| 15 | instance=vm.instance 16 | if instance.state == "running" 17 | ip2name[instance.public_ip_address]=vm.name 18 | environment.use "#{instance.public_ip_address}", { :user => vm.user , :keys => [ vm.private_key ], :paranoid => false, :keys_only => true} 19 | end 20 | end 21 | 22 | unless options["sudo"].nil? 23 | #check vm.sudo 24 | sudo_cmd="sudo" 25 | command="#{sudo_cmd} #{command}" 26 | end 27 | 28 | puts "Executing #{command}" 29 | begin 30 | environment.exec("#{command}") do |ch, stream, data| 31 | #exit code 32 | #http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/a806b0f5dae4e1e2 33 | 34 | ch.on_request("exit-status") do |ch, data| 35 | exit_code = data.read_long 36 | @status=exit_code 37 | if exit_code > 0 38 | puts "ERROR: exit code #{exit_code}" 39 | else 40 | puts "Successfully executed" 41 | end 42 | end 43 | if (ip2name.count > 1) || options.verbose? 44 | puts "[#{ip2name[ch[:host]]}] #{data}" 45 | else 46 | print "#{data}" 47 | end 48 | # puts "[#{ch[:host]} : #{stream}] #{data}" 49 | 50 | end 51 | rescue Errno::ECONNREFUSED 52 | puts "oops - no connection" 53 | end 54 | # Tell Net::SSH to wait for output from the SSH server 55 | environment.loop 56 | end 57 | 58 | end 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/old_reload.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | def reload(selection=nil?) 4 | load_config 5 | on_selected_machines(selection) do |id,vm| 6 | puts "rebooting #{id}" 7 | vm.instance.reboot 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/old_server.rb: -------------------------------------------------------------------------------- 1 | require 'net/ssh/multi' 2 | require 'pp' 3 | module Mccloud 4 | module Command 5 | def server(selection=nil,options=nil) 6 | 7 | puts "Starting server mode" 8 | trap("INT") { puts "You've hit CTRL-C . Stopping server now"; exit } 9 | threads = [] 10 | on_selected_machines(selection) do |id,vm| 11 | threads << Thread.new(id,vm) do |id,vm| 12 | public_ip_address=vm.instance.public_ip_address 13 | private_ip_address=vm.instance.private_ip_address 14 | unless public_ip_address.nil? || private_ip_address.nil? 15 | ssh_options={ :keys => [ vm.private_key ], :paranoid => false, :keys_only => true} 16 | Net::SSH.start(public_ip_address, vm.user, ssh_options) do |ssh| 17 | vm.forwardings.each do |forwarding| 18 | begin 19 | puts "Forwarding remote port #{forwarding.remote} from #{vm.name} to local port #{forwarding.local}" 20 | ssh.forward.local(forwarding.local, private_ip_address,forwarding.remote) 21 | rescue Errno::EACCES 22 | puts " Error - Access denied to forward remote port #{forwarding.remote} from #{vm.name} to local port #{forwarding.local}" 23 | end 24 | end 25 | ssh.loop { true } 26 | end 27 | end 28 | end 29 | end 30 | threads.each {|thr| thr.join} 31 | #puts "and we continue here" 32 | #sleep 30 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/old_ssh_command.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | def command(selection=nil,command="who am i") 4 | unless options.parallel? 5 | on_selected_machines(selection) do |id,vm| 6 | server=PROVIDER.servers.get(id) 7 | server.private_key_path=vm.private_key 8 | server.username = vm.user 9 | if server.state == "running" 10 | result=server.ssh(command) 11 | puts result[0].stdout 12 | else 13 | puts "not running so what's the point" 14 | end 15 | end 16 | else 17 | invoke :multi , [selection, command] 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/old_suspend.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Command 3 | def suspend 4 | load_config 5 | on_selected_machines(selection) do |id,vm| 6 | puts "Halting machine #{vm.name} with Id: #{id}" 7 | PROVIDER.servers.get(id).stop 8 | 9 | vm.instance.wait_for { printf ".";STDOUT.flush; state=="stopped"} 10 | puts 11 | 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/rsync.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Core 3 | module VmCommand 4 | 5 | def share_folder(name , dest,src,options={}) 6 | new_options={:mute => false}.merge(options) 7 | @shared_folders << { :name => name, :dest => dest, :src => src, :options => new_options} 8 | end 9 | 10 | def share_file(name , dest,src,options={}) 11 | new_options={:mute => false}.merge(options) 12 | @shared_files << { :name => name, :dest => dest, :src => src, :options => new_options} 13 | end 14 | 15 | def share 16 | @shared_folders.each do |folder| 17 | self.execute("test -d '#{folder[:dest]}' || mkdir -p '#{folder[:dest]}' ") 18 | clean_src_path=File.join(Pathname.new(folder[:src]).expand_path.cleanpath.to_s,'/') 19 | rsync(clean_src_path,folder[:dest],folder[:options]) 20 | end 21 | @shared_files.each do |file| 22 | self.execute("test -d '#{File.dirname(file[:dest])}' || mkdir -p '#{File.dirname(file[:dest])}' ") 23 | clean_src_path=Pathname.new(file[:src]).expand_path.cleanpath.to_s 24 | rsync(clean_src_path,file[:dest],file[:options]) 25 | end 26 | end 27 | 28 | def share_sync(src, dest, options = {}) 29 | clean_src_path=File.join(Pathname.new(src).cleanpath.to_s,'/') 30 | rsync(clean_src_path,dest,options) 31 | end 32 | 33 | def windows_client? 34 | ::Mccloud::Util::Platform.windows? 35 | end 36 | 37 | # cygwin rsync path must be adjusted to work 38 | def adjust_rsync_path(path) 39 | return path unless windows_client? 40 | path.gsub(/^(\w):/) { "/cygdrive/#{$1}" } 41 | end 42 | 43 | # see http://stackoverflow.com/questions/5798807/rsync-permission-denied-created-directories-have-no-permissions 44 | def rsync_permissions 45 | '--chmod=ugo=rwX' if windows_client? 46 | end 47 | 48 | # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/185404 49 | # This should work on windows too now 50 | # This will result in a ShellResult structure with stdout, stderr and status 51 | def rsync(src,dest="tmp",options = {}) 52 | unless !File.exists?(src) 53 | env.ui.info "[#{@name}] - rsyncing #{src}" 54 | mute="-v" 55 | mute="-q -t" if options[:mute] 56 | 57 | if Pathname.new(dest).absolute? 58 | dest_path = dest 59 | else 60 | dest_path = File.join(File::Separator,dest) 61 | end 62 | 63 | if dest_path == File::Separator 64 | puts "no way we gonna rsync --delete the root filesystem" 65 | exit -1 66 | end 67 | 68 | command="rsync #{rsync_permissions} --exclude '.DS_Store' --exclude '.hg' --exclude '.git' #{mute} --delete-excluded --delete -az -e 'ssh #{ssh_commandline_options(options)}' '#{adjust_rsync_path(src)}' '#{@user}@#{self.ip_address}:#{dest_path}'" 69 | else 70 | env.ui.info "[#{@name}] - rsync error: #{src} does no exist" 71 | exit 72 | end 73 | 74 | result=ShellResult.new("","",-1) 75 | env.logger.info "#{command}" unless options[:mute] 76 | IO.popen("#{command}") { |p| 77 | p.each_line{ |l| 78 | result.stdout+=l 79 | print l unless options[:mute] 80 | } 81 | result.status=Process.waitpid2(p.pid)[1].exitstatus 82 | if result.status!=0 83 | env.ui.info "Exit status was not 0 but #{result.status}" unless options[:mute] 84 | end 85 | } 86 | return result 87 | end 88 | 89 | end #module 90 | end #module 91 | end #module 92 | 93 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/ssh_bootstrap.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/platform' 2 | require 'net/ssh' 3 | 4 | module Mccloud 5 | module Provider 6 | module Core 7 | module VmCommand 8 | 9 | def ssh_bootstrap(command,bootstrap_options= {}) 10 | begin 11 | options = Hash.new 12 | 13 | options[:port] = @port 14 | 15 | unless @bootstrap_user.nil? 16 | options[:user] = @bootstrap_user 17 | end 18 | 19 | unless @bootstrap_password.nil? 20 | options[:password] = @bootstrap_password 21 | end 22 | 23 | if self.running? 24 | scriptname=command.nil? ? @bootstrap : command 25 | unless scriptname.nil? 26 | env.logger.info "[#{@name}] - Using #{scriptname} as bootstrap script" 27 | full_scriptname=Pathname.new(scriptname).expand_path(env.root_path).to_s 28 | env.logger.info "[#{@name}] - Full #{full_scriptname} " 29 | env.ui.info "[#{@name}] - Uploading bootstrap code to machine #{@name}" 30 | 31 | unless !File.exists?(full_scriptname) 32 | begin 33 | self.transfer(full_scriptname,"/tmp/bootstrap.sh",options) 34 | rescue Net::SSH::AuthenticationFailed 35 | raise ::Mccloud::Error, "[#{@name}] - Authentication problem \n" 36 | rescue Exception => ex 37 | raise ::Mccloud::Error, "[#{@name}] - Error uploading file #{full_scriptname} #{ex.inspect}\n" 38 | end 39 | env.ui.info "[#{@name}] - Enabling the bootstrap code to run" 40 | result=self.execute("chmod +x /tmp/bootstrap.sh && #{self.sudo_string("/tmp/bootstrap.sh",options)}",options) 41 | 42 | 43 | else 44 | raise ::Mccloud::Error, "[#{@name}] - Error: bootstrap file #{scriptname} does not exist" 45 | end 46 | 47 | else 48 | env.ui.warn "[#{@name}] - You didn't specify a bootstrap, hope you know what you're doing." 49 | end 50 | else 51 | env.ui.warn "[#{@name}] - Server is not running, so bootstrapping will do no good" 52 | end 53 | rescue ::Net::SSH::AuthenticationFailed => ex 54 | raise ::Mccloud::Error, "[#{@name}] - Authentication failure #{ex.to_s}" 55 | end 56 | end 57 | 58 | end #Module 59 | end #module 60 | end #Module 61 | end #module 62 | 63 | -------------------------------------------------------------------------------- /lib/mccloud/provider/core/vm/ssh_forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Core 4 | module VmCommand 5 | 6 | 7 | def ssh_forward(options=nil) 8 | return ssh_tunnel_start(@forwardings) 9 | end 10 | 11 | def ssh_tunnel_start(forwardings) 12 | unless forwardings.empty? 13 | @forward_threads<< Thread.new(self) { |vm| 14 | env=vm.env 15 | begin 16 | ssh_options={ :paranoid => false, :keys_only => true} 17 | ssh_options[:keys]= [ vm.private_key_path ] unless vm.private_key_path.nil? 18 | Net::SSH.start(vm.ip_address, vm.user, ssh_options) do |ssh_session| 19 | vm.forwardings.each do |f| 20 | begin 21 | env.ui.info "Forwarding remote port #{f.remote} on #{vm.ip_address} from #{@name} to localhost port #{f.local}" 22 | ssh_session.forward.local(f.local.to_i, "127.0.0.1",f.remote.to_i) 23 | #ssh_session.forward.local(f.local.to_i, vm.ip_address,f.remote.to_i) 24 | rescue Errno::EACCES 25 | env.ui.error "Error - Access denied to forward remote port #{f.remote} from #{@name} to localhost port #{f.local}" 26 | end 27 | end 28 | ssh_session.loop {true} 29 | end 30 | rescue IOError 31 | env.ui.error "IOError - maybe there is no listener on the port (yet?)" 32 | end 33 | } 34 | end 35 | return @forward_threads 36 | end 37 | 38 | def ssh_tunnel_stop 39 | @forward_threads.each do |thread| 40 | Thread.kill(thread) 41 | end 42 | end 43 | 44 | end #Module 45 | end #module 46 | end #Module 47 | end #module 48 | -------------------------------------------------------------------------------- /lib/mccloud/provider/fog/fogconfig.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | module Provider 3 | module Fog 4 | class FogConfig 5 | 6 | attr_reader :credential 7 | def initialize(credential) 8 | @credential=credential 9 | end 10 | 11 | def exists? 12 | return File.exists?(::Fog.credentials_path) 13 | end 14 | 15 | def missing_credentials(keynames) 16 | missing_credentials=Array.new 17 | ::Fog.credential=@credential 18 | 19 | keynames.each do |key| 20 | unless ::Fog.credentials.has_key?(key) 21 | missing_credentials << key 22 | end 23 | end 24 | return missing_credentials 25 | end 26 | 27 | def missing_snippet(keynames) 28 | # Reading the existing file if needed 29 | path=::Fog.credentials_path 30 | keys={} 31 | if File.exists?(path) 32 | keys=YAML.load(File.read(path)) 33 | end 34 | missing_credentials(keynames).each do |key| 35 | keys[@credential]=Hash.new if keys[@credential].nil? 36 | keys[@credential][key]="" 37 | end 38 | return keys.to_yaml 39 | end 40 | end 41 | end 42 | end 43 | end 44 | 45 | -------------------------------------------------------------------------------- /lib/mccloud/provider/fog/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/provider' 2 | require 'mccloud/provider/fog/fogconfig' 3 | 4 | module Mccloud 5 | module Provider 6 | module Fog 7 | class Provider < ::Mccloud::Provider::Core::Provider 8 | 9 | attr_accessor :credentials_path 10 | 11 | def initialize(name,options,env) 12 | super(name,options,env) 13 | required_gems=%w{fog} 14 | check_gem_availability(required_gems) 15 | require 'fog' 16 | @credentials_path=::Fog.credentials_path 17 | end 18 | 19 | def check_fog_credentials(keynames) 20 | ::Fog.credentials_path=@credentials_path 21 | 22 | errormsgs=["Missing Credentials"] 23 | fogconfig=::Mccloud::Provider::Fog::FogConfig.new(@credential) 24 | 25 | missing_credentials=fogconfig.missing_credentials(keynames) 26 | unless missing_credentials.empty? 27 | 28 | unless fogconfig.exists? 29 | errormsgs<<"Create the file #{::Fog.credentials_path} with the following content:" 30 | else 31 | errormsgs<<"Add the following snippet to #{::Fog.credentials_path}:" 32 | end 33 | 34 | errormsgs<< "===================== snippet begin =====================" 35 | errormsgs<< fogconfig.missing_snippet(keynames) 36 | errormsgs<< "===================== snippet end =====================" 37 | errormsg=errormsgs.join("\n") 38 | 39 | raise Mccloud::Error, "#{errormsg}" 40 | end 41 | end 42 | 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/host/provider/status' 2 | require 'mccloud/provider/host/vm' 3 | require 'mccloud/provider/core/provider' 4 | 5 | module Mccloud 6 | module Provider 7 | module Host 8 | class Provider < ::Mccloud::Provider::Core::Provider 9 | 10 | attr_accessor :name 11 | attr_accessor :flavor 12 | 13 | attr_accessor :options 14 | 15 | attr_accessor :vms 16 | 17 | include Mccloud::Provider::Host::ProviderCommand 18 | 19 | 20 | def initialize(name,options,env) 21 | 22 | super(name,options,env) 23 | 24 | @vms=Hash.new 25 | 26 | @options=options 27 | @flavor=self.class.to_s.split("::")[-2] 28 | @name=name 29 | end 30 | 31 | def raw 32 | # We don't use this 33 | @raw=nil 34 | end 35 | def up(selection,options) 36 | on_selected_components("vm",selection) do |id,vm| 37 | vm.up(options) 38 | end 39 | end 40 | 41 | def bootstrap(selection,script,options) 42 | on_selected_components("vm",selection) do |id,vm| 43 | vm._bootstrap(script,options) 44 | end 45 | 46 | end 47 | 48 | def destroy(selection,options) 49 | 50 | on_selected_components("vm",selection) do |id,vm| 51 | vm.destroy(options) 52 | end 53 | 54 | end 55 | 56 | def ssh(selection,command,options) 57 | 58 | on_selected_components("vm",selection) do |id,vm| 59 | vm.ssh(command,options) 60 | end 61 | 62 | end 63 | 64 | 65 | 66 | def provision(selection,options) 67 | 68 | on_selected_components("vm",selection) do |id,vm| 69 | vm._provision(options) 70 | end 71 | 72 | end 73 | 74 | def halt(selection,options) 75 | on_selected_components("vm",selection) do |id,vm| 76 | env.ui.info "Matched #{vm.name}" 77 | vm.halt(options) 78 | end 79 | 80 | end 81 | 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Host 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | #require 'mccloud/provider/host/vm/up' 4 | require 'mccloud/provider/host/vm/bootstrap' 5 | require 'mccloud/provider/host/vm/ssh' 6 | require 'mccloud/provider/host/vm/scp' 7 | require 'mccloud/provider/host/vm/forward' 8 | #require 'mccloud/provider/host/vm/rsync' 9 | #require 'mccloud/provider/host/vm/halt' 10 | require 'mccloud/provider/host/vm/provision' 11 | #require 'mccloud/provider/host/vm/destroy' 12 | 13 | module Mccloud::Provider 14 | module Host 15 | 16 | class Vm < ::Mccloud::Provider::Core::Vm 17 | 18 | include Mccloud::Provider::Host::VmCommand 19 | 20 | attr_accessor :ip_address 21 | 22 | def runnning? 23 | true 24 | end 25 | 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm/bootstrap.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Host 3 | module VmCommand 4 | 5 | def _bootstrap(command,options=nil) 6 | ssh_bootstrap(command,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Host 3 | module VmCommand 4 | 5 | def forward(command,options={}) 6 | @forward_threads=Array.new 7 | return self.ssh_forward(options) 8 | end 9 | 10 | end #module 11 | end #module 12 | end #module 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm/provision.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Host 3 | module VmCommand 4 | 5 | def _provision(options) 6 | 7 | self.share 8 | 9 | unless @provisioners.nil? 10 | @provisioners.each do |provisioner| 11 | env.ui.info "[#{@name}] - starting provisioning with #{provisioner.name} as provisioner" 12 | provisioner.run(self) 13 | end 14 | end 15 | end 16 | 17 | end #module 18 | end #module 19 | end #module 20 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm/scp.rb: -------------------------------------------------------------------------------- 1 | require 'net/scp' 2 | module Mccloud::Provider 3 | module Host 4 | module VmCommand 5 | 6 | def transfer(src,dest,options = {}) 7 | scp(src,dest,options) 8 | end 9 | 10 | def scp(src,dest,options = {}) 11 | 12 | # override options from Mccloudfile with parameter options 13 | ssh_options = mccloudfile_options.merge(options) 14 | 15 | Net::SCP.start(ip_address,ssh_options[:user],ssh_options) do |auth_scp| 16 | auth_scp.upload!(src,dest) 17 | end 18 | end 19 | 20 | def mccloudfile_options 21 | opts = Hash.new 22 | (opts[:user] = @user) if @user 23 | (opts[:keys] = @private_key_path) if @private_key_path 24 | (opts[:port] = @port) if @port 25 | opts 26 | end 27 | 28 | end #module 29 | end #module 30 | end #module 31 | -------------------------------------------------------------------------------- /lib/mccloud/provider/host/vm/ssh.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Host 3 | module VmCommand 4 | 5 | def ssh(command,options={}) 6 | super(command,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/libvirt/provider/status' 2 | require 'mccloud/provider/libvirt/vm' 3 | require 'mccloud/provider/fog/provider' 4 | 5 | module Mccloud 6 | module Provider 7 | module Libvirt 8 | class Provider < ::Mccloud::Provider::Fog::Provider 9 | 10 | attr_accessor :name 11 | attr_accessor :flavor 12 | 13 | attr_accessor :options 14 | 15 | attr_accessor :vms 16 | 17 | include Mccloud::Provider::Libvirt::ProviderCommand 18 | 19 | 20 | def initialize(name,options,env) 21 | 22 | super 23 | 24 | @vms=Hash.new 25 | 26 | @options=options 27 | @flavor=self.class.to_s.split("::")[-2] 28 | @name=name 29 | 30 | required_gems=%w{ruby-libvirt fog} 31 | check_gem_availability(required_gems) 32 | require 'libvirt' 33 | require 'fog' 34 | end 35 | 36 | 37 | def raw 38 | if @raw.nil? 39 | begin 40 | @raw=::Fog::Compute.new({:provider => "Libvirt"}.merge(@options)) 41 | rescue ArgumentError => e 42 | env.ui.error "Error loading raw provider : #{e.to_s} #{$!}" 43 | @raw=nil 44 | end 45 | end 46 | return @raw 47 | end 48 | 49 | def up(selection,options) 50 | on_selected_components("vm",selection) do |id,vm| 51 | vm.up(options) 52 | end 53 | end 54 | 55 | def bootstrap(selection,script,options) 56 | on_selected_components("vm",selection) do |id,vm| 57 | vm._bootstrap(script,options) 58 | end 59 | end 60 | 61 | def destroy(selection,options) 62 | on_selected_components("vm",selection) do |id,vm| 63 | vm.destroy(options) 64 | end 65 | end 66 | 67 | def ssh(selection,command,options) 68 | on_selected_components("vm",selection) do |id,vm| 69 | vm.ssh(command,options) 70 | end 71 | end 72 | 73 | 74 | 75 | def provision(selection,options) 76 | on_selected_components("vm",selection) do |id,vm| 77 | vm._provision(options) 78 | end 79 | end 80 | 81 | def halt(selection,options) 82 | on_selected_components("vm",selection) do |id,vm| 83 | vm.halt(options) 84 | end 85 | end 86 | 87 | def reload(selection,options) 88 | on_selected_components("vm",selection) do |id,vm| 89 | vm.reload(options) 90 | end 91 | end 92 | 93 | end 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | env.ui.info "" 8 | env.ui.info "Server(s) - provider #{@name}" 9 | 10 | printf "%-10s %-12s %-20s %-15s %-8s\n", "Name", "Instance Id", "IP", "Type","Status" 11 | 80.times { |i| printf "=" } ; env.ui.info "" 12 | 13 | raw.servers.each do |vm| 14 | if vm.name.start_with?(self.filter) 15 | unless self.filter=="" 16 | vm.name[self.filter]="" 17 | printf "%-10s %-12s %-20s %-20s %-15s %-8s\n",vm.name,vm.mac, vm.public_ip_address, vm.cpus,vm.memory_size,vm.state 18 | else 19 | env.ui.info "Name: #{vm.name}" 20 | env.ui.info "Instance Id: #{vm.uuid}" 21 | env.ui.info "Public Ip: #{vm.public_ip_address}" 22 | env.ui.info "Cpus: #{vm.cpus}" 23 | env.ui.info "State: #{vm.state}" 24 | 80.times { |i| printf "=" } ; env.ui.info "" 25 | end 26 | end 27 | end 28 | 29 | 30 | env.ui.info "Volume(s) - provider #{@name}" 31 | 80.times { |i| printf "=" } ; env.ui.info "" 32 | volume_list=raw.volumes.all() 33 | volume_list.each do |volume| 34 | printf "%-20s: %-10s %-10s \n",volume.name,volume.id,volume.key 35 | printf "%-20s: %-10s %-20s %-10s\n","",volume.pool_name, volume.path, volume.format_type 36 | printf "%-20s: %-10s %-10s\n","",volume.capacity,volume.allocation 37 | end 38 | 39 | end 40 | 41 | end #module 42 | end #module 43 | end #module 44 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | require 'mccloud/provider/libvirt/vm/up' 4 | require 'mccloud/provider/libvirt/vm/bootstrap' 5 | require 'mccloud/provider/libvirt/vm/ssh' 6 | require 'mccloud/provider/libvirt/vm/scp' 7 | require 'mccloud/provider/libvirt/vm/rsync' 8 | require 'mccloud/provider/libvirt/vm/halt' 9 | require 'mccloud/provider/libvirt/vm/provision' 10 | require 'mccloud/provider/libvirt/vm/destroy' 11 | require 'mccloud/provider/libvirt/vm/reload' 12 | require 'mccloud/provider/libvirt/vm/forward' 13 | 14 | 15 | module Mccloud::Provider 16 | module Libvirt 17 | 18 | class Vm < ::Mccloud::Provider::Core::Vm 19 | 20 | include Mccloud::Provider::Libvirt::VmCommand 21 | 22 | def ip_address 23 | return self.public_ip_address 24 | end 25 | 26 | def public_ip_address 27 | unless raw.nil? 28 | ip=raw.public_ip_address 29 | else 30 | ip=nil 31 | end 32 | return ip 33 | end 34 | 35 | def running? 36 | if raw.nil? 37 | return false 38 | else 39 | return raw.ready? 40 | end 41 | end 42 | 43 | def private_ip_address 44 | unless raw.nil? 45 | ip=raw.private_ip_address 46 | else 47 | ip=nil 48 | end 49 | return ip 50 | end 51 | 52 | def raw 53 | if @raw.nil? 54 | found=@provider.raw.servers.all(:name => "#{@provider.filter}#{@name}") 55 | unless found.nil? 56 | @raw=found.first 57 | end 58 | else 59 | @raw.private_key_path=@private_key_path 60 | @raw.username = @user 61 | end 62 | 63 | return @raw 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/bootstrap.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/util/platform' 2 | 3 | module Mccloud::Provider 4 | module Libvirt 5 | module VmCommand 6 | 7 | def _bootstrap(command,options=nil) 8 | if raw.ready? 9 | env.ui.info "[#{@name}] - Waiting for an ip-address " 10 | raw.wait_for { printf "."; STDOUT.flush; !public_ip_address.nil? } 11 | end 12 | ssh_bootstrap(command,options) 13 | end 14 | 15 | end #module 16 | end #Module 17 | end #module 18 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/destroy.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def destroy(options) 6 | fullname="#{@provider.filter}#{@name}" 7 | server=@provider.raw.servers.all(:name => fullname) 8 | volname="#{fullname}.img" 9 | #TODO use the creation options 10 | volume=@provider.raw.volumes.all(:name => volname) 11 | 12 | unless server.nil? 13 | env.ui.info "[#{@name}] - Destroying machine #{@provider.namespace}::#{@name}" 14 | 15 | server.first.destroy 16 | else 17 | env.ui.info "[#{@name}] - Server #{@provider.namespace}::#{@name} does not exist" 18 | end 19 | 20 | unless volume.nil? 21 | env.ui.info "[#{@name}] - Destroying volume #{@provider.namespace}::#{@name}.img" 22 | 23 | volume.first.destroy 24 | else 25 | env.ui.info "[#{@name}] - Volume #{@provider.namespace}::#{@name}.img does not exist" 26 | 27 | end 28 | 29 | end 30 | 31 | end #module 32 | end #module 33 | end #module 34 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def forward(command,options={}) 6 | @forward_threads=Array.new 7 | return self.ssh_forward(options) 8 | end 9 | 10 | end #module 11 | end #module 12 | end #module 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/halt.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def halt(options) 6 | 7 | if self.running? 8 | env.ui.info "Halting machine #{@name}(#{@raw.id})" 9 | raw.shutdown 10 | raw.wait_for { printf "."; STDOUT.flush; state=="stopped"||state=="crashed"} 11 | env.ui.info "" 12 | else 13 | env.ui.info "#{@name}(#{raw.id}) is already halted." 14 | end 15 | 16 | end 17 | 18 | end #module 19 | end #module 20 | end #module 21 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/provision.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def _provision(options) 6 | 7 | unless raw.nil? 8 | 9 | if raw.ready? 10 | @provisioners.each do |provisioner| 11 | env.ui.info "[#{@name}] - starting provisioning with #{provisioner.name} as provisioner" 12 | provisioner.run(self) 13 | end 14 | else 15 | env.ui.info "[#{@name}] - machine is not running, skipping provisioning" 16 | end 17 | else 18 | env.ui.info "[#{@name}] - machine doesn't exit yet" 19 | end 20 | 21 | end 22 | 23 | end #module 24 | end #module 25 | end #module 26 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/reload.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | def reload(options) 5 | env.logger.info "Checking if #{@name} is running: #{self.running?}" 6 | if self.running? 7 | self.halt(options) 8 | end 9 | self.up(options) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/rsync.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def rsync(path,options) 6 | super(path,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/scp.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def transfer(src,dest,options = {}) 6 | scp(src,dest,options) 7 | end 8 | 9 | def scp(src,dest, options = {}) 10 | raw.scp(src,dest,options) 11 | end 12 | 13 | end #module 14 | end #module 15 | end #module 16 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/ssh.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def ssh(command,options={}) 6 | super(command,options) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/libvirt/vm/up.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Libvirt 3 | module VmCommand 4 | 5 | def up(options) 6 | 7 | env.ui.info "Upping of libvirt vm #{@name}" 8 | 9 | # There is no existing machine yet, so we create it 10 | if raw.nil? 11 | enhanced_create_options=@create_options 12 | enhanced_create_options[:name]="#{@provider.filter}#{@name}" 13 | env.ui.info "[#{@name}] - Creating machine #{@provider.namespace}::#{@name}" 14 | @raw=@provider.raw.servers.create(enhanced_create_options) 15 | raw.start 16 | 17 | env.ui.info "[#{@name}] - Waiting for the machine to become accessible" 18 | raw.wait_for { printf "."; STDOUT.flush; ready?} 19 | 20 | # Wait for ssh to become available ... 21 | env.ui.info "[#{@name}] - Waiting for ip address" 22 | #env.ui.info instance.console_output.body["output"] 23 | raw.wait_for { printf "."; STDOUT.flush; !public_ip_address.nil?} 24 | 25 | env.ui.info "[#{@name}] - Waiting for ssh on #{self.ip_address} to become available" 26 | Mccloud::Util::Ssh.execute_when_tcp_available(self.ip_address, { :port => @port, :timeout => 6000 }) do 27 | env.ui.info "[#{@name}] - Ssh is available , proceeding with bootstrap" 28 | end 29 | 30 | # Because it's a new machine we bootstrap it to 31 | self._bootstrap(nil,options) 32 | 33 | else 34 | state=raw.state 35 | if state !="running" 36 | env.ui.info "Booting up machine #{@name}" 37 | raw.start 38 | raw.wait_for { printf ".";STDOUT.flush; ready?} 39 | env.ui.info "" 40 | else 41 | unless raw.state == "shutting-down" 42 | env.ui.info "[#{@name}] - already running." 43 | else 44 | env.ui.info "[#{@name}] - can't start machine because it is in state #{raw.state}" 45 | return 46 | end 47 | end 48 | 49 | end 50 | 51 | unless options["noprovision"] 52 | env.ui.info "[#{@name}] - Waiting for ssh to become available" 53 | Mccloud::Util::Ssh.execute_when_tcp_available(self.ip_address, { :port => @port, :timeout => 6000 }) do 54 | env.ui.info "[#{@name}] - Ssh is available , proceeding with provisioning" 55 | end 56 | 57 | env.ui.info "[#{@name}] - provision step #{@name}" 58 | self._provision(options) 59 | end 60 | 61 | end 62 | 63 | end #module 64 | end #module 65 | end #module 66 | -------------------------------------------------------------------------------- /lib/mccloud/provider/script/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/script/vm' 2 | require 'mccloud/util/platform' 3 | require 'mccloud/provider/core/provider' 4 | 5 | module Mccloud 6 | module Provider 7 | module Script 8 | class Provider < ::Mccloud::Provider::Core::Provider 9 | 10 | attr_accessor :name 11 | attr_accessor :flavor 12 | 13 | attr_accessor :options 14 | 15 | attr_accessor :vms 16 | 17 | attr_accessor :script_dir 18 | attr_accessor :variables 19 | 20 | #include Mccloud::Provider::Script::ProviderCommand 21 | 22 | 23 | def initialize(name,options,env) 24 | 25 | super(name,options,env) 26 | 27 | @vms=Hash.new 28 | @variables=Hash.new 29 | 30 | @options=options 31 | @flavor=self.class.to_s.split("::")[-2] 32 | @name=name 33 | end 34 | 35 | def up(selection,options) 36 | on_selected_components("vm",selection) do |id,vm| 37 | script_exec("up.sh",vm,options) 38 | end 39 | end 40 | 41 | def status(selection,options) 42 | unless selection.nil? 43 | on_selected_components("vm",selection) do |id,vm| 44 | script_exec("status.sh",vm,options) 45 | end 46 | else 47 | script_exec("status.sh",nil,options) 48 | end 49 | end 50 | 51 | def bootstrap(selection,script,options) 52 | on_selected_components("vm",selection) do |id,vm| 53 | script_exec("bootstrap.sh",vm,options) 54 | end 55 | 56 | end 57 | 58 | def destroy(selection,options) 59 | 60 | on_selected_components("vm",selection) do |id,vm| 61 | script_exec("destroy.sh",vm,options) 62 | end 63 | 64 | end 65 | 66 | def ssh(selection,command,options) 67 | 68 | on_selected_components("vm",selection) do |id,vm| 69 | script_exec("ssh.sh",vm,options) 70 | end 71 | 72 | end 73 | 74 | def provision(selection,options) 75 | 76 | on_selected_components("vm",selection) do |id,vm| 77 | script_exec("provision.sh",vm,options) 78 | end 79 | 80 | end 81 | 82 | def halt(selection,options) 83 | on_selected_components("vm",selection) do |id,vm| 84 | script_exec("halt.sh",vm,options) 85 | end 86 | 87 | end 88 | 89 | private 90 | def script_exec(filename,vm,options) 91 | 92 | # Set provider variables 93 | unless vm.nil? 94 | vm.variables.each do |name,value| 95 | env.logger.info "setting environment: #{name}=#{value}" 96 | ENV["MC_"+name.to_s]=value 97 | end 98 | ENV["MC_BOXNAME"]=vm.name 99 | end 100 | 101 | # Set vm variables 102 | env.logger.info "script_dir : #{File.expand_path(@script_dir)}" 103 | ENV["MC_SCRIPT_DIR"]=File.expand_path(@script_dir) 104 | @variables.each do |name,value| 105 | env.logger.info "setting environment: #{name}=#{value}" 106 | ENV["MC_"+name.to_s]=value 107 | end 108 | 109 | # Some hackery going on here. On Mac OS X Leopard (1.5), exec fails 110 | # (GH-51). As a workaround, we fork and wait. On all other platforms, 111 | # we simply exec. 112 | pid = nil 113 | pid = fork if ::Mccloud::Util::Platform.leopard? || ::Mccloud::Util::Platform.tiger? 114 | 115 | env.ui.info "Executing internal ssh command" 116 | script_command="#{File.join(self.script_dir,filename)}" 117 | env.ui.info script_command 118 | Kernel.exec "sh #{script_command}" if pid.nil? 119 | Process.wait(pid) if pid 120 | end 121 | 122 | end 123 | end 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /lib/mccloud/provider/script/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Script 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/script/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | module Mccloud::Provider 4 | module Script 5 | 6 | class Vm < ::Mccloud::Provider::Core::Vm 7 | 8 | attr_accessor :ip_address 9 | attr_accessor :variables 10 | 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/vagrant/provider/status' 2 | require 'mccloud/provider/vagrant/vm' 3 | require 'vagrant' 4 | 5 | module Mccloud 6 | module Provider 7 | module Vagrant 8 | class Provider < ::Mccloud::Provider::Core::Provider 9 | 10 | attr_accessor :name 11 | attr_accessor :flavor 12 | 13 | attr_accessor :options 14 | 15 | attr_accessor :vms 16 | 17 | include Mccloud::Provider::Vagrant::ProviderCommand 18 | 19 | 20 | def initialize(name,options,env) 21 | 22 | super(name,options,env) 23 | @options=options 24 | @flavor=self.class.to_s.split("::")[-2] 25 | @name=name 26 | @vms=Hash.new 27 | 28 | required_gems=%w{vagrant} 29 | check_gem_availability(required_gems) 30 | require 'vagrant' 31 | require 'vagrant/cli' 32 | 33 | 34 | end 35 | 36 | #We use this to get access to the logger attribute 37 | class LogEnvironment < ::Vagrant::Environment 38 | def logger=(logger) 39 | @logger=logger 40 | end 41 | end 42 | 43 | def raw 44 | if @raw.nil? 45 | begin 46 | @raw=LogEnvironment.new(:cwd => ".",:ui_class => ::Vagrant::UI::Colored) 47 | require 'logger' 48 | vlogger=::Logger.new(STDOUT) 49 | vlogger.formatter=Proc.new do |severity, datetime, progname, msg| 50 | "#{datetime} - #{progname} - #{msg}\n" 51 | #" [#{resource}] #{msg}\n" 52 | end 53 | # @raw.ui=Vagrant::UI.new(@raw) 54 | # @raw.ui.logger= 55 | @raw.logger=vlogger 56 | 57 | @raw.load! 58 | rescue ArgumentError => e 59 | env.ui.error "Error loading raw provider : #{e.to_s} #{$!}" 60 | @raw=nil 61 | end 62 | end 63 | return @raw 64 | end 65 | 66 | def up(selection,options) 67 | on_selected_components("vm",selection) do |id,vm| 68 | vm.up(options) 69 | end 70 | end 71 | 72 | def bootstrap(selection,command,options) 73 | on_selected_components("vm",selection) do |id,vm| 74 | vm.bootstrap(command,options) 75 | end 76 | 77 | end 78 | 79 | def destroy(selection,options) 80 | 81 | on_selected_components("vm",selection) do |id,vm| 82 | vm.destroy(options) 83 | end 84 | 85 | end 86 | 87 | def reload(selection,options) 88 | 89 | on_selected_components("vm",selection) do |id,vm| 90 | vm.reload(options) 91 | end 92 | 93 | end 94 | 95 | def suspend(selection,options) 96 | 97 | on_selected_components("vm",selection) do |id,vm| 98 | vm.suspend(options) 99 | end 100 | 101 | end 102 | 103 | def ssh(selection,command,options) 104 | 105 | on_selected_components("vm",selection) do |id,vm| 106 | vm.ssh(command,options) 107 | end 108 | 109 | end 110 | 111 | def provision(selection,options) 112 | 113 | on_selected_components("vm",selection) do |id,vm| 114 | vm._provision(options) 115 | end 116 | 117 | end 118 | 119 | def halt(selection,options) 120 | on_selected_components("vm",selection) do |id,vm| 121 | vm.halt(options) 122 | end 123 | 124 | end 125 | 126 | 127 | end 128 | 129 | end 130 | 131 | 132 | 133 | end 134 | end 135 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | self.raw.cli(['status',selection]) 8 | 9 | end 10 | 11 | end #module 12 | end #module 13 | end #module 14 | 15 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | require 'mccloud/provider/vagrant/vm/up' 4 | #require 'mccloud/provider/vagrant/vm/bootstrap' 5 | require 'mccloud/provider/vagrant/vm/ssh' 6 | require 'mccloud/provider/vagrant/vm/suspend' 7 | #require 'mccloud/provider/vagrant/vm/scp' 8 | #require 'mccloud/provider/vagrant/vm/rsync' 9 | require 'mccloud/provider/vagrant/vm/reload' 10 | require 'mccloud/provider/vagrant/vm/halt' 11 | require 'mccloud/provider/vagrant/vm/provision' 12 | require 'mccloud/provider/vagrant/vm/destroy' 13 | require 'mccloud/provider/vagrant/vm/forward' 14 | 15 | module Mccloud::Provider 16 | module Vagrant 17 | 18 | class Vm < ::Mccloud::Provider::Core::Vm 19 | 20 | include Mccloud::Provider::Vagrant::VmCommand 21 | 22 | def initialize(env) 23 | @user="vagrant" 24 | end 25 | 26 | def ip_address 27 | "127.0.0.1" 28 | end 29 | 30 | def public_ip_address 31 | "127.0.0.1" 32 | end 33 | 34 | def private_ip_address 35 | "127.0.0.1" 36 | end 37 | 38 | def raw 39 | if @raw.nil? 40 | @raw=@provider.raw.vms[@name.to_sym] 41 | end 42 | return @raw 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/destroy.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def destroy(command,options={}) 6 | self.provider.raw.cli(['destroy',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def forward(command,options={}) 6 | @forward_threads=Array.new 7 | return self.ssh_forward(options) 8 | end 9 | 10 | end #module 11 | end #module 12 | end #module 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/halt.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def halt(command,options={}) 6 | self.provider.raw.cli(['halt',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/provision.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def _provision(command,options={}) 6 | self.provider.raw.cli(['provision',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/reload.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def reload(command,options={}) 6 | self.provider.raw.cli(['reload',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/resume.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def resume(command,options={}) 6 | self.provider.raw.cli(['resume',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/ssh.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def ssh(command,options={}) 6 | self.provider.raw.cli(['ssh',self.name, command]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/suspend.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def suspend(command,options={}) 6 | self.provider.raw.cli(['suspend',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vagrant/vm/up.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vagrant 3 | module VmCommand 4 | 5 | def up(command,options={}) 6 | self.provider.raw.cli(['up',name]) 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/provider.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/vmfusion/provider/status' 2 | require 'mccloud/provider/vmfusion/vm' 3 | require 'mccloud/provider/core/provider' 4 | 5 | module Mccloud 6 | module Provider 7 | module Vmfusion 8 | class Provider < ::Mccloud::Provider::Core::Provider 9 | 10 | attr_accessor :name 11 | attr_accessor :flavor 12 | 13 | attr_accessor :options 14 | 15 | attr_accessor :vms 16 | 17 | include Mccloud::Provider::Vmfusion::ProviderCommand 18 | 19 | 20 | def initialize(name,options,env) 21 | 22 | super(name,options,env) 23 | @options=options 24 | @flavor=self.class.to_s.split("::")[-2] 25 | @name=name 26 | @vms=Hash.new 27 | 28 | required_gems=%w{fission} 29 | check_gem_availability(required_gems) 30 | require 'fission' 31 | 32 | end 33 | 34 | def raw 35 | if @raw.nil? 36 | begin 37 | @raw=Fission::VM.all 38 | rescue ArgumentError => e 39 | env.ui.error "Error loading raw provider : #{e.to_s} #{$!}" 40 | @raw=nil 41 | end 42 | end 43 | return @raw 44 | end 45 | 46 | def up(selection,options) 47 | on_selected_components("vm",selection) do |id,vm| 48 | vm.up(options) 49 | end 50 | end 51 | 52 | def bootstrap(selection,command,options) 53 | on_selected_components("vm",selection) do |id,vm| 54 | vm.bootstrap(command,options) 55 | end 56 | 57 | end 58 | 59 | def destroy(selection,options) 60 | 61 | on_selected_components("vm",selection) do |id,vm| 62 | vm.destroy(options) 63 | end 64 | 65 | end 66 | 67 | def ssh(selection,command,options) 68 | 69 | on_selected_components("vm",selection) do |id,vm| 70 | vm.ssh(command,options) 71 | end 72 | 73 | end 74 | 75 | 76 | end 77 | 78 | 79 | def provision(selection,options) 80 | 81 | on_selected_components("vm",selection) do |id,vm| 82 | vm._provision(options) 83 | end 84 | 85 | end 86 | 87 | def halt(selection,options) 88 | on_selected_components("vm",selection) do |id,vm| 89 | env.ui.info "Matched #{vm.name}" 90 | vm.halt(options) 91 | end 92 | 93 | end 94 | 95 | end 96 | end 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/provider/status.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module ProviderCommand 4 | 5 | def status(selection=nil,options=nil) 6 | 7 | env.ui.info "" 8 | 80.times { |i| printf "*"}; env.ui.info "" 9 | all_vms = ::Fission::VM.all 10 | all_running_vms = ::Fission::VM.all_running 11 | 12 | longest_vm_name = all_vms.max { |a,b| a.length <=> b.length } 13 | 14 | ::Fission::VM.all.each do |vm| 15 | status = all_running_vms.include?(vm) ? '[running]' : '[not running]' 16 | Fission.ui.output_printf "%-#{longest_vm_name.length}s %s\n", vm, status 17 | end 18 | 19 | end 20 | 21 | end #module 22 | end #module 23 | end #module 24 | 25 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/provider/core/vm' 2 | 3 | require 'mccloud/provider/vmfusion/vm/up' 4 | #require 'mccloud/provider/vmfusion/vm/bootstrap' 5 | #require 'mccloud/provider/vmfusion/vm/ssh' 6 | #require 'mccloud/provider/vmfusion/vm/scp' 7 | #require 'mccloud/provider/vmfusion/vm/rsync' 8 | require 'mccloud/provider/vmfusion/vm/halt' 9 | require 'mccloud/provider/vmfusion/vm/resume' 10 | require 'mccloud/provider/vmfusion/vm/suspend' 11 | require 'mccloud/provider/vmfusion/vm/forward' 12 | #require 'mccloud/provider/vmfusion/vm/provision' 13 | #require 'mccloud/provider/vmfusion/vm/destroy' 14 | 15 | 16 | module Mccloud::Provider 17 | module Vmfusion 18 | 19 | class Vm < ::Mccloud::Provider::Core::Vm 20 | 21 | include Mccloud::Provider::Vmfusion::VmCommand 22 | 23 | 24 | def ip_address 25 | "127.0.0.1" 26 | end 27 | 28 | def public_ip_address 29 | "127.0.0.1" 30 | end 31 | 32 | def private_ip_address 33 | "127.0.0.1" 34 | end 35 | 36 | def raw 37 | if @raw.nil? 38 | if @provider.raw.include?(@name.to_s) 39 | @raw=Fission::VM.new("#{@name.to_s}") 40 | end 41 | end 42 | 43 | return @raw 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm/forward.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module VmCommand 4 | 5 | def forward(command,options={}) 6 | @forward_threads=Array.new 7 | return self.ssh_forward(options) 8 | end 9 | 10 | end #module 11 | end #module 12 | end #module 13 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm/halt.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module VmCommand 4 | 5 | def halt(command,options={}) 6 | raw.stop 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm/resume.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module VmCommand 4 | 5 | def resume(command,options={}) 6 | raw.start 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm/suspend.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module VmCommand 4 | 5 | def suspend(command,options={}) 6 | raw.suspend 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provider/vmfusion/vm/up.rb: -------------------------------------------------------------------------------- 1 | module Mccloud::Provider 2 | module Vmfusion 3 | module VmCommand 4 | 5 | def up(command,options={}) 6 | raw.start 7 | end 8 | 9 | end #module 10 | end #module 11 | end #module 12 | -------------------------------------------------------------------------------- /lib/mccloud/provisioner/shell.rb: -------------------------------------------------------------------------------- 1 | require 'erb' 2 | require 'ostruct' 3 | 4 | module Mccloud 5 | module Provisioner 6 | 7 | class Shell 8 | 9 | attr_reader :name 10 | attr_reader :env 11 | 12 | attr_accessor :path 13 | attr_accessor :inline 14 | attr_accessor :sudo 15 | 16 | def initialize(env) 17 | @env=env 18 | @sudo=false 19 | @name ="shell" 20 | @inline="who am i" 21 | @log_level="info" 22 | end 23 | 24 | def run(server) 25 | server.transfer(StringIO.new(@inline),"/tmp/shell-provisioner.sh") unless @inline.nil? 26 | server.transfer(path,"/tmp/shell-provisioner.sh") unless @path.nil? 27 | 28 | server.execute("chmod +x /tmp/shell-provisioner.sh",{:mute => true}) 29 | 30 | env.ui.info "[#{server.name}] - [#{@name}] - running shell" 31 | env.ui.info "[#{server.name}] - [#{@name}] - login as #{server.user}" 32 | 33 | begin 34 | if !@sudo || server.user=="root" 35 | server.execute("/tmp/shell-provisioner.sh") 36 | else 37 | server.execute("sudo /tmp/shell-provisioner.sh") 38 | end 39 | rescue Exception 40 | ensure 41 | env.ui.info "[#{server.name}] - [#{@name}] - Cleaning up script" 42 | server.execute("rm /tmp/shell-provisioner.sh",{:mute => true}) 43 | end 44 | end 45 | 46 | end 47 | end #Module Provisioners 48 | end #Module Mccloud 49 | -------------------------------------------------------------------------------- /lib/mccloud/template.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | class Template 3 | attr_accessor :file 4 | attr_accessor :erb 5 | attr_accessor :params 6 | attr_accessor :author 7 | attr_accessor :bootstrap 8 | 9 | attr_accessor :name 10 | attr_accessor :env 11 | 12 | def initialize(name,env) 13 | @name=name 14 | @env=env 15 | 16 | @erb=true 17 | @file=nil 18 | @params=Hash.new 19 | @author="No author specified" 20 | @bootstrap=nil 21 | end 22 | 23 | def path 24 | File.join(@env.config.templates.path,@name) 25 | end 26 | 27 | def exists? 28 | File.directory?(self.path) 29 | end 30 | 31 | # Bindings in ERB http://www.stuartellis.eu/articles/erb/ 32 | # Links: 33 | # * Trimming whitespace in ERB 34 | # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/242656 35 | # * Appending to ERB output 36 | # http://blog.jayfields.com/2007/01/appending-to-erb-output-from-block.html 37 | def comment(flag) 38 | cur_pos=@output.length 39 | yield 40 | new_pos=@output.length 41 | if flag 42 | 43 | # Extraxt the block 44 | block_text=@output[cur_pos..new_pos] 45 | 46 | # Remove the block 47 | @output[cur_pos..new_pos]='' 48 | 49 | # Comment the block, with leading spaces into account 50 | block_text.gsub!(/^(\s)*/,'\1# ') 51 | 52 | # Re-insert the block 53 | @output=@output.insert cur_pos, block_text 54 | end 55 | 56 | end 57 | 58 | def to_s 59 | "Template #{name}" 60 | end 61 | 62 | def to_template(vm_name="noname") 63 | result="" 64 | filename=@file 65 | env.logger.info "Opening template file #{@file}" 66 | if File.exists?(filename) 67 | template=File.new(filename).read 68 | result=ERB.new(template,nil,"-","@output").result(binding) 69 | end 70 | return result 71 | end 72 | 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/mccloud/templates.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/template' 2 | 3 | module Mccloud 4 | class Templates < Hash 5 | attr_reader :env 6 | 7 | def initialize(env) 8 | @env=env 9 | end 10 | 11 | def load! 12 | if self.exists? 13 | Dir[File.join(self.path,"**")].each do |dir| 14 | template_name=File.basename(dir) 15 | t=Template.new(template_name,env) 16 | self[template_name]=t 17 | end 18 | else 19 | env.logger.info "Skipping loading of definitions as the definition_path does exist" 20 | end 21 | end 22 | 23 | def path 24 | @env.config.mccloud.template_path 25 | end 26 | 27 | def exists? 28 | File.directory?(self.path) 29 | end 30 | 31 | def registered?(name) 32 | return self.has_key?(name) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-centos-rubysource-1.8.7.sh: -------------------------------------------------------------------------------- 1 | #http://www.catapult-creative.com/2009/02/04/installing-rails-on-centos-5/ 2 | 3 | yum install -y httpd-devel openssl-devel zlib-devel gcc gcc-c++ curl-devel expat-devel gettext-devel 4 | 5 | mkdir /usr/local/src 6 | cd /usr/local/src 7 | curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz 8 | tar xzvf ruby-1.8.7-p72.tar.gz 9 | cd ruby-1.8.7-p72 10 | ./configure --enable-shared --enable-pthread 11 | make 12 | make install 13 | 14 | 15 | cd /usr/local/src 16 | wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz 17 | tar xzvf rubygems-1.3.5.tgz 18 | cd rubygems-1.3.5 19 | ruby setup.rb 20 | gem install rubygems-update 21 | update_rubygems 22 | 23 | 24 | gem install chef --no-ri --no-rdoc 25 | gem install puppet --no-ri --no-rdoc 26 | 27 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-centos-rvm-1.8.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | yum install -y bash curl git 4 | bash < <(curl -s -B https://rvm.beginrescueend.com/install/rvm) 5 | yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel lib 6 | yaml-devel libffi-devel openssl-devel 7 | source /usr/local/rvm/scripts/rvm 8 | rvm install ruby-1.8.7 9 | rvm use 1.8.7 --default 10 | 11 | gem install chef --no-ri --no-rdoc 12 | gem install puppet --no-ri --no-rdoc 13 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-centos-rvm-1.9.2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | yum install -y bash curl git 4 | bash < <(curl -s -B https://rvm.beginrescueend.com/install/rvm) 5 | yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel lib 6 | yaml-devel libffi-devel openssl-devel 7 | source /usr/local/rvm/scripts/rvm 8 | rvm install ruby-1.9.2 9 | rvm use 1.9.2 --default 10 | 11 | gem install chef --no-ri --no-rdoc 12 | gem install puppet --no-ri --no-rdoc 13 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-centos-rvm-ree-1.8.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | yum install -y bash curl git 4 | bash < <(curl -s -B https://rvm.beginrescueend.com/install/rvm) 5 | yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel lib 6 | yaml-devel libffi-devel openssl-devel 7 | source /usr/local/rvm/scripts/rvm 8 | rvm install ree-1.8.7 9 | rvm use ree-1.8.7 --default 10 | 11 | gem install chef --no-ri --no-rdoc 12 | gem install puppet --no-ri --no-rdoc 13 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-chef-omnibus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | # download omnibus install.sh 4 | if which curl 2>/dev/null; then 5 | curl -L https://www.opscode.com/chef/install.sh | sudo bash 6 | else 7 | wget -q -O - https://www.opscode.com/chef/install.sh | sudo bash 8 | fi 9 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-custom.sh: -------------------------------------------------------------------------------- 1 | # This is an empty bootstrap , ready for you to customize! -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-ubuntu-rvm-1.8.7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | apt-get update 4 | apt-get -y install libopenssl-ruby wget ssl-cert git-core 5 | apt-get -y install linux-headers-$(uname -r) build-essential 6 | apt-get -y install zlib1g-dev libssl-dev libreadline5-dev 7 | 8 | 9 | bash < <(curl -s -B https://rvm.beginrescueend.com/install/rvm) 10 | source /usr/local/rvm/scripts/rvm 11 | 12 | rvm install 1.8.7 13 | rvm use 1.8.7 --default 14 | 15 | gem install chef --no-ri --no-rdoc 16 | gem install puppet --no-ri --no-rdoc 17 | 18 | -------------------------------------------------------------------------------- /lib/mccloud/templates/bootstrap/bootstrap-ubuntu-system.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | apt-get update 4 | apt-get -y install ruby ruby-dev libopenssl-ruby rdoc ri irb build-essential wget ssl-cert 5 | cd /tmp 6 | test ! -f rubygems-1.3.7 && wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz 7 | test -f rubygems-1.3.7.tgz && tar zxf rubygems-1.3.7.tgz 8 | cd rubygems-1.3.7 && ruby setup.rb --no-format-executable 9 | gem install chef --no-ri --no-rdoc 10 | gem install puppet --no-ri --no-rdoc -------------------------------------------------------------------------------- /lib/mccloud/templates/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | mccloud: 3 | general: 4 | creating_home_dir: "Creating home directory since it doesn't exist: %{directory}" 5 | moving_home_dir: "Moving old Vagrant home directory to new location: %{directory}" 6 | home_dir_migration_failed: |- 7 | Both an old and new Vagrant home directory exist. Only the new one will 8 | be used. Please merge the old directory into the new directory if you'd 9 | like to use the old data as well. 10 | 11 | Old: %{old} 12 | New: %{new} 13 | 14 | #------------------------------------------------------------------------------- 15 | # Translations for exception classes 16 | #------------------------------------------------------------------------------- 17 | errors: 18 | base_vm_not_found: The base VM with the name '%{name}' was not found. 19 | box_not_found: Box '%{name}' could not be found. 20 | chef_not_detected: |- 21 | The chef (either `chef-solo` or `chef-client`) binary was not found on 22 | the VM and is required for chef provisioning. Please verify that chef 23 | is installed and that the binary is available on the PATH. 24 | 25 | 26 | #------------------------------------------------------------------------------- 27 | # Translations for config validation errors 28 | #------------------------------------------------------------------------------- 29 | config: 30 | 31 | -------------------------------------------------------------------------------- /lib/mccloud/templates/vm.erb: -------------------------------------------------------------------------------- 1 | Mccloud::Config.run do |config| 2 | config.vm.define "<%= @name %>" do |vm_config| 3 | 4 | # You can customize vm setting here if you want 5 | # to override the settings of a definition 6 | vm_config.vm.definition = "<%= @definition.name %>" 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/mccloud/ui.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | # Vagrant UIs handle communication with the outside world (typically 3 | # through a shell). They must respond to the typically logger methods 4 | # of `warn`, `error`, `info`, and `confirm`. 5 | class UI 6 | attr_accessor :env 7 | 8 | def initialize(env) 9 | @env = env 10 | end 11 | 12 | [:warn, :error, :info, :confirm].each do |method| 13 | define_method(method) do |message| 14 | # Log normal console messages 15 | env.logger.info("ui") { message } 16 | end 17 | end 18 | 19 | [:clear_line, :report_progress, :ask, :no?, :yes?].each do |method| 20 | # By default do nothing, these aren't logged 21 | define_method(method) { |*args| } 22 | end 23 | 24 | # A shell UI, which uses a `Thor::Shell` object to talk with 25 | # a terminal. 26 | class Shell < UI 27 | def initialize(env, shell) 28 | super(env) 29 | 30 | @shell = shell 31 | end 32 | 33 | [[:warn, :yellow], [:error, :red], [:info, nil], [:confirm, :green]].each do |method, color| 34 | class_eval <<-CODE 35 | def #{method}(message, opts=nil) 36 | super(message) 37 | opts ||= {} 38 | opts[:new_line] = true if !opts.has_key?(:new_line) 39 | @shell.say("\#{format_message(message, opts)}", #{color.inspect}, opts[:new_line]) 40 | end 41 | CODE 42 | end 43 | 44 | [:ask, :no?, :yes?].each do |method| 45 | class_eval <<-CODE 46 | def #{method}(message, opts=nil) 47 | super(message) 48 | opts ||= {} 49 | @shell.send(#{method.inspect}, format_message(message, opts), opts[:color]) 50 | end 51 | CODE 52 | end 53 | 54 | def report_progress(progress, total, show_parts=true) 55 | percent = (progress.to_f / total.to_f) * 100 56 | line = "Progress: #{percent.to_i}%" 57 | line << " (#{progress} / #{total})" if show_parts 58 | 59 | @shell.say(line, nil, false) 60 | end 61 | 62 | def clear_line 63 | @shell.say(line_reset, nil, false) 64 | end 65 | 66 | protected 67 | 68 | def format_message(message, opts=nil) 69 | opts = { :prefix => true }.merge(opts || {}) 70 | opts[:prefix]=false if env.resource=="mccloud" 71 | message = "[#{env.resource}] #{message}" if opts[:prefix] 72 | message 73 | end 74 | 75 | def line_reset 76 | reset = "\r" 77 | reset += "\e[0K" unless Util::Platform.windows? 78 | reset 79 | end 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /lib/mccloud/util/platform.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | 3 | #Shameless copy of Vagrant code 4 | module Mccloud 5 | module Util 6 | # This class just contains some platform checking code. 7 | class Platform 8 | class << self 9 | def tiger? 10 | platform.include?("darwin8") 11 | end 12 | 13 | def leopard? 14 | platform.include?("darwin9") 15 | end 16 | 17 | def windows? 18 | platform.include?("mswin") || platform.include?("mingw") 19 | end 20 | 21 | [:darwin, :bsd, :linux].each do |type| 22 | define_method("#{type}?") do 23 | platform.include?(type.to_s) 24 | end 25 | end 26 | 27 | def platform 28 | RbConfig::CONFIG["host_os"].downcase 29 | end 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/mccloud/util/rostruct.rb: -------------------------------------------------------------------------------- 1 | #http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/150311 2 | 3 | require 'ostruct' 4 | 5 | class ROpenStruct < OpenStruct 6 | def method_missing(mid, *args) 7 | mname = mid.id2name 8 | len = args.length 9 | if len == 0 10 | @table[mname.intern] = ROpenStruct.new 11 | self.new_ostruct_member(mname) 12 | @table[mname.intern] 13 | else 14 | super 15 | end 16 | end 17 | end 18 | 19 | test = ROpenStruct.new 20 | test.p = "hello" 21 | test.t.s.p.t.z.y.x = "hi" 22 | test.xyz 23 | 24 | p test -------------------------------------------------------------------------------- /lib/mccloud/util/sshkey.rb: -------------------------------------------------------------------------------- 1 | #Shameless copy of https://github.com/bensie/sshkey/raw/master/lib/sshkey.rb 2 | # Make it 1.8 compatbible 3 | 4 | require 'openssl' 5 | require 'base64' 6 | require 'digest/md5' 7 | 8 | module Mccloud 9 | module Util 10 | 11 | class SSHKey 12 | 13 | def self.generate(options = {}) 14 | SSHKey.new(OpenSSL::PKey::RSA.generate(2048).to_pem, options) 15 | end 16 | 17 | attr_reader :key_object, :comment, :rsa_private_key, :rsa_public_key, :ssh_public_key, :fingerprint 18 | 19 | def initialize(private_key, options = {}) 20 | @key_object = OpenSSL::PKey::RSA.new(private_key) 21 | 22 | @comment = options[:comment] || "" 23 | @rsa_private_key = @key_object.to_pem 24 | @rsa_public_key = @key_object.public_key.to_pem 25 | raw_ssh_public_key = ssh_public_key_conversion 26 | 27 | # @ssh_public_key = ["ssh-rsa", Base64.strict_encode64(raw_ssh_public_key), @comment].join(" ").strip 28 | 29 | @ssh_public_key = ["ssh-rsa", [raw_ssh_public_key].pack("m0").gsub(/\n/,''), @comment].join(" ").strip 30 | @fingerprint = Digest::MD5.hexdigest(raw_ssh_public_key).gsub(/(.{2})(?=.)/, '\1:\2') 31 | end 32 | 33 | private 34 | 35 | # All data type encoding is defined in the section #5 of RFC #4251. 36 | # String and mpint (multiple precision integer) types are encoded this way : 37 | # 4-bytes word: data length (unsigned big-endian 32 bits integer) 38 | # n bytes : binary representation of the data 39 | 40 | # For instance, the "stringsh-rsa" string is encoded as the following byte array 41 | # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a'] 42 | def ssh_public_key_conversion 43 | e = @key_object.public_key.e.to_i 44 | n = @key_object.public_key.n.to_i 45 | 46 | out = [0,0,0,7].pack("c*") 47 | out += "ssh-rsa" 48 | out += encode_unsigned_int_32(to_byte_array(e).length).pack("c*") 49 | out += to_byte_array(e).pack("c*") 50 | out += encode_unsigned_int_32(to_byte_array(n).length).pack("c*") 51 | out += to_byte_array(n).pack("c*") 52 | 53 | return out 54 | end 55 | 56 | def encode_unsigned_int_32(value) 57 | out = [] 58 | out[0] = value >> 24 & 0xff 59 | out[1] = value >> 16 & 0xff 60 | out[2] = value >> 8 & 0xff 61 | out[3] = value & 0xff 62 | return out 63 | end 64 | 65 | def to_byte_array(num) 66 | result = [] 67 | begin 68 | result << (num & 0xff) 69 | num >>= 8 70 | end until (num == 0 || num == -1) && (result.last[7] == num[7]) 71 | result.reverse 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/mccloud/version.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | end 3 | 4 | unless defined?(Mccloud::VERSION) 5 | ::Mccloud::VERSION = "0.1.1" 6 | end 7 | -------------------------------------------------------------------------------- /lib/mccloud/vm.rb: -------------------------------------------------------------------------------- 1 | module Mccloud 2 | 3 | class Vm 4 | 5 | attr_accessor :name 6 | attr_reader :env 7 | attr_accessor :definition 8 | 9 | def initialize(name,env) 10 | @name=name 11 | @env=env 12 | end 13 | 14 | def exists? 15 | File.exists?(self.path) 16 | end 17 | 18 | def path 19 | File.join(@env.config.mccloud.vm_path,@name+".rb") 20 | end 21 | 22 | def load! 23 | self.validate 24 | 25 | content=File.read(self.path) 26 | mccloud_configurator=env.config 27 | content.gsub!("Mccloud::Config.run","mccloud_configurator.define") 28 | 29 | begin 30 | env.config.instance_eval(content) 31 | rescue Error => ex 32 | raise ::Mccloud::Error, "Error reading vm from file #{definition_file}#{ex}" 33 | end 34 | end 35 | 36 | def create 37 | begin 38 | unless self.exists? 39 | File.open(self.path,'w'){ |f| f.write(self.to_template)} 40 | else 41 | raise ::Mccloud::Error, "VM file #{self.path} already exists" 42 | end 43 | rescue Error => ex 44 | raise ::Mccloud::Error, "Error writing vm file" 45 | end 46 | end 47 | 48 | def to_template 49 | result="" 50 | filename=File.expand_path(File.join(File.dirname(__FILE__),'templates','vm.erb')) 51 | env.logger.info "Opening vm template file #{@file}" 52 | template=File.new(filename).read 53 | result=ERB.new(template).result(binding) 54 | return result 55 | end 56 | 57 | def validate 58 | raise ::Mccloud::Error, "Vm #{@name} does not yet exist" unless self.exists? 59 | end 60 | end 61 | end 62 | 63 | -------------------------------------------------------------------------------- /lib/mccloud/vms.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud/vm' 2 | module Mccloud 3 | class Vms < Hash 4 | 5 | attr_reader :env 6 | 7 | def initialize(env) 8 | @env=env 9 | end 10 | 11 | def define(name,definitionname) 12 | # Check if definition exists 13 | unless env.config.definitions.registered?(definitionname) 14 | raise ::Mccloud::Error, "Definition #{definitionname} does not exist" 15 | end 16 | # Create the vms dir if needed 17 | unless self.exists? 18 | self.create 19 | end 20 | 21 | vm=::Mccloud::Vm.new(name,env) 22 | unless vm.exists? 23 | vm.definition=env.config.definitions[definitionname] 24 | vm.create 25 | end 26 | end 27 | 28 | def load! 29 | if self.exists? 30 | Dir[File.join(self.path,"**.rb")].each do |dir| 31 | name=File.basename(dir,'.rb') 32 | vm=::Mccloud::Vm.new(name,env) 33 | vm.load! 34 | end 35 | else 36 | env.logger.info "Skipping loading of vms as the vm_path does exist" 37 | end 38 | end 39 | 40 | def path 41 | @env.config.mccloud.vm_path 42 | end 43 | 44 | def exists? 45 | File.directory?(self.path) 46 | end 47 | 48 | def create 49 | begin 50 | unless self.exists? 51 | env.logger.info "Creating the vms directory #{self.path} as it doesn't exist yet" 52 | FileUtils.mkdir(self.path) 53 | end 54 | rescue Exception => ex 55 | raise ::Mccloud::Error, "Error creating vms directory #{self.path}: \n#{ex}" 56 | end 57 | end 58 | 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /mccloud.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path("../lib/mccloud/version", __FILE__) 3 | 4 | Gem::Specification.new do |s| 5 | s.name = "mccloud" 6 | s.version = Mccloud::VERSION 7 | s.platform = Gem::Platform::RUBY 8 | s.authors = ["Patrick Debois"] 9 | s.email = ["patrick.debois@jedi.be"] 10 | s.homepage = "http://github.com/jedi4ever/mccloud/" 11 | s.summary = %q{Cloud integration vagrant style} 12 | s.description = %q{Use the same simple commandline api to manage cloud interfaces} 13 | 14 | s.required_rubygems_version = ">= 1.3.6" 15 | s.rubyforge_project = "mccloud" 16 | 17 | s.add_dependency "net-ssh", ">= 2.2.2" 18 | #s.add_dependency "sshkey" 19 | s.add_dependency "net-scp" 20 | s.add_dependency "fog", "~> 1.38.0" 21 | #s.add_dependency "excon", "0.24.0" 22 | 23 | s.add_dependency "json" 24 | s.add_dependency "ansi" 25 | 26 | #s.add_dependency "templater" 27 | s.add_dependency "popen4", "~> 0.1.2" 28 | s.add_dependency "thor", ">= 0.14.6" 29 | s.add_dependency "highline", "~> 1.6.1" 30 | #s.add_dependency "progressbar" 31 | #s.add_development_dependency "cucumber", "0.8.5" 32 | 33 | 34 | s.add_dependency "net-ssh-multi" 35 | #s.add_dependency "rspec" 36 | 37 | s.add_development_dependency "bundler", ">= 1.0.0" 38 | s.add_development_dependency("ruby-libvirt","~>0.4.0") 39 | s.add_development_dependency("vagrant","~>0.8.1") 40 | s.add_development_dependency("rake","~>0.9") 41 | 42 | s.add_dependency "i18n" 43 | 44 | s.files = `git ls-files`.split("\n") 45 | s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact 46 | s.require_path = 'lib' 47 | end 48 | 49 | -------------------------------------------------------------------------------- /samples/bootstrap-ubuntu-system.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | apt-get update 4 | apt-get -y install ruby ruby-dev libopenssl-ruby rdoc ri irb build-essential wget ssl-cert 5 | cd /tmp 6 | test ! -f rubygems-1.3.7.tgz && wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz 7 | test -f rubygems-1.3.7.tgz && tar zxf rubygems-1.3.7.tgz 8 | 9 | gem --version |grep 1.3.7 | wc -l |grep 0 && cd rubygems-1.3.7 && ruby setup.rb --no-format-executable 10 | 11 | gem list chef|grep chef|wc -l | grep 0 && gem install chef --no-ri --no-rdoc 12 | gem list puppet|grep puppet|wc -l | grep 0 && gem install puppet --no-ri --no-rdoc 13 | 14 | useradd puppet 15 | 16 | echo "bootstrap finished" 17 | -------------------------------------------------------------------------------- /samples/stack_cloud.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion" : "2010-09-09", 3 | 4 | "Description": "Create a fully functioning stack installation." , 5 | "Parameters": { 6 | "InstanceType": { 7 | "Description": "Type of EC2 instance to launch", 8 | "Type": "String", 9 | "Default": "t1.micro" 10 | }, 11 | "WebServerPort": { 12 | "Description": "TCP/IP port fo the webserver", 13 | "Type": "String", 14 | "Default": "80" 15 | }, 16 | "KeyName": { 17 | "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances", 18 | "Type": "String" 19 | } 20 | }, 21 | 22 | "Mappings": { 23 | "AWSInstanceType2Arch": { 24 | "t1.micro" : { "Arch": "64" }, 25 | "m1.small" : { "Arch" : "32" }, 26 | "m1.large" : { "Arch" : "64" }, 27 | "m1.xlarge" : { "Arch" : "64" }, 28 | "m2.xlarge" : { "Arch" : "64" }, 29 | "m2.2xlarge" : { "Arch" : "64" }, 30 | "m2.4xlarge" : { "Arch" : "64" }, 31 | "c1.medium" : { "Arch" : "32" }, 32 | "c1.xlarge" : { "Arch" : "64" }, 33 | "cc1.4xlarge" : { "Arch" : "64" } 34 | }, 35 | "AWSRegionArch2AMI": { 36 | "us-east-1": { "32": "ami-3e02f257", "64": "ami-3202f25b" } 37 | } 38 | }, 39 | 40 | "Resources": { 41 | "webcf": { 42 | "Type": "AWS::EC2::Instance", 43 | "Properties": { 44 | "InstanceType": { "Ref": "InstanceType" }, 45 | "SecurityGroups": [ { "Ref": "patrickweb" }, "default" ], 46 | "KeyName": { "Ref": "KeyName" }, 47 | "Tags": [ { 48 | "Key": "Name", 49 | "Value": "drupal" 50 | } ], 51 | "ImageId": { "Fn::FindInMap" : [ 52 | "AWSRegionArch2AMI", { "Ref": "AWS::Region" }, 53 | { "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ] } 54 | ] } 55 | } 56 | }, 57 | 58 | "patrickweb": { 59 | "Type": "AWS::EC2::SecurityGroup", 60 | "Properties": { 61 | "GroupDescription": "Web security group, allows port 80 in", 62 | "SecurityGroupIngress": [ { 63 | "IpProtocol": "tcp", 64 | "FromPort": "22", 65 | "ToPort": "22", 66 | "CidrIp": "0.0.0.0/0" 67 | }, 68 | { 69 | "IpProtocol": "tcp", 70 | "FromPort": { "Ref": "WebServerPort" }, 71 | "ToPort": { "Ref": "WebServerPort" }, 72 | "CidrIp": "0.0.0.0/0" 73 | } ] 74 | } 75 | } 76 | }, 77 | 78 | "Outputs" : { 79 | "InstanceId" : { 80 | "Description" : "InstanceId of the newly created EC2 instance", 81 | "Value" : { "Ref" : "webcf" } 82 | }, 83 | "AZ" : { 84 | "Description" : "Availability Zone of the newly created EC2 instance", 85 | "Value" : { "Fn::GetAtt" : [ "webcf", "AvailabilityZone" ] } 86 | }, 87 | "PublicIP" : { 88 | "Description" : "Public IP address of the newly created EC2 instance", 89 | "Value" : { "Fn::GetAtt" : [ "webcf", "PublicIp" ] } 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /samples/stacks.txt: -------------------------------------------------------------------------------- 1 | * Mcollective stack - http://docs.puppetlabs.com/mcollective/ec2demo.html 2 | http://mcollective-101-demo.s3.amazonaws.com/cloudfront_demo.json 3 | 4 | * Drupal stack - http://bitnami.org/stack/drupal 5 | http://bitnami.org/cloudformation/drupal.template 6 | -------------------------------------------------------------------------------- /spec/commands/define_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'fileutils' 3 | require 'tempfile' 4 | 5 | describe "Define command" do 6 | 7 | before(:each) do 8 | @tempdir = Dir.mktmpdir 9 | end 10 | 11 | after(:each) do 12 | @env=nil 13 | FileUtils.remove_entry_secure @tempdir 14 | end 15 | 16 | context "Given a fresh mccloud project has been inited" do 17 | before do 18 | args=["init","bla"] 19 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 20 | ::Mccloud::CLI.start(args,:env => env) 21 | end 22 | 23 | describe "When I run mccloud define ubuntu ubuntu-10" do 24 | before do 25 | args=["define","ubuntu","ubuntu-10.10-server-amd64"] 26 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 27 | ::Mccloud::CLI.start(args,:env => env) 28 | end 29 | 30 | it "And the next time I load the environment it should have one definition" do 31 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 32 | env.config.templates.length.should > 0 33 | end 34 | 35 | it "It should have a new definition directory called ubuntu" do 36 | File.directory?(File.join(@tempdir,"definitions","ubuntu")).should be_true 37 | File.exists?(File.join(@tempdir,"definitions","ubuntu","mccloud.rb")).should be_true 38 | end 39 | 40 | 41 | it "And the next time I load the environment it should have one definition" do 42 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 43 | env.config.definitions.length.should == 1 44 | end 45 | 46 | it "And the default provider of the definition is aws-us-east" do 47 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 48 | env.config.definitions["ubuntu"].provider =~ /aws-us-east/ 49 | end 50 | end 51 | end 52 | 53 | context "Given a fresh mccloud project and 1 definition ubuntu" do 54 | before do 55 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 56 | args=["init","bla"] 57 | ::Mccloud::CLI.start(args,:env => env) 58 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 59 | args=["define","ubuntu",'ubuntu-10.10-server-amd64'] 60 | ::Mccloud::CLI.start(args,:env => env) 61 | end 62 | 63 | describe "When I run mccloud vm define ubuntu ubuntu" do 64 | 65 | before do 66 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 67 | args=["vm","define",'ubuntu','ubuntu'] 68 | ::Mccloud::CLI.start(args,:env => env) 69 | end 70 | 71 | it "It should have an ubuntu definition " do 72 | content=File.read(File.join(@tempdir,"definitions","ubuntu","mccloud.rb")) 73 | content.should =~ /ubuntu/ 74 | end 75 | 76 | it "It should have a new vms directory" do 77 | File.directory?(File.join(@tempdir,"vms")).should be_true 78 | end 79 | 80 | it "It should have a new vm file ubuntu.rb" do 81 | File.exists?(File.join(@tempdir,"vms","ubuntu.rb")).should be_true 82 | end 83 | 84 | it "It should have exactly one vm defined" do 85 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 86 | env.config.vms.length.should == 2 87 | end 88 | 89 | it "And the vm ubuntu should have username ubuntu" do 90 | env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => true) 91 | env.config.vms["ubuntu"].user.should == "ubuntu" 92 | end 93 | end 94 | end 95 | 96 | end 97 | -------------------------------------------------------------------------------- /spec/commands/init_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'fileutils' 3 | require 'tempfile' 4 | 5 | describe "Init command" do 6 | 7 | before(:each) do 8 | @tempdir = Dir.mktmpdir 9 | @env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 10 | end 11 | 12 | after(:each) do 13 | @env=nil 14 | FileUtils.remove_entry_secure @tempdir 15 | end 16 | 17 | it "When I run an mccloud init from an empty directory, it should create a new Mccloudfile" do 18 | args=["init"] 19 | ::Mccloud::CLI.start(args,:env => @env) 20 | File.exists?(File.join(@tempdir,"Mccloudfile")).should be_true 21 | end 22 | 23 | it "When I run an mccloud init in a directory that already has a Mccloudfile, it should error" do 24 | args=["init"] 25 | ::Mccloud::CLI.start(args,:env => @env) 26 | @env.ui.should_receive(:error).at_least(1).times.with(/already exists/) 27 | ::Mccloud::CLI.start(args,:env => @env) 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /spec/environment/environment_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'tempfile' 3 | 4 | describe "Mccloud environment" do 5 | it "With a cwd passed, and no mccloudfile in any parentdir, the default would be currentdir" do 6 | tempdir = Dir.mktmpdir 7 | begin 8 | env=Mccloud::Environment.new(:cwd => tempdir) 9 | Pathname(env.root_path).dirname.realpath.should == Pathname(tempdir).dirname.realpath 10 | ensure 11 | FileUtils.remove_entry_secure tempdir 12 | end 13 | end 14 | 15 | it "With a cwd passed, and a mccloudfile in it, the default would be currentdir" do 16 | tempdir = Dir.mktmpdir 17 | FileUtils.touch(File.join(tempdir,"Mccloudfile")) 18 | begin 19 | env=Mccloud::Environment.new(:cwd => tempdir) 20 | Pathname(env.root_path).dirname.realpath.should == Pathname(tempdir).dirname.realpath 21 | ensure 22 | FileUtils.remove_entry_secure tempdir 23 | end 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /spec/generator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'fileutils' 3 | require 'tempfile' 4 | require 'mccloud/generator' 5 | 6 | describe "Generator" do 7 | 8 | before(:each) do 9 | @tempdir = Dir.mktmpdir 10 | @env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 11 | @env.ssh_key_path=@tempdir 12 | end 13 | 14 | after(:each) do 15 | @env=nil 16 | FileUtils.remove_entry_secure @tempdir 17 | end 18 | 19 | it "When I specify an unknown provider it should generate an error" do 20 | expect { 21 | @env.generator.generate({:provider => :blabla}) 22 | }.to raise_error(::Mccloud::Error) 23 | end 24 | 25 | it "When I specify no provider it should default to aws" do 26 | @env.generator.generate() 27 | File.exists?(@env.mccloud_file).should be_true 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /spec/keypair_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'fileutils' 3 | require 'tempfile' 4 | require 'mccloud/keypair' 5 | 6 | describe "Keypair" do 7 | 8 | before(:each) do 9 | @tempdir = Dir.mktmpdir 10 | @env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 11 | @env.ssh_key_path=@tempdir 12 | end 13 | 14 | after(:each) do 15 | @env=nil 16 | FileUtils.remove_entry_secure @tempdir 17 | end 18 | 19 | it "When I generate a non-existing pair, the public and private key should be created" do 20 | k=::Mccloud::Keypair.new("mccloud",@env) 21 | k.generate 22 | File.exists?(File.join(@env.ssh_key_path,"mccloud_rsa.pub")).should == true 23 | File.exists?(File.join(@env.ssh_key_path,"mccloud_rsa")).should == true 24 | end 25 | 26 | it "When I generate a existing pair, there should be an error" do 27 | k=::Mccloud::Keypair.new("mccloud",@env) 28 | k.generate 29 | expect { k.generate }.to raise_error(Mccloud::Error) 30 | end 31 | 32 | it "When I generate a existing pair,and I force the creation there should be no error" do 33 | k=::Mccloud::Keypair.new("mccloud",@env) 34 | k.generate 35 | expect { k.generate({:force => true}) }.to_not raise_error(Mccloud::Error) 36 | end 37 | 38 | end 39 | -------------------------------------------------------------------------------- /spec/provider/aws/credentials_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'fileutils' 3 | require 'tempfile' 4 | require 'mccloud/provider/aws/provider' 5 | 6 | describe "AWS provider" do 7 | 8 | before(:each) do 9 | @tempdir = Dir.mktmpdir 10 | @env=Mccloud::Environment.new(:cwd => @tempdir,:autoload => false) 11 | end 12 | 13 | after(:each) do 14 | @env=nil 15 | FileUtils.remove_entry_secure @tempdir 16 | end 17 | 18 | it "When there are no credentials, accessing the raw provider should be missing credentials" do 19 | p=::Mccloud::Provider::Aws::Provider.new("aws-bla",{},@env) 20 | p.credentials_path=File.join(@tempdir,".fog") 21 | expect { 22 | raw=p.raw 23 | }.to raise_error(Mccloud::Error) 24 | end 25 | 26 | it "When there are credentials, accessing the raw provider should be ok" do 27 | p=::Mccloud::Provider::Aws::Provider.new("aws-bla",{},@env) 28 | credentials={:default => {:aws_access_key_id => "1223454", 29 | :aws_secret_access_key => "123456"}} 30 | p.credentials_path=File.join(@tempdir,".fog") 31 | File.open(p.credentials_path,'w') {|f| f.write(credentials.to_yaml)} 32 | expect { 33 | raw=p.raw 34 | }.to_not raise_error(Mccloud::Error) 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /spec/provisioner/puppet/Mccloud-puppet-test: -------------------------------------------------------------------------------- 1 | Mccloud::Config.run do |config| 2 | config.provider.define "aws-us-east" do |provider_config| 3 | provider_config.provider.flavor = :aws 4 | provider_config.provider.check_keypairs = false 5 | provider_config.provider.check_security_groups = true 6 | end 7 | 8 | config.keypair.define "mccloud" do |key_config| 9 | key_config.keypair.public_key_path = "#{File.join(ENV['HOME'],'.ssh','mccloud_rsa.pub')}" 10 | key_config.keypair.private_key_path = "#{File.join(ENV['HOME'],'.ssh','mccloud_rsa')}" 11 | end 12 | 13 | config.keystore.define "aws-us-east-key-store" do |keystore_config| 14 | keystore_config.keystore.provider = "aws-us-east" 15 | keystore_config.keystore.keypairs = [ 16 | { :name => "mccloud-key", :keypair => "mccloud"} ] 17 | end 18 | 19 | config.vm.define "puppet" do |vm_config| 20 | vm_config.vm.provider = "aws-us-east" 21 | vm_config.vm.key_name = "mccloud-key" 22 | 23 | vm_config.vm.security_groups = [ "mccloud"] 24 | 25 | vm_config.vm.provision :puppet do |puppet| 26 | puppet.manifest_file = "aws-demo1.pp" 27 | # puppet.manifest_path = "manifests" 28 | puppet.module_path = ["modules"] 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/provisioner/puppet/puppet_spec.rb: -------------------------------------------------------------------------------- 1 | require 'mccloud' 2 | require 'mccloud/provisioner/puppet' 3 | require 'tempfile' 4 | 5 | # Without a cwd passed, and no mccloudfile in any parentdir 6 | # The default would be currentdir "." 7 | #describe ::Mccloud::Provisioner::Puppet, "#apply" do 8 | describe "Provisioner puppet" do 9 | def default_config(env) 10 | # Dynamically creating the vm 11 | # @env.load! 12 | env.config.define do |config| 13 | config.provider.define "aws-us-east" do |provider_config| 14 | provider_config.provider.flavor = :aws 15 | provider_config.provider.region = "us-east-1" 16 | provider_config.provider.credentials_path=File.join(@tempdir,".fog") 17 | end 18 | 19 | config.keypair.define "mccloud" do |key_config| 20 | key_config.keypair.public_key_path = "#{File.join(ENV['HOME'],'.ssh','mccloud_rsa.pub')}" 21 | key_config.keypair.private_key_path = "#{File.join(ENV['HOME'],'.ssh','mccloud_rsa')}" 22 | end 23 | 24 | config.keystore.define "aws-us-east-key-store" do |keystore_config| 25 | keystore_config.keystore.provider = "aws-us-east" 26 | keystore_config.keystore.keypairs = [ 27 | { :name => "mccloud", :keypair => "mccloud"}, 28 | ] 29 | end 30 | 31 | end 32 | end 33 | 34 | def fake_credentials(env) 35 | credentials={:default => {:aws_access_key_id => "1234567", 36 | :aws_secret_access_key => "1234567"}} 37 | File.open(File.join(@tempdir,".fog"),'w') { |f| f.write(credentials.to_yaml)} 38 | end 39 | 40 | def default_puppet(env) 41 | env.config.define do |config| 42 | config.vm.define "puppet" do |vm_config| 43 | vm_config.vm.provider = "aws-us-east" 44 | vm_config.vm.provision :puppet do |puppet| 45 | puppet.module_path = ["modules"] 46 | end 47 | end 48 | end 49 | end 50 | 51 | before(:each) do 52 | @tempdir=Dir.mktmpdir 53 | @env=Mccloud::Environment.new( 54 | :cwd => File.dirname(__FILE__), 55 | :autoload => false 56 | ) 57 | 58 | fake_credentials(@env) 59 | default_config(@env) 60 | default_puppet(@env) 61 | 62 | # Fog will get loaded because of aws 63 | Fog.mock! 64 | #@env.config.providers["aws-us-east"].keystore_sync 65 | 66 | @vm=@env.config.vms["puppet"] 67 | ::Mccloud::Util::Ssh.stub(:execute_when_tcp_available).and_return(true) 68 | @vm.stub!(:share_folder).and_return(nil) 69 | @vm.stub!(:transfer).and_return(nil) 70 | @vm.stub!(:execute).and_return(nil) 71 | @vm.stub!(:sudo).and_return(nil) 72 | end 73 | 74 | after(:each) do 75 | Fog::Mock.reset 76 | FileUtils.remove_entry_secure @tempdir 77 | @env=nil 78 | @vm=nil 79 | end 80 | 81 | it "When the machine is up, and no manifest is specified puppet should not run" do 82 | expect { 83 | @vm.up 84 | @vm._provision 85 | }.should raise_error 86 | end 87 | 88 | it "When the machine is up, puppet should run fine and has a valid manifest" do 89 | @vm.provisioner.manifest_file="bla.sh" 90 | @vm.up 91 | @vm.should_receive(:share_folder).at_least(1).times 92 | @vm.should_receive(:sudo).at_least(1).times.with(/puppet apply/) 93 | @vm._provision 94 | end 95 | 96 | it "When the machine is down, running the provision should throw an error" do 97 | expect { 98 | @vm._provision 99 | }.should raise_error 100 | end 101 | 102 | it "When 1 module path and 1 manifest path are given, it should share 2 folders" do 103 | @vm.provisioners.first.manifest_file="bla.sh" 104 | @vm.up 105 | # We need to count from here as 'upi', also does a provision on first run 106 | @vm.should_receive(:share_folder).exactly(2).times 107 | @vm._provision 108 | end 109 | 110 | end 111 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedi4ever/mccloud/5d1995e50ac558e23feb94b87dcb018878a9b501/spec/spec_helper.rb -------------------------------------------------------------------------------- /templates/ubuntu-10.10-server-amd64/aws.json: -------------------------------------------------------------------------------- 1 | { 2 | "amis" => { "aws_us-east_us-east-1a_t1.micro": { :ami => "ami-cef405a7" , :user => "ubuntu", :bootstrap => [ "bootstrap.sh"]} } 3 | } 4 | -------------------------------------------------------------------------------- /templates/ubuntu-10.10-server-amd64/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | apt-get update 4 | apt-get -y install ruby ruby-dev libopenssl-ruby rdoc ri irb build-essential wget ssl-cert 5 | cd /tmp 6 | test ! -f rubygems-1.3.7.tgz && wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz 7 | test -f rubygems-1.3.7.tgz && tar zxf rubygems-1.3.7.tgz 8 | 9 | gem --version |grep 1.3.7 | wc -l |grep 0 && cd rubygems-1.3.7 && ruby setup.rb --no-format-executable 10 | 11 | gem list chef|grep chef|wc -l | grep 0 && gem install chef --no-ri --no-rdoc 12 | gem list puppet|grep puppet|wc -l | grep 0 && gem install puppet --no-ri --no-rdoc 13 | 14 | useradd puppet 15 | 16 | echo "bootstrap finished" 17 | -------------------------------------------------------------------------------- /templates/ubuntu-10.10-server-amd64/definition.old: -------------------------------------------------------------------------------- 1 | # Canonical 2 | # http://uec-images.ubuntu.com/releases/10.04/release/ 3 | # http://jonathanhui.com/create-and-launch-amazon-ec2-instance-ubuntu-and-centos 4 | 5 | aws_templates=[ 6 | { :name => "aws-us-east::ubuntu-10.10-64", 7 | :description => "Ubuntu 10.10 - Maverick 64-bit (Canonical/EBS)", 8 | :provider => "aws-us-east", 9 | :ami => "ami-cef405a7", :user => "ubuntu" ,:arch => "64", 10 | :zone => "us-east-1a", 11 | :bootstrap => [ "bootstrap-ubunty.sh"]}, 12 | { :name => "aws-us-east::ubuntu-10.10-32", 13 | :description => "Ubuntu 10.10 - Maverick 32-bit (Canonical/EBS)", 14 | :ami => "ami-ccf405a5", :user => "ubuntu" ,:arch => "32", 15 | :provider => "aws-us-east", 16 | :zone => "us-east-1a", 17 | :bootstrap => ""}, 18 | { :name => "aws-us-east::ubuntu-10.04-64", 19 | :description => "Ubuntu 10.04 - Lucid 64-bit (Canonical/EBS)", 20 | :ami => "ami-3202f25b", :user => "ubuntu" ,:arch => "64", 21 | :provider => "aws-us-east", 22 | :zone => "us-east-1a", 23 | :bootstrap => "" }, 24 | { :name => "aws-us-east::ubuntu-10.04-32", 25 | :description => "Ubuntu 10.04 - Lucid 32-bit (Canonical/EBS)", 26 | :ami => "ami-3e02f257", :user => "ubuntu" ,:arch => "32", 27 | :provider => "aws-us-east", 28 | :zone => "us-east-1a", 29 | :bootstrap => "" }, 30 | { :name => "aws-us-east::centos-5.4-64", 31 | :description => "Centos 5.4 - 64-bit (Rightscale/EBS)", 32 | :ami => "ami-4d42a924", :user => "root" ,:arch => "64", 33 | :provider => "aws-us-east", 34 | :zone => "us-east-1a", 35 | :bootstrap => "" }, 36 | { :name => "aws-us-east::centos-5.4-32", 37 | :description => "Centos 5.4 - 32-bit (Rightscale/EBS)", 38 | :ami => "ami-2342a94a", :user => "root" ,:arch => "32", 39 | :provider => "aws-us-east", 40 | :zone => "us-east-1a", 41 | :bootstrap => "" } 42 | ] 43 | 44 | aws_templates.each do |template| 45 | config.template.define "#{template[:name]}" do |template_config| 46 | template_config.template.name=template[:name] 47 | template_config.template.params=template 48 | template_config.template.file=File.join(".","aws.erb") 49 | template_config.template.bootstrap="#{template[:bootstrap]}" 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /templates/ubuntu-10.10-server-amd64/mccloud.erb: -------------------------------------------------------------------------------- 1 | Mccloud::Config.run do |config| 2 | config.definition.define "ubuntu" do |d_config| 3 | d_config.definition.provider = "aws-us-east" 4 | d_config.definition.user = "ubuntu" 5 | end 6 | end 7 | --------------------------------------------------------------------------------