Added puppet faces for azure cloud

This commit is contained in:
Ranjan Kumar 2013-09-12 10:15:16 +05:30
Коммит bec50221dc
20 изменённых файлов: 1332 добавлений и 0 удалений

5
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
tmp/
.DS_Store
.bundle/
vendor/
Gemfile.lock

Просмотреть файл

@ -0,0 +1,18 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/application/face_base'
class Puppet::Application::NodeAzure < Puppet::Application::FaceBase
end

Просмотреть файл

@ -0,0 +1,379 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'rubygems'
require 'net/ssh'
require 'tilt'
require 'highline/import'
module Puppet::CloudAzurePack
class << self
def initialize_env_variable(options)
ENV['azure_publish_settings_file'.upcase] = options[:publish_settings_file]
ENV['azure_subscription_id'.upcase] = options[:azure_subscription_id]
ENV['azure_api_url'.upcase] = options[:api_url]
require 'azure'
end
def views(name)
File.join(File.dirname(__FILE__), 'face/node_azure/views', name)
end
def merge_default_options(options)
default_options = { "publish-settings-file" => true }
default_options.merge(options)
end
def add_default_options(action)
add_api_url_option(action)
add_publish_settings_file_option(action)
add_subscription_id_option(action)
end
def add_shutdown_options(action)
add_deployment_options(action)
add_vm_name_option(action,false)
end
def add_delete_options(action)
add_default_options(action)
add_vm_name_option(action,false)
add_cloud_service_name_option(action,false)
end
def add_deployment_options(action)
add_default_options(action)
add_cloud_service_name_option(action,false)
end
def add_bootstrap_options(action)
add_publish_settings_file_option(action)
add_subscription_id_option(action)
add_vm_user_option(action,false)
add_node_ipaddress_options(action,false)
add_password_option(action)
add_puppet_master_ip_option(action,false)
add_ssh_port_option(action)
add_certificate_file_option(action)
add_private_key_file_option(action)
end
def add_create_options(action)
add_default_options(action)
add_image_option(action)
add_vm_name_option(action, false)
add_storage_account_option(action)
add_cloud_service_name_option(action)
add_deployment_name_option(action)
add_vm_user_option(action)
add_password_option(action)
add_puppet_master_ip_option(action)
add_end_points_option(action)
add_location_option(action)
add_vm_size_option(action)
add_ssh_port_option(action)
add_certificate_file_option(action)
add_private_key_file_option(action)
add_winrm_transport_option(action)
end
def add_location_option(action)
action.option '--location=' do
summary "The location identifier for the Windows Azure portal.valid choices are ('West US', 'East US', 'East Asia', 'Southeast Asia','North Europe', 'West Europe')."
description <<-EOT
The location identifier for the Windows Azure portal.
valid choices are ('West US', 'East US', 'East Asia', 'Southeast Asia',
'North Europe', 'West Europe').
EOT
required
before_action do |action, args, options|
valid_locations = ['west us', 'east us', 'east asia', 'southeast asia', 'north europe', 'west europe']
if options[:location].empty?
raise ArgumentError, "Location is required"
elsif options[:location] && !valid_locations.include?(options[:location].downcase)
raise ArgumentError, "The location is not valid. .valid choices are ('West US', 'East US', 'East Asia', 'Southeast Asia','North Europe', 'West Europe')."
end
end
end
end
def add_publish_settings_file_option(action)
action.option '--publish-settings-file=' do
summary 'The subscription identifier for the Windows Azure portal.'
description <<-EOT
The subscription identifier for the Windows Azure portal.
EOT
required
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:publish_settings_file].empty?
raise ArgumentError, "Publish Settings File Id is required"
end
unless test 'f', options[:publish_settings_file]
raise ArgumentError, "Could not find file '#{options[:publish_settings_file]}'"
end
unless test 'r', options[:publish_settings_file]
raise ArgumentError, "Could not read from file '#{options[:publish_settings_file]}'"
end
end
end
end
def add_vm_name_option(action,optional=true)
action.option '--vm-name=' do
summary 'The name of the virtual machine.'
description <<-EOT
The name of the virtual machine.
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:vm_name].empty?
raise ArgumentError, "VM Name is required."
end
end
end
end
def add_image_option(action)
action.option '--image=' do
summary 'The name of the disk image that will be used to create the virtual machine'
description <<-EOT
The name of the disk image that will be used to create the virtual machine
EOT
required
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:image].empty?
raise ArgumentError, "Source image name is required"
else
Puppet::CloudAzurePack.initialize_env_variable(options)
image_service = Azure::VirtualMachineImageService.new
os_image = image_service.list_virtual_machine_images.select{|x| x.name == options[:image]}.first
raise ArgumentError, "Source image name is invalid" unless os_image
@os_type = os_image.os_type
end
end
end
end
def add_subscription_id_option(action)
action.option '--azure-subscription-id=' do
summary 'The subscription identifier for the Windows Azure portal.'
description <<-EOT
The subscription identifier for the Windows Azure portal.
EOT
end
end
def add_storage_account_option(action)
action.option '--storage-account-name=' do
summary 'The name of the storage account used with the cloud service.'
description <<-EOT
The name of the storage account used with the cloud service
EOT
end
end
def add_cloud_service_name_option(action,optional=true)
action.option '--cloud-service-name=' do
summary 'The name of the cloud service.'
description <<-EOT
The name of the cloud service.
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:cloud_service_name].empty?
raise ArgumentError, "Cloud service name is required."
end
end
end
end
def add_vm_user_option(action,optional=true)
action.option '--vm-user=' do
summary 'The VM user name.'
description <<-EOT
The VM user name. It mandatory incase of liunx VM installation.
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:vm_user].empty?
raise ArgumentError, "The VM user name is required."
end
end
end
end
def add_puppet_master_ip_option(action,optional=true)
action.option '--puppet-master-ip=' do
summary 'The puppet master ip address.'
description <<-EOT
The puppet master ip address. It mandatory incase of puppet node installation.
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:puppet_master_ip].empty?
raise ArgumentError, "The pupet master ip address is required."
end
end
end
end
def add_deployment_name_option(action,optional=true)
action.option '--deployment-name=' do
summary 'The vm instance deployment name.'
description <<-EOT
The vm instance deployment name.
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:deployment_name].empty?
raise ArgumentError, "Deployment name is required."
end
end
end
end
def add_password_option(action)
action.option '--password=' do
summary 'Authentication password for vm.'
description <<-EOT
Authentication password for vm.
EOT
required if @os_type == 'Windows'
before_action do |action, args, options|
if options[:password].empty?
raise ArgumentError, "The password is required."
end
end
end
end
def add_end_points_option(action)
action.option '--tcp-endpoints=' do
summary 'Tcp End Points. '
description <<-EOT
Add Tcp end points. example --tcp-endpoints="80,3889:3889"
EOT
end
end
def add_node_ipaddress_options(action,optional=true)
action.option '--node-ipaddress=' do
summary 'Node Ip address. '
description <<-EOT
The ip address where puppet need to install."
EOT
required unless optional
before_action do |action, args, options|
options = Puppet::CloudAzurePack.merge_default_options(options)
if options[:node_ipaddress].empty?
raise ArgumentError, "The Node ip address is require."
end
end
end
end
def add_api_url_option(action)
action.option '--api-url=' do
summary 'Windows Azure API url.'
description <<-EOT
Windows Azure API url.
EOT
end
end
def add_certificate_file_option(action)
action.option '--certificate-file=' do
summary "Authentication using certificate instead of password."
description <<-EOT
Authentication using certificate instead of password.
EOT
before_action do |action, args, options|
unless test 'f', options[:certificate_file]
raise ArgumentError, "Could not find file '#{options[:certificate_file]}'"
end
unless test 'r', options[:certificate_file]
raise ArgumentError, "Could not read from file '#{options[:certificate_file]}'"
end
end
end
end
def add_private_key_file_option(action)
action.option '--private-key-file=' do
summary "Authentication using certificate instead of password."
description <<-EOT
Authentication using certificate instead of password..
EOT
before_action do |action, args, options|
unless test 'f', options[:private_key_file]
raise ArgumentError, "Could not find file '#{options[:private_key_file]}'"
end
unless test 'r', options[:private_key_file]
raise ArgumentError, "Could not read from file '#{options[:private_key_file]}'"
end
end
end
end
def add_winrm_transport_option(action)
action.option '--winrm-transport=' do
summary "Winrm authentication protocol. Valid choices are http or https or http,https"
description <<-EOT
Winrm authentication protocol. Valid choices are http or https or http,https.
EOT
before_action do |action, args, options|
winrm_transport = options[:winrm_transport].split(",")
unless (!winrm_transport.nil? && (winrm_transport.select{|x| x.downcase == 'http' or x.downcase == 'https'}.size > 0))
raise ArgumentError, "The winrm transport is not valid. Valid choices are http or https or http,https"
end
options[:winrm_transport] = winrm_transport
end
end
end
def add_ssh_port_option(action)
action.option '--ssh-port=' do
summary 'Port for ssh server.'
description <<-EOT
Port for ssh server.
EOT
end
end
def add_vm_size_option(action)
action.option '--vm-size=' do
summary 'The instance size. valid choice are ExtraSmall, Small, Medium, Large, ExtraLarge'
description <<-EOT
The instance size. valid choice are ExtraSmall, Small, Medium, Large, ExtraLarge
EOT
before_action do |action, args, options|
valid_role_sizes = ['ExtraSmall', 'Small', 'Medium', 'Large', 'ExtraLarge', 'A6', 'A7']
if options[:vm_size] && !valid_role_sizes.include?(options[:vm_size])
raise ArgumentError, "The vm-size is not valid. Valid choices are valid choice are ExtraSmall, Small, Medium, Large, ExtraLarge"
end
end
end
end
end
end

Просмотреть файл

@ -0,0 +1,66 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/core/remote_connection'
require 'puppet/core/utility'
require 'puppet/cloudpack/installer'
require 'tempfile'
include Puppet::Core::RemoteConnection
include Puppet::Core::Utility
module Puppet
module CloudPack
module BootStrap
class << self
def start(params)
puts "Installing puppet node on #{params[:node_ipaddress]}\n"
puts
login = params[:vm_user]
ssh_opts = { }
ssh_opts[:password] = params[:password]
ssh_opts[:paranoid] = false
ssh_opts[:port] = params[:ssh_port] || 22
options = {:environment=>'production',:puppet_master_ip => params[:puppet_master_ip]}
options[:tmp_dir] = File.join('/', 'tmp', random_string('puppet-tmp-location-',10))
create_tmpdir_cmd = "bash -c 'umask 077; mkdir #{options[:tmp_dir]}'"
ssh_remote_execute(params[:node_ipaddress], login, ssh_opts, create_tmpdir_cmd)
tmp_script_file = compile_template(options)
remote_script_path = File.join(options[:tmp_dir], "puppet_installation_script.sh")
scp_remote_upload(params[:node_ipaddress], login, ssh_opts, tmp_script_file.path, remote_script_path)
cmd_prefix = login == 'root' ? '' : 'sudo '
install_command = "#{cmd_prefix}bash -c 'chmod u+x #{remote_script_path}; sed -i 's/\r//' #{remote_script_path}; #{remote_script_path}'"
results = ssh_remote_execute(params[:node_ipaddress], login, ssh_opts, install_command)
if results[:exit_code] != 0 then
raise "The installation script exited with a non-zero exit status, indicating a failure. It may help to run with --debug to see the script execution or to check the installation log file on the remote system in #{options[:tmp_dir]}.".inspect
end
end
def compile_template(options)
puts "Installing Puppet ..."
install_script = Installer.build_installer_template('puppet-community', options)
puts("Compiled installation script:")
begin
f = Tempfile.open('install_script')
f.write(install_script)
f
rescue Exception => e
puts e
ensure
f.close
end
end
end
end
end
end

Просмотреть файл

@ -0,0 +1,45 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'erb'
module Puppet
module CloudPack
module Installer
class << self
def build_installer_template(name, options = {})
# binding is a kernel method
ERB.new(File.read(find_template(name))).result(binding)
end
def lib_script_dir
File.join(File.dirname(__FILE__), 'scripts')
end
def find_template(name)
user_script = File.expand_path("../#{name}.erb", __FILE__)
puts user_script
return user_script if File.exists?(user_script)
lib_script = File.join(lib_script_dir, "#{name}.erb")
if File.exists?(lib_script)
lib_script
else
raise "Could not find installation template for #{name}"
end
end
end
end
end
end

Просмотреть файл

@ -0,0 +1,147 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
#!/bin/bash
# This script is intended to be used with the install puppet-client
set -u
#set -e
function rpm_install(){
# Setup the yum Puppet repository
cat >/etc/yum.repos.d/puppet.repo <<'EOFYUMREPO'
[puppetlabs]
name = Puppetlbas
baseurl = http://yum.puppetlabs.com/el/$releasever/products/$basearch/
gpgcheck = 1
enabled = 1
gpgkey = http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
EOFYUMREPO
# Install Puppet from yum.puppetlabs.com
rpm -Uvh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-6.noarch.rpm
yum install -y puppet
}
function suse_install(){
zypper ar --refresh http://download.opensuse.org/repositories/home:/eclipseagent:/puppet/SLE_11/ repo-puppet
zypper --non-interactive --gpg-auto-import-keys ref
zypper install -y puppet
}
function apt_install() {
# Download and install the puppetlabs apt public
apt-key adv --recv-key --keyserver pool.sks-keyservers.net 4BD6EC30
# We need to grab the distro and release in order to populate
# the apt repo details. We are assuming that the lsb_release command
# will be available as even puppet evens has it (lsb_base) package as
# dependancy.
# Since puppet requires lsb-release I believe this is ok to use for
# the purpose of distro and release discovery.
apt-get update
apt-get -y install lsb-release
release=$(lsb_release -c | cut -f 2)
# Setup the apt Puppet repository
cat > /etc/apt/sources.list.d/puppetlabs.list <<EOFAPTREPO
deb http://apt.puppetlabs.com/ ${release} main dependencies
EOFAPTREPO
apt-get update
# Install Puppet from Debian repositories
apt-get -y install puppet
}
function install_puppet() {
case ${breed} in
"redhat")
rpm_install ;;
"debian")
apt_install ;;
"suse")
suse_install ;;
esac
}
function configure_puppet() {
cat >/etc/puppet/puppet.conf <<'EOFPUPPETCONF'
[main]
logdir = /var/log/puppet
rundir = /var/run/puppet
vardir = /var/lib/puppet
ssldir = $vardir/ssl
pluginsync = true
report = true
runinterval = 120
server = puppet
environment = <%= options[:environment] %>
<% if options[:puppetagent_certname] %>
certname = <%= options[:puppetagent_certname] %>
<% end %>
EOFPUPPETCONF
if [ -f /etc/default/puppet ]; then
cat > /etc/default/puppet <<EOFPUPPETDEFAULT
# Defaults for puppet - sourced by /etc/init.d/puppet
# Start puppet on boot?
START=yes
# Startup options
DAEMON_OPTS=""
EOFPUPPETDEFAULT
fi
}
function start_puppet() {
/etc/init.d/puppet restart
}
function update_hosts(){
#Remove lines which contain puppet keyword in hosts file.
sed --in-place '/puppet/d' /etc/hosts
host=<%= options[:puppet_master_ip] %>
if ( echo "$host" | egrep -q "[a-zA-Z]" ); then
IP=$(host "$host" | grep "has address" | head -1 | awk '{print $NF}')
else
IP="$host"
fi
echo "$IP puppet" >> /etc/hosts
echo 'DNS or host is added in /etc/hosts'
}
function provision_puppet() {
if [ -f /etc/redhat-release ]; then
export breed='redhat'
elif [ -f /etc/debian_version ]; then
export breed='debian'
elif [ -f /etc/SuSE-release ]; then
export breed='suse'
else
echo "This OS is not supported by Puppet Cloud Provisioner"
exit 1
fi
install_puppet
configure_puppet
update_hosts
start_puppet
echo "Puppet installation finished!"
exit 0
}
provision_puppet

Просмотреть файл

@ -0,0 +1,100 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'rubygems'
require 'net/ssh'
require 'net/scp'
module Puppet
module Core
module RemoteConnection
def scp_remote_upload(server, login, ssh_opts, local_path,remote_path)
begin
Net::SCP.start(server, login, ssh_opts) do |scp|
scp.upload! local_path, remote_path
end
rescue Net::SSH::HostKeyMismatch => e
puts "remembering new key: #{e.fingerprint}"
e.remember_host!
retry
rescue Net::SSH::AuthenticationFailed => user
raise "Authentication failure for user #{user}.".inspect
rescue Exception => e
raise e.message.inspect
end
end
def ssh_remote_execute(server, login, ssh_opts, command, keyfile = nil)
puts "Executing remote command ..."
puts "Command: #{command}"
buffer = String.new
stdout = String.new
exit_code = nil
begin
Net::SSH.start(server, login, ssh_opts) do |session|
session.open_channel do |channel|
channel.request_pty do |c, success|
raise "could not request pty" unless success
channel.on_data do |ch, data|
if data =~ /\[sudo\]/ || data =~ /Password/i
channel.send_data "#{ssh_opts[:password]}\n"
end
buffer << data
stdout << data
if buffer =~ /\n/
lines = buffer.split("\n")
buffer = lines.length > 1 ? lines.pop : String.new
lines.each do |line|
puts line
end
end
end
channel.on_eof do |ch|
# Display anything remaining in the buffer
unless buffer.empty?
puts buffer
end
end
channel.on_request("exit-status") do |ch, data|
exit_code = data.read_long
puts "SSH Command Exit Code: #{exit_code}"
end
# Finally execute the command
channel.exec(command)
end
end
session.loop
end
rescue Net::SSH::HostKeyMismatch => e
puts "remembering new key: #{e.fingerprint}"
e.remember_host!
retry
rescue Net::SSH::AuthenticationFailed => user
raise "Authentication failure for user #{user}.".inspect
rescue Exception => e
puts e.message
end
puts "Executing remote command ... Done"
{ :exit_code => exit_code, :stdout => stdout }
end
end
end
end

128
lib/puppet/core/utility.rb Normal file
Просмотреть файл

@ -0,0 +1,128 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
module Puppet
module Core
module Utility
def random_string(str='azure',no_of_char=5)
str+(0...no_of_char).map{ ('a'..'z').to_a[rand(26)] }.join
end
def ask_for_password(options, os_type)
regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}/
password = options[:password]
return options if !password.nil? && !password.match(regex).nil?
password_required = 'y'
if (options[:private_key_file] && options[:certificate_file] && os_type == 'Linux')
password_required = ask("\nDo you want to enable password authentication (y/n)? ") {
|pass| pass.validate = /^y{1}$|^n{1}$/
}
end
if password_required == 'y' or os_type == 'Windows'
puts "The supplied password must be 6-72 characters long and meet password complexity requirements."
puts "Require atleast 1 captial letter and digit."
options[:password] = ask("\nPASSWORD? ") { |pass| pass.echo ="*"; pass.validate = regex }
end
options
end
def test_tcp_connection(server)
unless (server && server.ipaddress)
Loggerx.error_with_exit("Instance is not running.")
exit 1
end
puts("\n")
if server.os_type == 'Linux'
ip = server.ipaddress
port = server.tcp_endpoints.collect{|x| x["PublicPort"] if x["Name"] == 'SSH'}.compact.first
Loggerx.info "Waiting for sshd on #{ip}:#{port}"
print("# ") until tcp_test_ssh(ip,port) {
sleep 10
Loggerx.info "done"
}
elsif server.os_type == 'Windows'
ip = server.ipaddress
port = 5985
Loggerx.info "Waiting for winrm on #{ip}:#{port}"
print("# ") until tcp_test_winrm(ip,port) {
sleep 10
Loggerx.success("done")
}
end
end
def tcp_test_ssh(fqdn, sshport)
tcp_socket = TCPSocket.new(fqdn, sshport)
readable = IO.select([tcp_socket], nil, nil, 5)
if readable
puts "\n"
Loggerx.info("sshd accepting connections on #{fqdn}, banner is #{tcp_socket.gets}")
yield
true
else
false
end
rescue SocketError
sleep 2
false
rescue Errno::ETIMEDOUT
false
rescue Errno::EPERM
false
rescue Errno::ECONNREFUSED
sleep 2
false
rescue Errno::EHOSTUNREACH
sleep 2
false
ensure
tcp_socket && tcp_socket.close
end
def tcp_test_winrm(ip_addr, port)
hostname = ip_addr
TCPSocket.new(hostname, port)
return true
rescue SocketError
sleep 2
false
rescue Errno::ETIMEDOUT
false
rescue Errno::EPERM
false
rescue Errno::ECONNREFUSED
sleep 2
false
rescue Errno::EHOSTUNREACH
sleep 2
false
rescue Errno::ENETUNREACH
sleep 2
false
end
end
end
end
class String
def fix(size=18, padstr=' ')
self[0...size].ljust(size, padstr)
end
end

Просмотреть файл

@ -0,0 +1,30 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/cloudazurepack'
require 'puppet/face'
Puppet::Face.define(:node_azure, '0.0.1') do
copyright "Windows Azure", 2013
license "Microsoft Open Technologies, Inc; see COPYING"
summary "View and manage Window Azure nodes."
description <<-'EOT'
This subcommand provides a command line interface to work with Windows Azure
machine instances. The goal of these actions are to easily create new
machines, install Puppet onto them, and tear them down when they're no longer
required.
EOT
end

Просмотреть файл

@ -0,0 +1,39 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
require 'puppet/cloudpack/bootstrap'
Puppet::Face.define :node_azure, '0.0.1' do
action :bootstrap do
summary 'Install puppet node on Windows Azure VM'
description <<-'EOT'
Install puppet node on Windows Azure Virtual Machine.
EOT
Puppet::CloudAzurePack.add_bootstrap_options(self)
when_invoked do |options|
Puppet::CloudPack::BootStrap.start(options)
end
examples <<-'EOT'
$ puppet node_azure bootstrap --publish-settings-file=azuremanagement_pfx.publishsettings \
--vm-user=username --puppet-master-ip=152.56.161.48 --password=Abcd123 \
--node-ip-address=domain.cloudapp.net
EOT
end
end

Просмотреть файл

@ -0,0 +1,72 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
require 'puppet/cloudpack/bootstrap'
Puppet::Face.define :node_azure, '0.0.1' do
action :create do
summary 'Create Windows Azure VM'
description <<-'EOT'
The create action create a storage account, cloud service and vm.
EOT
Puppet::CloudAzurePack.add_create_options(self)
when_invoked do |options|
options = ask_for_password(options, @os_type)
virtual_machine_service = Azure::VirtualMachineService.new
params = {
:vm_name=> options[:vm_name],
:vm_user=> options[:vm_user],
:image=> options[:image],
:password => options[:password],
:location => options[:location]
}
others = {
:storage_account_name=> options[:storage_account_name],
:cloud_service_name=> options[:cloud_service_name],
:deployment_name => options[:deployment_name],
:tcp_endpoints => options[:tcp_endpoints],
:private_key_file => options[:private_key_file] ,
:certificate_file => options[:certificate_file],
:ssh_port => options[:ssh_port],
:vm_size => options[:vm_size]
}
others.merge!(:winrm_transport => options[:winrm_transport]) unless options[:winrm_transport].nil?
server = virtual_machine_service.create_virtual_machine(params, others)
unless server.class == String
options[:node_ipaddress] = server.ipaddress
if options[:puppet_master_ip] && server
test_tcp_connection(server)
if server.os_type == 'Linux'
Puppet::CloudPack::BootStrap.start(options)
else
puts '\npuppet installation on windows is not yet implemented.'
end
end
end
end
examples <<-'EOT'
$ puppet node_azure create --publish-settings-file azuremanagement.publishsettings --vm-name vmname\
--vm-user ranjan --password Password!@12 --storage-account-name storageaccount1'\
--image b4590d9e3ed742e4a1d46e5424aa335e__SUSE-Linux-Enterprise-Server-11-SP2-Agent13\
--cloud-service-name cloudname --subscription-id 2346a-fce0-4cd3-a4ea-80e84bddff87\
--service-location "Southeast Asia" --tcp-endpoints "80,3889:3889"
EOT
end
end

Просмотреть файл

@ -0,0 +1,43 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :delete do
summary 'Delete Windows Azure node instances'
description <<-'EOT'
The delete action delete windows azure node instances.
EOT
Puppet::CloudAzurePack.add_delete_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
virtual_machine_service = Azure::VirtualMachineService.new
virtual_machine_service.delete_virtual_machine(options[:vm_name], options[:cloud_service_name])
nil
end
returns 'NONE'
examples <<-'EOT'
$ puppet node_azure delete --publish-settings-file azuremanagement.publishsettings \
--cloud-service-name service_name --vm-name name
EOT
end
end

Просмотреть файл

@ -0,0 +1,46 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :images do
summary 'List Windows Azure images'
#arguments 'NONE'
description <<-'EOT'
The images action obtains a list of images from the cloud provider and
displays them on the console output.
EOT
Puppet::CloudAzurePack.add_default_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
virtual_machine_image_service = Azure::VirtualMachineImageService.new
images = virtual_machine_image_service.list_virtual_machine_images
puts Tilt.new(Puppet::CloudAzurePack.views('images.erb'), 1, :trim => '%').render(nil, :images => images)
end
returns 'Array of attribute hashes containing information about each Azure images.'
examples <<-'EOT'
$ puppet node_azure images --publish-settings-file azuremanagement.publishsettings --azure-subscription-id ID
OS Type OS Nmae
Windows : 2cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-Beta
Windows : 2cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-Beta-February-2013
Linux : 5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS63JAN20130122
EOT
end
end

Просмотреть файл

@ -0,0 +1,50 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :locations do
summary 'List Windows Azure locations'
#arguments 'NONE'
description <<-'EOT'
The locations action obtains a list of locatons from the cloud provider and
displays them on the console output.
EOT
Puppet::CloudAzurePack.add_default_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
base_management = Azure::BaseManagementService.new
locations = base_management.list_locations
puts Tilt.new(Puppet::CloudAzurePack.views('locations.erb'), 1, :trim => '%').render(nil, :locations => locations)
end
returns 'Array of attribute hashes containing information about each Azure locations.'
examples <<-'EOT'
$ puppet node_azure locations --publish-settings-file azuremanagement.publishsettings
Location Name Available Service
West US : Compute, Storage, PersistentVMRole
East US : Compute, Storage, PersistentVMRole
East Asia : Compute, Storage, PersistentVMRole
Southeast Asia : Compute, Storage, PersistentVMRole
North Europe : Compute, Storage, PersistentVMRole
West Europe : Compute, Storage, PersistentVMRole
EOT
end
end

Просмотреть файл

@ -0,0 +1,51 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :servers do
summary 'List Windows Azure node instances'
arguments 'list'
description <<-'EOT'
The list action obtains a list of instances from the cloud provider and
displays them on the console output. For Azure instances, only the instances in
a specific region are provided.
EOT
Puppet::CloudAzurePack.add_default_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
virtual_machine_service = Azure::VirtualMachineService.new
servers = virtual_machine_service.list_virtual_machines
puts Tilt.new(Puppet::CloudAzurePack.views('servers.erb'), 1, :trim => '%').render(nil, :roles => servers)
end
returns 'Array of attribute hashes containing information about each Azure instance.'
examples <<-'EOT'
$ puppet node_azure servers --publish-settings-file azuremanagement.publishsettings --azure-subscription-id ID
Server: 1
Service: cloudserver1
Deployment: deployment1
Role: windows
Host: akwindows
Deployment Status: Running
Role Status: ReadyRole
IP Address: 168.61.8.83
EOT
end
end

Просмотреть файл

@ -0,0 +1,43 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :shutdown do
summary 'Shutdown Windows Azure node instances'
description <<-'EOT'
The shutdown action stops windows azure node instances.
EOT
Puppet::CloudAzurePack.add_shutdown_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
virtual_machine_service = Azure::VirtualMachineService.new
virtual_machine_service.shutdown_virtual_machine(options[:vm_name], options[:cloud_service_name])
nil
end
returns 'NONE'
examples <<-'EOT'
$ puppet node_azure shutdown --publish-settings-file azuremanagement.publishsettings \
--cloud-service-name service_name --vm-name name
EOT
end
end

Просмотреть файл

@ -0,0 +1,43 @@
#-------------------------------------------------------------------------
# Copyright 2013 Microsoft Open Technologies, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'puppet/face/node_azure'
Puppet::Face.define :node_azure, '0.0.1' do
action :start do
summary 'starts Windows Azure node instances'
description <<-'EOT'
The start action starts windows azure node instances.
EOT
Puppet::CloudAzurePack.add_shutdown_options(self)
when_invoked do |options|
Puppet::CloudAzurePack.initialize_env_variable(options)
virtual_machine_service = Azure::VirtualMachineService.new
virtual_machine_service.start_virtual_machine(options[:vm_name], options[:cloud_service_name])
nil
end
returns 'NONE'
examples <<-'EOT'
$ puppet node_azure start --publish-settings-file azuremanagement.publishsettings \
--cloud-service-name service_name --vm-name name
EOT
end
end

Просмотреть файл

@ -0,0 +1,7 @@
<%="Listing Virtual Machine Images".bold %>
<%="OS Type".bold%> <%="Category".bold%> <%="Name".bold%>
<%images.each do |image|%>
<%=image.os_type.fix%> <%=image.category.fix(20)%> <%=image.name%>
<%end%>

Просмотреть файл

@ -0,0 +1,7 @@
<%="Listing Locations".bold%>
<%="Location Name".bold%> <%="Available Service".bold%>
<%locations.each do |location|%>
<%=location.name.fix%> <%=location.available_services%>
<%end%>

Просмотреть файл

@ -0,0 +1,13 @@
<%index=1%>
<%="Listing Servers".bold%>
<%roles.each do |role|%>
<%="Server: #{index}".bold%>
<%="Service".fix%>: <%=role.cloud_service_name %>
<%="Deployment".fix%>: <%=role.deployment_name%>
<%="Role".fix%>: <%=role.vm_name %>
<%="Host".fix%>: <%=role.hostname%>
<%="Deployment Status".fix%>: <%=role.deployment_status == "Running" ? role.deployment_status.green : role.deployment_status%>
<%="Role Status".fix%>: <%=role.status%>
<%="IP Address".fix%>: <%=role.ipaddress%>
<%index+=1%>
<%end%>