recipes/radosgw_federated.rb (169 lines of code) (raw):

# # Author:: Hans Chris Jones <chris.jones@lambdastack.io> # Cookbook Name:: ceph # # Copyright 2017, Bloomberg Finance L.P. # # 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. # # Federated version of creating keys and setting up radosgw. # NOTE: This recipe *MUST* be included in the 'radosgw' recipe and not used as a stand alone recipe! service_type = node['ceph']['mon']['init_style'] # NOTE: This base_key can also be the bootstrap-rgw key (ceph.keyring) if desired but the default is the admin key. Just change it here. base_key = "/etc/ceph/#{node['ceph']['cluster']}.client.admin.keyring" # NOTE: If multisite-replication == true then one region and more than one zone will need to exist. Can support # additional regions if some base logic is changed below but for now just one zone. # NOTE: If multisite-replication == false then one region and one zone. For example, the one region plus each zone will # create a region-zone combination which is both region and zone so that the same set of data and it's structure can # be used for both scenarios. # NOTE: The region.json file is a little different for no multisite-replication since there is a one-to-one region/zone # combination. The zone.json is the same for both scenarios. if node['ceph']['pools']['radosgw']['federated_enable'] node['ceph']['pools']['radosgw']['federated_zone_instances'].each do |inst| keyring = if node['ceph']['pools']['radosgw']['federated_multisite_replication'] == false "/etc/ceph/#{node['ceph']['cluster']}.client.radosgw.#{inst['region']}-#{inst['name']}.keyring" else "/etc/ceph/#{node['ceph']['cluster']}.client.radosgw.keyring" end file "/var/log/radosgw/#{node['ceph']['cluster']}.client.radosgw.#{inst['region']}-#{inst['name']}.log" do owner node['ceph']['owner'] group node['ceph']['group'] end directory "/var/lib/ceph/radosgw/#{node['ceph']['cluster']}-radosgw.#{inst['region']}-#{inst['name']}" do owner node['ceph']['owner'] group node['ceph']['group'] mode node['ceph']['mode'] recursive true action :create not_if "test -d /var/lib/ceph/radosgw/#{node['ceph']['cluster']}-radosgw.#{inst['region']}-#{inst['name']}" end # Check for existing keys first! new_key = '' ruby_block "check-radosgw-secret-#{inst['name']}" do block do fetch = Mixlib::ShellOut.new("sudo ceph auth get-key client.radosgw.#{inst['region']}-#{inst['name']} 2>/dev/null") fetch.run_command key = fetch.stdout unless key.to_s.strip.empty? new_key = ceph_chef_save_radosgw_inst_secret(key, "#{inst['region']}-#{inst['name']}") end end end # If an initial key exists then this will run - for shared keyring file unless !new_key.to_s.strip.empty? new_key = ceph_chef_radosgw_inst_secret("#{inst['region']}-#{inst['name']}") # One last sanity check on the key new_key = nil if new_key.to_s.strip.length != 40 end execute 'update-ceph-radosgw-secret' do command lazy { "sudo ceph-authtool #{keyring} --name=client.radosgw.#{inst['region']}-#{inst['name']} --add-key=#{new_key} --cap osd 'allow rwx' --cap mon 'allow rwx'" } only_if { !new_key.to_s.strip.empty? } only_if "test -s #{keyring}" sensitive true if Chef::Resource::Execute.method_defined? :sensitive end execute 'write-ceph-radosgw-secret' do command lazy { "sudo ceph-authtool #{keyring} --create-keyring --name=client.radosgw.#{inst['region']}-#{inst['name']} --add-key=#{new_key} --cap osd 'allow rwx' --cap mon 'allow rwx'" } only_if { !new_key.to_s.strip.empty? } not_if "test -s #{keyring}" sensitive true if Chef::Resource::Execute.method_defined? :sensitive end # If no initial key exists then this will run execute 'generate-client-radosgw-secret' do command <<-EOH sudo ceph-authtool --create-keyring #{keyring} -n client.radosgw.#{inst['region']}-#{inst['name']} --gen-key --cap osd 'allow rwx' --cap mon 'allow rwx' EOH creates keyring not_if { ceph_chef_radosgw_inst_secret("#{inst['region']}-#{inst['name']}") } not_if "test -s #{keyring}" notifies :create, "ruby_block[save-radosgw-secret-#{inst['name']}]", :immediately sensitive true if Chef::Resource::Execute.method_defined? :sensitive end # Allow all zone keys execute 'update-client-radosgw-secret' do command <<-EOH sudo ceph-authtool #{keyring} -n client.radosgw.#{inst['region']}-#{inst['name']} --gen-key --cap osd 'allow rwx' --cap mon 'allow rwx' EOH not_if "sudo grep client.radosgw.#{inst['region']}-#{inst['name']} #{keyring}" sensitive true if Chef::Resource::Execute.method_defined? :sensitive end execute "update-client-radosgw-#{inst['region']}-#{inst['name']}-auth" do command <<-EOH sudo ceph -k #{base_key} auth add client.radosgw.#{inst['region']}-#{inst['name']} -i #{keyring} EOH not_if "ceph auth list | grep client.radosgw.#{inst['region']}-#{inst['name']}" sensitive true if Chef::Resource::Execute.method_defined? :sensitive end # Saves the key to the current node attribute ruby_block "save-radosgw-secret-#{inst['name']}" do block do fetch = Mixlib::ShellOut.new("sudo ceph-authtool #{keyring} -n client.radosgw.#{inst['region']}-#{inst['name']} --print-key") fetch.run_command key = fetch.stdout ceph_chef_save_radosgw_inst_secret(key.delete!("\n"), "#{inst['region']}-#{inst['name']}") end action :nothing end # Add the region and zone files and remove the default root pools if node['ceph']['pools']['radosgw']['federated_multisite_replication'] == true template "/etc/ceph/#{inst['region']}-region.json" do source 'radosgw-federated-region.json.erb' not_if "test -s /etc/ceph/#{inst['region']}-region.json" end template "/etc/ceph/#{inst['region']}-region-map.json" do source 'radosgw-federated-region-map.json.erb' not_if "test -s /etc/ceph/#{inst['region']}-region-map.json" end region_file = "/etc/ceph/#{inst['region']}-region.json" region_map_file = "/etc/ceph/#{inst['region']}-region-map.json" region = (inst['region']).to_s zone = (inst['name']).to_s else template "/etc/ceph/#{inst['region']}-#{inst['name']}-region.json" do source 'radosgw-federated-no-replication-region.json.erb' variables lazy { { :region => (inst['region']).to_s, :zone => (inst['name']).to_s, :zone_url => (inst['url']).to_s, :zone_port => (inst['port']).to_s } } not_if "test -s /etc/ceph/#{inst['region']}-#{inst['name']}-region.json" end template "/etc/ceph/#{inst['region']}-#{inst['name']}-region-map.json" do source 'radosgw-federated-no-replication-region-map.json.erb' variables lazy { { :region => (inst['region']).to_s, :zone => (inst['name']).to_s, :zone_url => (inst['url']).to_s, :zone_port => (inst['port']).to_s } } not_if "test -s /etc/ceph/#{inst['region']}-#{inst['name']}-region-map.json" end region_file = "/etc/ceph/#{inst['region']}-#{inst['name']}-region.json" region_map_file = "/etc/ceph/#{inst['region']}-#{inst['name']}-region-map.json" region = "#{inst['region']}-#{inst['name']}" zone = "#{inst['region']}-#{inst['name']}" end if node['ceph']['pools']['radosgw']['federated_enable_regions_zones'] template "/etc/ceph/#{zone}-zone.json" do source 'radosgw-federated-zone.json.erb' variables lazy { { :region => (inst['region']).to_s, :zone => (inst['name']).to_s, :secret_key => '', :access_key => '' } } not_if "test -s /etc/ceph/#{zone}-zone.json" end execute "region-set-#{inst['region']}" do command <<-EOH sudo radosgw-admin region set --infile #{region_file} --rgw-region #{region} --name client.radosgw.#{inst['region']}-#{inst['name']} EOH # not_if "sudo radosgw-admin region list --name client.radosgw.#{inst['region']}-#{inst['name']} | grep #{inst['region']}" end execute "region-map-set-#{inst['region']}" do command <<-EOH sudo radosgw-admin region-map set --infile #{region_map_file} --rgw-region #{region} --name client.radosgw.#{inst['region']}-#{inst['name']} EOH # not_if "sudo radosgw-admin region-map get --name client.radosgw.#{inst['region']}-#{inst['name']} | grep #{inst['region']}" end # execute 'remove-default-region' do # command lazy { "rados -p .#{inst['region']}.rgw.root rm region_info.default" } # ignore_failure true # not_if "rados -p .#{inst['region']}.rgw.root ls | grep region_info.default" # end # execute 'remove-default-zone' do # command lazy { "rados -p .#{inst['region']}-#{inst['name']}.rgw.root rm zone_info.default" } # ignore_failure true # not_if "rados -p .#{inst['region']}-#{inst['name']}.rgw.root ls | grep zone_info.default" # end execute "zone-set-#{inst['name']}" do command <<-EOH sudo radosgw-admin zone set --rgw-zone=#{inst['region']}-#{inst['name']} --infile /etc/ceph/#{zone}-zone.json --name client.radosgw.#{inst['region']}-#{inst['name']} EOH # not_if "sudo radosgw-admin zone list --name client.radosgw.#{inst['region']}-#{inst['name']} | grep #{inst['name']}" end execute "create-region-defaults-#{inst['region']}" do command <<-EOH sudo radosgw-admin region default --rgw-region=#{region} --name client.radosgw.#{inst['region']}-#{inst['name']} sudo radosgw-admin region-map update --rgw-region #{region} --name client.radosgw.#{inst['region']}-#{inst['name']} EOH end end # execute "update-regionmap-#{inst['name']}" do # command <<-EOH # sudo radosgw-admin regionmap update --name client.radosgw.#{inst['region']}-#{inst['name']} # EOH # end # FUTURE: Update the keys for the zones. This will allow each one to sync with the other. # ceph_chef_secure_password(20) # ceph_chef_secure_password(40) # Will need to create radosgw-admin user with --system so that each zone has a system user so that they can # communicate with each other for replication # This is only here as part of completeness. The service_type is not really needed because of defaults. ruby_block "radosgw-finalize-#{inst['name']}" do block do ['done', service_type].each do |ack| ::File.open("/var/lib/ceph/radosgw/#{node['ceph']['cluster']}-radosgw.#{inst['region']}-#{inst['name']}/#{ack}", 'w').close end end not_if "test -f /var/lib/ceph/radosgw/#{node['ceph']['cluster']}-radosgw.#{inst['region']}-#{inst['name']}/done" end end end