We do it this way. It avoids complexity and breaking tests.
--- /dev/null
+---
+driver_plugin: vagrant
+driver_config:
+ require_chef_omnibus: true
+
+platforms:
+- name: ubuntu-10.04
+- name: ubuntu-12.04
+- name: centos-6.4
+- name: centos-5.9
+
+provisioner:
+ name: chef_zero
+
+suites:
+- name: default
+ run_list:
+ - "recipe[ceph::repo]"
+ - "recipe[ceph]"
+ attributes: &defaults
+ ceph:
+ config:
+ fsid: ae3f1d03-bacd-4a90-b869-1a4fabb107f2
+ mon_initial_members:
+ - "127.0.0.1"
+- name: osd
+ run_list:
+ - "role[ceph-osd]"
+ attributes: *defaults
+- name: mon
+ run_list:
+ - "role[ceph-mon]"
+ attributes: *defaults
+- name: mds
+ run_list:
+ - "role[ceph-mds]"
+ attributes: *defaults
+- name: radosgw
+ run_list:
+ - "role[ceph-radosgw]"
+ attributes: *defaults
--- /dev/null
+AllCops:
+ Excludes:
+ - vendor/**
+
+AlignParameters:
+ Enabled: false
+Encoding:
+ Enabled: false
+HashSyntax:
+ Enabled: false
+StringLiterals:
+ Enabled: false
+LineLength:
+ Enabled: false
+MethodLength:
+ Max: 30
--- /dev/null
+rvm:
+ - 1.9.3
+ - 2.0.0
+before_script:
+ - bundle exec berks install
+bundler_args: --without integration
+script:
+ - bundle exec strainer test --except kitchen
--- /dev/null
+site :opscode
+
+metadata
--- /dev/null
+source "https://rubygems.org"
+
+gem "chef", "~> 11.4.4"
+gem "json", "<= 1.7.7" # chef 11 dependency
+gem "berkshelf", "~> 2.0.10"
+gem "chefspec", "~> 3.0.2"
+gem "foodcritic", "~> 3.0.3"
+gem "strainer"
+gem "rubocop"
+
+group :integration do
+ gem "test-kitchen", "~> 1.1.1"
+ gem "kitchen-vagrant", "~> 0.14"
+end
--- /dev/null
+Chef cookbook for deploying the Ceph storage system
+===================================================
+
+Note: "knife cookbook upload" needs this directory to be named "ceph".
+Please clone the repository as
+
+ git clone https://github.com/ceph/ceph-cookbooks.git ceph
+
+(we cannot name this repository ceph.git, as that is the main project
+itself)
+
+
+DESCRIPTION
+===========
+
+Installs and configures Ceph, a distributed network storage and filesystem designed to provide excellent performance, reliability, and scalability.
+
+The current version is focused towards deploying Monitors and OSD on Ubuntu.
+
+For documentation on how to use this cookbook, refer to the [USAGE](#USAGE) section.
+
+Work in progress:
+
+* RadosGW
+* MDS
+* Other Distro (Debian, RHEL/CentOS, FC)
+
+REQUIREMENTS
+============
+
+Platform
+--------
+
+Tested as working:
+
+* Ubuntu Precise (12.04)
+
+Cookbooks
+---------
+
+The ceph cookbook requires the following cookbooks from Opscode:
+
+https://github.com/opscode/cookbooks
+
+* apt
+* apache2
+
+
+ATTRIBUTES
+==========
+
+Ceph Rados Gateway
+------------------
+
+* node[:ceph][:radosgw][:api_fqdn]
+* node[:ceph][:radosgw][:admin_email]
+* node[:ceph][:radosgw][:rgw_addr]
+
+TEMPLATES
+=========
+
+
+
+USAGE
+=====
+
+Ceph cluster design is beyond the scope of this README, please turn to the
+public wiki, mailing lists, visit our IRC channel, or contact Inktank:
+
+http://ceph.com/docs/master
+http://ceph.com/resources/mailing-list-irc/
+http://www.inktank.com/
+
+
+Ceph Monitor
+------------
+
+Ceph monitor nodes should use the ceph-mon role.
+
+Includes:
+
+* ceph::default
+* ceph::conf
+
+Ceph Metadata Server
+--------------------
+
+Ceph metadata server nodes should use the ceph-mds role.
+
+Includes:
+
+* ceph::default
+
+Ceph OSD
+--------
+
+Ceph OSD nodes should use the ceph-osd role
+
+Includes:
+
+* ceph::default
+* ceph::conf
+
+Ceph Rados Gateway
+------------------
+
+Ceph Rados Gateway nodes should use the ceph-radosgw role
+
+
+LICENSE AND AUTHORS
+===================
+
+* Author: Kyle Bader <kyle.bader@dreamhost.com>
+
+* Copyright 2013, DreamHost Web Hosting and Inktank Storage 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.
--- /dev/null
+# Strainerfile
+rubocop: bundle exec rubocop $SANDBOX/$COOKBOOK
+knife test: bundle exec knife cookbook test $COOKBOOK
+foodcritic: bundle exec foodcritic -f any -t ~FC003 -t ~FC023 $SANDBOX/$COOKBOOK
+#chefspec: bundle exec rspec $SANDBOX/$COOKBOOK/spec
--- /dev/null
+default["ceph"]["cephfs_mount"] = "/ceph"
--- /dev/null
+default["ceph"]["config"] = {}
+default["ceph"]["config-sections"] = {}
--- /dev/null
+default['ceph']['install_debug'] = true
+default['ceph']['encrypted_data_bags'] = false
--- /dev/null
+case node['platform']
+when 'ubuntu'
+ default["ceph"]["mds"]["init_style"] = "upstart"
+else
+ default["ceph"]["mds"]["init_style"] = "sysvinit"
+end
--- /dev/null
+case node['platform']
+when 'ubuntu'
+ default["ceph"]["mon"]["init_style"] = "upstart"
+else
+ default["ceph"]["mon"]["init_style"] = "sysvinit"
+end
+default["ceph"]["mon"]["secret_file"] = "/etc/chef/secrets/ceph_mon"
--- /dev/null
+case node['platform']
+when 'ubuntu'
+ default["ceph"]["osd"]["init_style"] = "upstart"
+else
+ default["ceph"]["osd"]["init_style"] = "sysvinit"
+end
+default["ceph"]["osd"]["secret_file"] = "/etc/chef/secrets/ceph_osd"
--- /dev/null
+#
+# Cookbook Name:: ceph
+# Attributes:: radosgw
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+#
+
+default["ceph"]["radosgw"]["api_fqdn"] = "localhost"
+default["ceph"]["radosgw"]["admin_email"] = "admin@example.com"
+default["ceph"]["radosgw"]["rgw_addr"] = "*:80"
+default["ceph"]["radosgw"]["rgw_port"] = false
+default["ceph"]["radosgw"]["webserver_companion"] = "apache2" # can be false
+default['ceph']["radosgw"]['use_apache_fork'] = true
+case node['platform']
+when 'ubuntu'
+ default["ceph"]["radosgw"]["init_style"] = "upstart"
+else
+ default["ceph"]["radosgw"]["init_style"] = "sysvinit"
+end
--- /dev/null
+default['ceph']['branch'] = "stable" # Can be stable, testing or dev.
+# Major release version to install or gitbuilder branch
+default['ceph']['version'] = "dumpling"
+default['ceph']['el_add_epel'] = true
+default['ceph']['repo_url'] = "http://ceph.com"
+default['ceph']['extras_repo_url'] = "http://ceph.com/packages/ceph-extras"
+
+case node['platform_family']
+when "debian"
+ # Debian/Ubuntu default repositories
+ default['ceph']['debian']['stable']['repository'] = "#{node['ceph']['repo_url']}/debian-#{node['ceph']['version']}/"
+ default['ceph']['debian']['stable']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc"
+ default['ceph']['debian']['testing']['repository'] = "#{node['ceph']['repo_url']}/debian-testing/"
+ default['ceph']['debian']['testing']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc"
+ default['ceph']['debian']['dev']['repository'] = "http://gitbuilder.ceph.com/ceph-deb-#{node['lsb']['codename']}-x86_64-basic/ref/#{node['ceph']['version']}"
+ default['ceph']['debian']['dev']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+ default['ceph']['debian']['extras']['repository'] = "#{node['ceph']['extras_repo_url']}/debian/"
+ default['ceph']['debian']['extras']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc"
+when "rhel"
+ # Redhat/CentOS default repositories
+ default['ceph']['rhel']['stable']['repository'] = "#{node['ceph']['repo_url']}/rpm-#{node['ceph']['version']}/el6/noarch/ceph-release-1-0.el6.noarch.rpm"
+ default['ceph']['rhel']['testing']['repository'] = "#{node['ceph']['repo_url']}/rpm-testing/el6/x86_64/ceph-release-1-0.el6.noarch.rpm"
+ default['ceph']['rhel']['dev']['repository'] = "http://gitbuilder.ceph.com/ceph-rpm-centos6-x86_64-basic/ref/#{node['ceph']['version']}/x86_64/"
+ default['ceph']['rhel']['dev']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+ default['ceph']['rhel']['extras']['repository'] = "#{node['ceph']['extras_repo_url']}/rpm/rhel6/x86_64/"
+ default['ceph']['rhel']['extras']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+when "fedora"
+ # Fedora default repositories
+ default['ceph']['fedora']['stable']['repository'] = "#{node['ceph']['repo_url']}/rpm-#{node['ceph']['version']}/fc#{node['platform_version']}/x86_64/ceph-release-1-0.fc#{node['platform_version']}.noarch.rpm"
+ default['ceph']['fedora']['testing']['repository'] = "#{node['ceph']['repo_url']}/rpm-testing/fc#{node['platform_version']}/x86_64/ceph-release-1-0.fc#{node['platform_version']}.noarch.rpm"
+ default['ceph']['fedora']['dev']['repository'] = "http://gitbuilder.ceph.com/ceph-rpm-fc#{node['platform_version']}-x86_64-basic/ref/#{node['ceph']['version']}/RPMS/x86_64/"
+ default['ceph']['fedora']['dev']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+ default['ceph']['fedora']['extras']['repository'] = "#{node['ceph']['extras_repo_url']}/rpm/fedora#{node['platform_version']}/x86_64/"
+ default['ceph']['fedora']['extras']['repository_key'] = "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+when "suse"
+ # (Open)SuSE default repositories
+ # Chef doesn't make a difference between suse and opensuse
+ suse = %x[ head -n1 /etc/SuSE-release| awk '{print $1}' ].chomp.downcase # can be suse or opensuse
+ suse = "sles" if suse == "suse"
+ suse_version = suse << %x[ grep VERSION /etc/SuSE-release | awk -F'= ' '{print $2}' ].chomp
+
+ default['ceph']['suse']['stable']['repository'] = "#{node['ceph']['repo_url']}/rpm-#{node['ceph']['version']}/#{suse_version}/x86_64/ceph-release-1-0.#{suse_version}.noarch.rpm"
+ default['ceph']['suse']['testing']['repository'] = "#{node['ceph']['repo_url']}/rpm-testing/#{suse_version}/x86_64/ceph-release-1-0.#{suse_version}.noarch.rpm"
+ default['ceph']['suse']['extras']['repository'] = "#{node['ceph']['extras_repo_url']}/rpm/#{suse_version}/x86_64/"
+else
+ fail "#{node['platform_family']} is not supported"
+end
--- /dev/null
+require 'ipaddr'
+require 'json'
+
+def crowbar?
+ !defined?(Chef::Recipe::Barclamp).nil?
+end
+
+def get_mon_nodes(extra_search = nil)
+ if crowbar?
+ mon_roles = search(:role, 'name:crowbar-* AND run_list:role\[ceph-mon\]')
+ unless mon_roles.empty?
+ search_string = mon_roles.map { |role_object| "roles:" + role_object.name }.join(' OR ')
+ search_string = "(#{search_string}) AND ceph_config_environment:#{node['ceph']['config']['environment']}"
+ end
+ else
+ search_string = "ceph_is_mon:true AND chef_environment:#{node.chef_environment}"
+ end
+
+ unless extra_search.nil?
+ search_string = "(#{search_string}) AND (#{extra_search})"
+ end
+ search(:node, search_string)
+end
+
+# If public_network is specified
+# we need to search for the monitor IP
+# in the node environment.
+# 1. We look if the network is IPv6 or IPv4
+# 2. We look for a route matching the network
+# 3. We grab the IP and return it with the port
+def find_node_ip_in_network(network, nodeish = nil)
+ nodeish = node unless nodeish
+ net = IPAddr.new(network)
+ nodeish["network"]["interfaces"].each do |iface, addrs|
+ addrs["addresses"].each do |ip, params|
+ if params['family'].eql?("inet6") && net.include?(ip)
+ return "[#{ip}]:6789"
+ elsif params['family'].eql?("inet") && net.include?(ip)
+ return "#{ip}:6789"
+ end
+ end
+ end
+ nil
+end
+
+def mon_addresses
+ mon_ips = []
+
+ if File.exists?("/var/run/ceph/ceph-mon.#{node['hostname']}.asok")
+ mon_ips = quorum_members_ips
+ else
+ mons = []
+ # make sure if this node runs ceph-mon, it's always included even if
+ # search is laggy; put it first in the hopes that clients will talk
+ # primarily to local node
+ mons << node if node['ceph']['is_mon']
+
+ mons += get_mon_nodes
+ if crowbar?
+ mon_ips = mons.map { |node| Chef::Recipe::Barclamp::Inventory.get_network_by_type(node, "admin").address }
+ else
+ if node['ceph']['config']['global'] && node['ceph']['config']['global']['public network']
+ mon_ips = mons.map { |nodeish| find_node_ip_in_network(node['ceph']['config']['global']['public network'], nodeish) }
+ else
+ mon_ips = mons.map { |node| node['ipaddress'] + ":6789" }
+ end
+ end
+ end
+ mon_ips.reject { |m| m.nil? }.uniq
+end
+
+def quorum_members_ips
+ mon_ips = []
+ cmd = Mixlib::ShellOut.new("ceph --admin-daemon /var/run/ceph/ceph-mon.#{node['hostname']}.asok mon_status")
+ cmd.run_command
+ cmd.error!
+
+ mons = JSON.parse(cmd.stdout)['monmap']['mons']
+ mons.each do |k|
+ mon_ips.push(k['addr'][0..-3])
+ end
+ mon_ips
+end
+
+QUORUM_STATES = %w(leader, peon)
+def have_quorum?
+ # "ceph auth get-or-create-key" would hang if the monitor wasn't
+ # in quorum yet, which is highly likely on the first run. This
+ # helper lets us delay the key generation into the next
+ # chef-client run, instead of hanging.
+ #
+ # Also, as the UNIX domain socket connection has no timeout logic
+ # in the ceph tool, this exits immediately if the ceph-mon is not
+ # running for any reason; trying to connect via TCP/IP would wait
+ # for a relatively long timeout.
+
+ cmd = Mixlib::ShellOut.new("ceph --admin-daemon /var/run/ceph/ceph-mon.#{node['hostname']}.asok mon_status")
+ cmd.run_command
+ cmd.error!
+
+ state = JSON.parse(cmd.stdout)['state']
+ QUORUM_STATES.include?(state)
+end
--- /dev/null
+name "ceph"
+maintainer "Kyle Bader"
+maintainer_email "kyle.bader@dreamhost.com"
+license "Apache 2.0"
+description "Installs/Configures the Ceph distributed filesystem"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version "0.1.0"
+
+depends "apache2", ">= 1.1.12"
+depends "apt"
+depends "yum", ">= 3.0"
+depends "yum-epel"
--- /dev/null
+def whyrun_supported?
+ true
+end
+
+action :add do
+ filename = @current_resource.filename
+ keyname = @current_resource.keyname
+ caps = @new_resource.caps.map { |k, v| "#{k} '#{v}'" }.join(' ')
+ if @current_resource.exists
+ Chef::Log.info "#{ @new_resource} already exists - nothing to do"
+ else
+ if @current_resource.caps != @new_resource.caps
+ converge_by("create ceph auth key #{keyname}") do
+ auth_set_key(keyname, caps) unless @current_resource.exists
+ end
+ end
+ if @current_resource.as_keyring
+ get_new_content = method(:get_new_key_file)
+ else
+ get_new_content = method(:get_new_key)
+ end
+ if get_saved_key_file(@current_resource.filename) != get_new_content.call(keyname)
+ converge_by("save ceph auth key to #{filename}") do
+ file filename do
+ content lazy { get_new_content.call(keyname) }
+ owner "root"
+ group "root"
+ mode "640"
+ end
+ end
+ end
+ end
+end
+
+def load_current_resource
+ @current_resource = Chef::Resource::CephClient.new(@new_resource.name)
+ @current_resource.name(@new_resource.name)
+ @current_resource.as_keyring(@new_resource.as_keyring)
+ @current_resource.keyname(@new_resource.keyname || "client.#{current_resource.name}.#{node['hostname']}")
+ @current_resource.caps(get_caps(@current_resource.keyname))
+ if @current_resource.as_keyring
+ get_new_content = method(:get_new_key_file)
+ @current_resource.filename(@new_resource.filename || "/etc/ceph/ceph.client.#{current_resource.name}.#{node['hostname']}.keyring")
+ else
+ get_new_content = method(:get_new_key)
+ @current_resource.filename(@new_resource.filename || "/etc/ceph/ceph.client.#{current_resource.name}.#{node['hostname']}.secret")
+ end
+ if @current_resource.caps == @new_resource.caps &&
+ get_saved_key_file(@current_resource.filename) == get_new_content.call(@current_resource.keyname)
+ @current_resource.exists = true
+ end
+end
+
+def get_new_key(keyname)
+ cmd = "ceph auth print_key #{keyname}"
+ key = Mixlib::ShellOut.new(cmd).run_command.stdout
+ key
+end
+
+def get_new_key_file(keyname)
+ cmd = "ceph auth print_key #{keyname}"
+ key = Mixlib::ShellOut.new(cmd).run_command.stdout
+ "[#{keyname}]\n\tkey = #{key}\n"
+end
+
+def get_saved_key_file(filename)
+ ::IO.read(filename) rescue ""
+end
+
+def get_caps(keyname)
+ caps = {}
+ cmd = "ceph auth get #{keyname}"
+ output = Mixlib::ShellOut.new(cmd).run_command.stdout
+ output.scan(/caps\s*(\S+)\s*=\s*"([^"]*)"/) {|k, v|
+ caps[k] = v
+ }
+ caps
+end
+
+def auth_set_key(keyname, caps)
+ # find the monitor secret
+ mon_secret = ""
+ mons = get_mon_nodes
+ if !mons.empty?
+ mon_secret = mons[0]["ceph"]["monitor-secret"]
+ elsif mons.empty? && node["ceph"]["monitor-secret"]
+ mon_secret = node["ceph"]["monitor-secret"]
+ else
+ Chef::Log.warn("No monitor secret found")
+ end
+ # try to add the key
+ cmd = "ceph auth get-or-create #{keyname} #{caps} --name mon. --key='#{mon_secret}'"
+ get_or_create = Mixlib::ShellOut.new(cmd)
+ get_or_create.run_command
+ if get_or_create.stderr.scan(/EINVAL.*but cap.*does not match/)
+ Chef::Log.info("Deleting old key with incorrect caps")
+ # delete an old key if it exists and is wrong
+ Mixlib::ShellOut.new("ceph auth del #{keyname}").run_command
+ # try to create again
+ get_or_create.run_command
+ end
+ get_or_create.error!
+end
--- /dev/null
+
+include_recipe "apt"
+
+branch = node['ceph']['branch']
+
+apt_repository "ceph-#{branch}" do
+ repo_name "ceph"
+ uri node['ceph']['debian'][branch]['repository']
+ distribution node['lsb']['codename'] == "jessie" ? "sid" : node['lsb']['codename']
+ components ['main']
+ key node['ceph']['debian'][branch]['repository_key']
+end
+
+if node['roles'].include?("ceph-tgt")
+ apt_repository "ceph-extras-#{branch}" do
+ repo_name "ceph-extras"
+ uri node['ceph']['debian']['extras']['repository']
+ distribution node['lsb']['codename'] == "jessie" ? "sid" : node['lsb']['codename']
+ components ['main']
+ key node['ceph']['debian']['extras']['repository_key']
+ end
+end
+
+if node['roles'].include?("ceph-radosgw") \
+ && node["ceph"]["radosgw"]["webserver_companion"] == "apache2" \
+ && node["ceph"]["radosgw"]["use_apache_fork"] == true
+ case node['lsb']['codename']
+ when "precise", "oneiric"
+ apt_repository "ceph-apache2" do
+ repo_name "ceph-apache2"
+ uri "http://gitbuilder.ceph.com/apache2-deb-#{node['lsb']['codename']}-x86_64-basic/ref/master"
+ distribution node['lsb']['codename']
+ components ["main"]
+ key "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+ end
+ apt_repository "ceph-modfastcgi" do
+ repo_name "ceph-modfastcgi"
+ uri "http://gitbuilder.ceph.com/libapache-mod-fastcgi-deb-#{node['lsb']['codename']}-x86_64-basic/ref/master"
+ distribution node['lsb']['codename']
+ components ["main"]
+ key "https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc"
+ end
+ else
+ Log.info("Ceph's Apache and Apache FastCGI forks not available for this distribution")
+ end
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: cephfs
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+include_recipe "ceph::conf"
+
+name = "cephfs"
+client_name = "cephfs.#{node['hostname']}"
+filename = "/etc/ceph/ceph.client.#{client_name}.secret"
+
+ceph_client name do
+ filename filename
+ caps ({ "mon" => "allow r", "osd" => "allow rw", "mds" => "allow" })
+ as_keyring false
+end
+
+mons = mon_addresses.join(",") + ":/"
+
+directory node['ceph']['cephfs_mount']
+
+mount node['ceph']['cephfs_mount'] do
+ fstype "ceph"
+ device mons
+ options "_netdev,name=#{client_name},secretfile=#{filename}"
+ dump 0
+ pass 0
+ action [:mount, :enable]
+ not_if { mons.empty? }
+end
--- /dev/null
+fail "fsid must be set in config" if node["ceph"]["config"]['fsid'].nil?
+fail "mon_initial_members must be set in config" if node["ceph"]["config"]['mon_initial_members'].nil?
+
+is_rgw = node['roles'].include?('ceph-radosgw')
+
+directory "/etc/ceph" do
+ owner "root"
+ group "root"
+ mode "0755"
+ action :create
+end
+
+template '/etc/ceph/ceph.conf' do
+ source 'ceph.conf.erb'
+ variables(
+ :mon_addresses => mon_addresses,
+ :is_rgw => is_rgw
+ )
+ mode '0644'
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: default
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+packages = []
+
+case node['platform_family']
+when "debian"
+ packages = %w{
+ ceph
+ ceph-common
+ }
+
+ if node['ceph']['install_debug']
+ packages_dbg = %w{
+ ceph-dbg
+ ceph-common-dbg
+ }
+ packages += packages_dbg
+ end
+when "rhel", "fedora"
+ packages = %w{
+ ceph
+ }
+
+ if node['ceph']['install_debug']
+ packages_dbg = %w{
+ ceph-debug
+ }
+ packages += packages_dbg
+ end
+end
+
+packages.each do |pkg|
+ package pkg do
+ action :install
+ end
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: mds
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+include_recipe "ceph::default"
+include_recipe "ceph::conf"
+
+cluster = 'ceph'
+
+directory "/var/lib/ceph/mds/#{cluster}-#{node["hostname"]}" do
+ owner "root"
+ group "root"
+ mode 00755
+ recursive true
+ action :create
+end
+
+ruby_block "create mds client key" do
+ block do
+ keyring = %x[ ceph auth get-or-create mds.#{node['hostname']} osd 'allow *' mon 'allow rwx' --name mon. --key='#{node["ceph"]["monitor-secret"]}' ]
+ keyfile = File.new("/var/lib/ceph/mds/#{cluster}-#{node['hostname']}/keyring", "w")
+ keyfile.puts(keyring)
+ keyfile.close
+ end
+end
+
+file "/var/lib/ceph/mds/#{cluster}-#{node["hostname"]}/done" do
+ owner "root"
+ group "root"
+ mode 00644
+end
+
+service_type = node["ceph"]["osd"]["init_style"]
+
+case service_type
+when "upstart"
+ filename = "upstart"
+else
+ filename = "sysvinit"
+end
+file "/var/lib/ceph/mds/#{cluster}-#{node["hostname"]}/#{filename}" do
+ owner "root"
+ group "root"
+ mode 00644
+end
+
+service "ceph_mds" do
+ case service_type
+ when "upstart"
+ service_name "ceph-mds-all-starter"
+ provider Chef::Provider::Service::Upstart
+ else
+ service_name "ceph"
+ end
+ action [:enable, :start]
+ supports :restart => true
+end
--- /dev/null
+# This recipe creates a monitor cluster
+#
+# You should never change the mon default path or
+# the keyring path.
+# Don't change the cluster name either
+# Default path for mon data: /var/lib/ceph/mon/$cluster-$id/
+# which will be /var/lib/ceph/mon/ceph-`hostname`/
+# This path is used by upstart. If changed, upstart won't
+# start the monitor
+# The keyring files are created using the following pattern:
+# /etc/ceph/$cluster.client.$name.keyring
+# e.g. /etc/ceph/ceph.client.admin.keyring
+# The bootstrap-osd and bootstrap-mds keyring are a bit
+# different and are created in
+# /var/lib/ceph/bootstrap-{osd,mds}/ceph.keyring
+
+include_recipe "ceph::default"
+include_recipe "ceph::conf"
+
+service_type = node["ceph"]["mon"]["init_style"]
+
+node.default['ceph']['is_mon'] = true
+
+directory "/var/run/ceph" do
+ owner "root"
+ group "root"
+ mode 00755
+ recursive true
+ action :create
+end
+
+directory "/var/lib/ceph/mon/ceph-#{node["hostname"]}" do
+ owner "root"
+ group "root"
+ mode 00755
+ recursive true
+ action :create
+end
+
+# TODO: cluster name
+cluster = 'ceph'
+
+unless File.exists?("/var/lib/ceph/mon/ceph-#{node["hostname"]}/done")
+ keyring = "#{Chef::Config[:file_cache_path]}/#{cluster}-#{node['hostname']}.mon.keyring"
+
+ if node['ceph']['encrypted_data_bags']
+ secret = Chef::EncryptedDataBagItem.load_secret(node["ceph"]["mon"]["secret_file"])
+ monitor_secret = Chef::EncryptedDataBagItem.load("ceph", "mon", secret)["secret"]
+ else
+ monitor_secret = node["ceph"]["monitor-secret"]
+ end
+
+ execute "format as keyring" do
+ command "ceph-authtool '#{keyring}' --create-keyring --name=mon. --add-key='#{monitor_secret}' --cap mon 'allow *'"
+ creates "#{Chef::Config[:file_cache_path]}/#{cluster}-#{node['hostname']}.mon.keyring"
+ end
+
+ execute 'ceph-mon mkfs' do
+ command "ceph-mon --mkfs -i #{node['hostname']} --keyring '#{keyring}'"
+ end
+
+ ruby_block "finalise" do
+ block do
+ ["done", service_type].each do |ack|
+ ::File.open("/var/lib/ceph/mon/ceph-#{node["hostname"]}/#{ack}", "w").close
+ end
+ end
+ end
+end
+
+if service_type == "upstart"
+ service "ceph-mon" do
+ provider Chef::Provider::Service::Upstart
+ action :enable
+ end
+ service "ceph-mon-all" do
+ provider Chef::Provider::Service::Upstart
+ supports :status => true
+ action [:enable, :start]
+ end
+end
+
+service "ceph_mon" do
+ case service_type
+ when "upstart"
+ service_name "ceph-mon-all-starter"
+ provider Chef::Provider::Service::Upstart
+ else
+ service_name "ceph"
+ end
+ supports :restart => true, :status => true
+ action [:enable, :start]
+end
+
+mon_addresses.each do |addr|
+ execute "peer #{addr}" do
+ command "ceph --admin-daemon '/var/run/ceph/ceph-mon.#{node['hostname']}.asok' add_bootstrap_peer_hint #{addr}"
+ ignore_failure true
+ end
+end
+
+# The key is going to be automatically
+# created,
+# We store it when it is created
+unless node['ceph']['encrypted_data_bags']
+ ruby_block "get osd-bootstrap keyring" do
+ block do
+ run_out = ""
+ while run_out.empty?
+ run_out = Mixlib::ShellOut.new("ceph auth get-key client.bootstrap-osd").run_command.stdout.strip
+ sleep 2
+ end
+ node.override['ceph']['bootstrap_osd_key'] = run_out
+ node.save
+ end
+ not_if { node['ceph']['bootstrap_osd_key'] }
+ end
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: osd
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+# this recipe allows bootstrapping new osds, with help from mon
+# Sample environment:
+# #knife node edit ceph1
+# "osd_devices": [
+# {
+# "device": "/dev/sdc"
+# },
+# {
+# "device": "/dev/sdd",
+# "dmcrypt": true,
+# "journal": "/dev/sdd"
+# }
+# ]
+
+include_recipe "ceph::default"
+include_recipe "ceph::conf"
+
+package 'gdisk' do
+ action :upgrade
+end
+
+package 'cryptsetup' do
+ action :upgrade
+ only_if { node[:dmcrypt] }
+end
+
+service_type = node["ceph"]["osd"]["init_style"]
+mons = node['ceph']['encrypted_data_bags'] ? get_mon_nodes : get_mon_nodes("ceph_bootstrap_osd_key:*")
+
+if mons.empty?
+ puts "No ceph-mon found."
+else
+
+ directory "/var/lib/ceph/bootstrap-osd" do
+ owner "root"
+ group "root"
+ mode "0755"
+ end
+
+ # TODO: cluster name
+ cluster = 'ceph'
+
+ if node['ceph']['encrypted_data_bags']
+ secret = Chef::EncryptedDataBagItem.load_secret(node["ceph"]["osd"]["secret_file"])
+ osd_secret = Chef::EncryptedDataBagItem.load("ceph", "osd", secret)["secret"]
+ else
+ osd_secret = mons[0]["ceph"]["bootstrap_osd_key"]
+ end
+
+ execute "format as keyring" do
+ command "ceph-authtool '/var/lib/ceph/bootstrap-osd/#{cluster}.keyring' --create-keyring --name=client.bootstrap-osd --add-key='#{osd_secret}'"
+ creates "/var/lib/ceph/bootstrap-osd/#{cluster}.keyring"
+ end
+
+ if crowbar?
+ ruby_block "select new disks for ceph osd" do
+ block do
+ do_trigger = false
+ node["crowbar"]["disks"].each do |disk, data|
+ if node["crowbar"]["disks"][disk]["usage"] == "Storage"
+ puts "Disk: #{disk} should be used for ceph"
+
+ system 'ceph-disk-prepare', \
+ "/dev/#{disk}"
+ fail 'ceph-disk-prepare failed' unless $?.exitstatus == 0
+
+ do_trigger = true
+
+ node.set["crowbar"]["disks"][disk]["usage"] = "ceph-osd"
+ node.save
+ end
+ end
+
+ if do_trigger
+ system 'udevadm', \
+ "trigger", \
+ "--subsystem-match=block", \
+ "--action=add"
+ fail 'udevadm trigger failed' unless $?.exitstatus == 0
+ end
+
+ end
+ end
+ else
+ # Calling ceph-disk-prepare is sufficient for deploying an OSD
+ # After ceph-disk-prepare finishes, the new device will be caught
+ # by udev which will run ceph-disk-activate on it (udev will map
+ # the devices if dm-crypt is used).
+ # IMPORTANT:
+ # - Always use the default path for OSD (i.e. /var/lib/ceph/
+ # osd/$cluster-$id)
+ # - $cluster should always be ceph
+ # - The --dmcrypt option will be available starting w/ Cuttlefish
+ if !node["ceph"]["osd_devices"].nil?
+ node["ceph"]["osd_devices"].each_with_index do |osd_device, index|
+ unless osd_device["status"].nil?
+ Log.info("osd: osd_device #{osd_device} has already been setup.")
+ next
+ end
+
+ dmcrypt = osd_device["encrypted"] == true ? "--dmcrypt" : ""
+
+ create_cmd = "ceph-disk-prepare #{dmcrypt} #{osd_device['device']} #{osd_device['journal']}"
+ if osd_device["type"] == "directory"
+ directory osd_device["device"] do
+ owner "root"
+ group "root"
+ recursive true
+ end
+ create_cmd << " && ceph-disk-activate #{osd_device['device']}"
+ end
+ execute "Creating Ceph OSD on #{osd_device['device']}" do
+ command create_cmd
+ action :run
+ notifies :create, "ruby_block[save osd_device status #{index}]"
+ end
+ # we add this status to the node env
+ # so that we can implement recreate
+ # and/or delete functionalities in the
+ # future.
+ ruby_block "save osd_device status #{index}" do
+ block do
+ node.normal["ceph"]["osd_devices"][index]["status"] = "deployed"
+ node.save
+ end
+ action :nothing
+ end
+ end
+ service "ceph_osd" do
+ case service_type
+ when "upstart"
+ service_name "ceph-osd-all-starter"
+ provider Chef::Provider::Service::Upstart
+ else
+ service_name "ceph"
+ end
+ action [:enable, :start]
+ supports :restart => true
+ end
+ else
+ Log.info('node["ceph"]["osd_devices"] empty')
+ end
+ end
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: radosgw
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+case node['platform_family']
+when "debian"
+ packages = %w{
+ radosgw
+ }
+
+ if node['ceph']['install_debug']
+ packages_dbg = %w{
+ radosgw-dbg
+ }
+ packages += packages_dbg
+ end
+when "rhel", "fedora", "suse"
+ packages = %w{
+ ceph-radosgw
+ }
+end
+
+packages.each do |pkg|
+ package pkg do
+ action :upgrade
+ end
+end
+
+include_recipe "ceph::conf"
+
+if !::File.exists?("/var/lib/ceph/radosgw/ceph-radosgw.#{node['hostname']}/done")
+ if node["ceph"]["radosgw"]["webserver_companion"]
+ include_recipe "ceph::radosgw_#{node["ceph"]["radosgw"]["webserver_companion"]}"
+ end
+
+ ceph_client "radosgw" do
+ caps ({ "mon" => "allow rw", "osd" => "allow rwx" })
+ end
+
+ file "/var/lib/ceph/radosgw/ceph-radosgw.#{node['hostname']}/done" do
+ action :create
+ end
+
+ service "radosgw" do
+ case node["ceph"]["radosgw"]["init_style"]
+ when "upstart"
+ service_name "radosgw-all-starter"
+ provider Chef::Provider::Service::Upstart
+ else
+ if node['platform'] == "debian"
+ service_name "radosgw"
+ else
+ service_name "ceph-radosgw"
+ end
+ end
+ supports :restart => true
+ action [:enable, :start]
+ end
+else
+ Log.info("Rados Gateway already deployed")
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: radosgw_apache2
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+case node['platform_family']
+when "debian", "suse"
+ packages = %w{
+ apache2
+ libapache2-mod-fastcgi
+ }
+when "rhel", "fedora"
+ packages = %w{
+ httpd
+ mod_fastcgi
+ }
+end
+
+packages.each do |pkg|
+ package pkg do
+ action :upgrade
+ end
+end
+
+# For EL, delete the current fastcgi configuration
+# and set the correct owners for dirs and logs
+d_owner = d_group = "root"
+if node['platform_family'] == "rhel"
+ file "#{node['apache']['dir']}/conf.d/fastcgi.conf" do
+ action :delete
+ backup false
+ end
+ d_owner = d_group = "apache"
+end
+
+%W{ /var/run/ceph
+ /var/lib/ceph/radosgw/ceph-radosgw.#{node['hostname']}
+ /var/lib/apache2/
+}.each do |dir|
+ directory dir do
+ owner d_owner
+ group d_group
+ mode "0755"
+ recursive true
+ action :create
+ end
+end
+
+file "/var/log/ceph/radosgw.log" do
+ owner d_owner
+ group d_group
+ mode "0644"
+ action :create
+end
+
+include_recipe "apache2"
+
+apache_module "fastcgi" do
+ conf true
+end
+
+apache_module "rewrite" do
+ conf false
+end
+
+web_app "rgw" do
+ template "rgw.conf.erb"
+ server_name node['ceph']['radosgw']['api_fqdn']
+ admin_email node['ceph']['radosgw']['admin_email']
+ ceph_rgw_addr node['ceph']['radosgw']['rgw_addr']
+end
+
+service "apache2" do
+ action :restart
+end
+
+template "/var/www/s3gw.fcgi" do
+ source "s3gw.fcgi.erb"
+ owner "root"
+ group "root"
+ mode "0755"
+ variables(
+ :ceph_rgw_client => "client.radosgw.#{node['hostname']}"
+ )
+end
--- /dev/null
+case node['platform_family']
+when "debian"
+ include_recipe "ceph::apt"
+when "rhel", "suse"
+ include_recipe "ceph::rpm"
+else
+ fail "not supported"
+end
--- /dev/null
+platform_family = node['platform_family']
+
+case platform_family
+when "rhel"
+ if node['ceph']['el_add_epel'] == true
+ include_recipe "yum_epel"
+ end
+end
+
+branch = node['ceph']['branch']
+if branch == "dev" && platform_family != "centos" && platform_family != "fedora"
+ fail "Dev branch for #{platform_family} is not yet supported"
+end
+
+repo = node['ceph'][platform_family][branch]['repository']
+
+yum_repository "ceph" do
+ baseurl repo
+ gpgkey node['ceph'][platform_family]['dev']['repository_key'] if branch == "dev"
+end
+
+if node['roles'].include?("ceph-tgt")
+ yum_repository "ceph-extra" do
+ baseurl node['ceph'][platform_family]['extras']['repository']
+ gpgkey node['ceph'][platform_family]['extras']['repository_key']
+ end
+end
--- /dev/null
+#
+# Author:: Kyle Bader <kyle.bader@dreamhost.com>
+# Cookbook Name:: ceph
+# Recipe:: radosgw
+#
+# Copyright 2011, DreamHost Web Hosting
+#
+# 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.
+
+case node['platform_family']
+when "debian"
+ packages = %w{
+ tgt
+ }
+when "rhel", "fedora"
+ packages = %w{
+ scsi-target-utils
+ }
+end
+
+packages.each do |pkg|
+ package pkg do
+ action :upgrade
+ end
+end
+
+include_recipe "ceph::conf"
+# probably needs the key
+service "tgt" do
+ if node['platform'] == "ubuntu"
+ # The ceph version of tgt does not provide an Upstart script
+ provider Chef::Provider::Service::Init::Debian
+ service_name "tgt"
+ else
+ service_name "tgt"
+ end
+ supports :restart => true
+ action [:enable, :start]
+end
--- /dev/null
+actions :add
+default_action :add
+
+attribute :name, :kind_of => String, :name_attribute => true
+attribute :caps, :kind_of => Hash, :default => { "mon" => "allow r", "osd" => "allow r" }
+
+# Whether to store the secret in a keyring file or a plain secret file
+attribute :as_keyring, :kind_of => [TrueClass, FalseClass], :default => true
+
+# what the key should be called in the ceph cluster
+# defaults to client.#{name}.#{hostname}
+attribute :keyname, :kind_of => String
+
+# where the key should be saved
+# defaults to /etc/ceph/ceph.client.#{name}.#{hostname}.keyring if as_keyring
+# defaults to /etc/ceph/ceph.client.#{name}.#{hostname}.secret if not as_keyring
+attribute :filename, :kind_of => String
+
+attr_accessor :exists
--- /dev/null
+{
+ "name": "ceph-mds",
+ "description": "Ceph Metadata Server",
+ "run_list": [
+ "recipe[ceph::repo]",
+ "recipe[ceph::mds]"
+ ]
+}
\ No newline at end of file
--- /dev/null
+name "ceph-mds"
+description "Ceph Metadata Server"
+run_list(
+ 'recipe[ceph::repo]',
+ 'recipe[ceph::mds]'
+)
--- /dev/null
+{
+ "name": "ceph-mon",
+ "description": "Ceph Monitor",
+ "run_list": [
+ "recipe[ceph::repo]",
+ "recipe[ceph::mon]"
+ ]
+}
\ No newline at end of file
--- /dev/null
+name "ceph-mon"
+description "Ceph Monitor"
+run_list(
+ 'recipe[ceph::repo]',
+ 'recipe[ceph::mon]'
+)
--- /dev/null
+{
+ "name": "ceph-osd",
+ "description": "Ceph Object Storage Device",
+ "run_list": [
+ "recipe[ceph::repo]",
+ "recipe[ceph::osd]"
+ ]
+}
\ No newline at end of file
--- /dev/null
+name "ceph-osd"
+description "Ceph Object Storage Device"
+run_list(
+ 'recipe[ceph::repo]',
+ 'recipe[ceph::osd]'
+)
--- /dev/null
+{
+ "name": "ceph-radosgw",
+ "description": "Ceph RADOS Gateway",
+ "run_list": [
+ "recipe[ceph::repo]",
+ "recipe[ceph::radosgw]"
+ ]
+}
\ No newline at end of file
--- /dev/null
+name "ceph-radosgw"
+description "Ceph RADOS Gateway"
+run_list(
+ 'recipe[ceph::repo]',
+ 'recipe[ceph::radosgw]'
+)
--- /dev/null
+name "ceph-tgt"
+description "Ceph iSCSI Target"
+run_list(
+ 'recipe[ceph::repo]',
+ 'recipe[ceph::tgt]'
+)
--- /dev/null
+[global]
+ fsid = <%= node["ceph"]["config"]["fsid"] %>
+ mon initial members = <%= node["ceph"]["config"]["mon_initial_members"] %>
+ mon host = <%= @mon_addresses.join(', ') %>
+<% if (! node['ceph']['config']['global'].nil?) -%>
+ <% node['ceph']['config']['global'].each do |k, v| %>
+ <%= k %> = <%= v %>
+ <% end %>
+<% end -%>
+
+<% if (! node['ceph']['config']['osd'].nil?) -%>
+[osd]
+ <% node['ceph']['config']['osd'].each do |k, v| %>
+ <%= k %> = <%= v %>
+ <% end %>
+<% end -%>
+
+<% if (! node['ceph']['config']['mon'].nil?) -%>
+[mon]
+ <% node['ceph']['config']['mon'].each do |k, v| %>
+ <%= k %> = <%= v %>
+ <% end %>
+<% end -%>
+
+<% if (! node['ceph']['config']['mds'].nil?) -%>
+[mds]
+ <% node['ceph']['config']['mds'].each do |key, value| -%>
+ <%= key %> = <%= value %>
+ <% end -%>
+<% end -%>
+
+<% if (@is_rgw) -%>
+[client.radosgw.<%= node['hostname'] %>]
+ host = <%= node['hostname'] %>
+ rgw socket path = /var/run/ceph/radosgw.<%= node['hostname'] %>
+ keyring = /etc/ceph/ceph.client.radosgw.<%= node['hostname'] %>.keyring
+ log file = /var/log/ceph/radosgw.log
+<% if (! node['ceph']['config']['rgw'].nil?) -%>
+ <% node['ceph']['config']['rgw'].each do |k, v| %>
+ <%= k %> = <%= v %>
+ <% end %>
+<% end -%>
+<% end -%>
+
+<% node['ceph']['config-sections'].each do |name, sect| %>
+[<%= name %>]
+ <% sect.each do |k, v| %>
+ <%= k %> = <%= v %>
+ <% end %>
+<% end %>
--- /dev/null
+<IfModule mod_fastcgi.c>
+ AddHandler fastcgi-script .fcgi
+ #FastCgiWrapper /usr/lib/apache2/suexec
+ FastCgiIpcDir /var/lib/apache2/fastcgi
+</IfModule>
--- /dev/null
+<% if node['ceph']['radosgw']['rgw_port'] -%>
+FastCgiExternalServer /var/www/s3gw.fcgi -host 127.0.0.1:<%= node['ceph']['radosgw']['rgw_port'] %>
+<% else -%>
+FastCgiExternalServer /var/www/s3gw.fcgi -socket /var/run/ceph/radosgw.<%= node['hostname'] %>
+<% end -%>
+
+LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\"" proxy_combined
+LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\"" proxy_debug
+
+<VirtualHost <%= node['ceph']['radosgw']['rgw_addr'] %>>
+ ServerName <%= @params[:server_name] %>
+<% if node['ceph']['radosgw']['api_aliases'] -%>
+<% node['ceph']['radosgw']['api_aliases'].each do |api_alias| -%>
+ ServerAlias <%= api_alias %>
+<% end -%>
+<% end -%>
+ ServerAdmin <%= node["ceph"]["radosgw"]["admin_email"] %>
+ DocumentRoot /var/www/
+
+ RewriteEngine On
+ RewriteRule ^/([a-zA-Z0-9-_.]*)([/]?.*) /s3gw.fcgi?page=$1¶ms=$2&%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
+
+ <IfModule mod_fastcgi.c>
+ <Directory /var/www/>
+ Options +ExecCGI
+ AllowOverride All
+ SetHandler fastcgi-script
+ Order allow,deny
+ Allow from all
+ AuthBasicAuthoritative Off
+ </Directory>
+ </IfModule>
+
+ AllowEncodedSlashes On
+
+ ErrorLog /var/log/<%= node['apache']['package'] %>/error.log
+ CustomLog /var/log/<%= node['apache']['package'] %>/rgw-access.log proxy_combined
+ ServerSignature Off
+</VirtualHost>
--- /dev/null
+#!/bin/sh
+exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n <%= @ceph_rgw_client %>