crowbar/crowbar-openstack

View on GitHub
chef/cookbooks/swift/recipes/ring-compute.rb

Summary

Maintainability
A
1 hr
Test Coverage
# Copyright 2011, Dell
#
# 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.
#
# Author: andi abes
#

if node.roles.include?("swift-storage") && node[:swift][:devs].nil?
  # We can safely return here because if we're a storage node and have no
  # device yet, then it simply means that we haven't looked for devices yet. It
  # cannot mean that we just have no devices because we raise an exception in
  # that case (see disks recipe).
  Chef::Log.info("Not proceeding with ring compute yet; this chef run is only used to find disks on storage nodes.")
  return
end

include_recipe "swift::rsync"

##
# Assumptions:
#  - The partitions to be used on each node are in node[:swift][:devs]
#  - only nodes which have the swift-storage role assigned are used.

=begin
  http://swift.openstack.org/howto_installmultinode.html

swift-ring-builder account.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6202/$DEVICE $WEIGHT
swift-ring-builder container.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6201/$DEVICE $WEIGHT
swift-ring-builder object.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6200/$DEVICE $WEIGHT

      command  "swift-ring-builder object.builder add z#{zone}-#{storage_ip_addr}:6200/#{disk[:name]} #{weight}"
=end

## collect the nodes that need to be notified when ring files are updated
target_nodes = []

####
# collect the current contents of the ring files.
nodes = node_search_with_cache("roles:swift-storage")

disks_a = []
disks_c = []
disks_o = []

disk_assign_expr = node[:swift][:disk_zone_assign_expr]

nodes.each { |node|
  storage_ip = Swift::Evaluator.get_ip_by_type(node, :storage_ip_expr)
  log ("Looking at node: #{storage_ip}") { level :debug }

  target_nodes << storage_ip

  disks=node[:swift][:devs]
  next if disks.nil?

  disks.each {|uuid,disk|
    Chef::Log.info("Swift - considering #{node[:fqdn]}:#{disk[:name]}")
    next unless disk[:state] == "Operational"

    # we need at least node for which we trying to predict zone to avoid odd searching across chef by disk uuid
    z_o, w_o = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), ring: "object",    disk: disk, target_node: node)
    z_c, w_c = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), ring: "container", disk: disk, target_node: node)
    z_a, w_a = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), ring: "account",   disk: disk, target_node: node)

    log("obj: #{z_o}/#{w_o} container: #{z_c}/#{w_c} account: #{z_a}/#{w_a}. count: #{$DISK_CNT}") { level :info }

    d = { ip: storage_ip, dev_name: disk[:name], port: 6200 }

    if z_o
      d[:port] = 6200
      d[:zone] = z_o
      d[:weight] = w_o
      disks_o << d
    end
    if z_c
      d = d.dup
      d[:port] = 6201
      d[:zone] = z_c
      d[:weight] = w_c
      disks_c << d
    end
    if z_a
      d = d.dup
      d[:port] = 6202
      d[:zone] = z_a
      d[:weight] = w_a
      disks_a << d
    end
  }
}

hash = node[:swift][:cluster_hash]
min_move = node[:swift][:min_part_hours]
parts = node[:swift][:partitions]
replicas = node[:swift][:replicas]
zones = node[:swift][:zones]

log ("cluster config: replicas:#{replicas} zones:#{zones} hash:#{hash}")

swift_ringfile "account.builder" do
  disks disks_a
  replicas replicas
  min_part_hours min_move
  partitions parts
  action [:apply, :rebalance]
end
swift_ringfile "container.builder" do
  disks disks_c
  replicas replicas
  min_part_hours min_move
  partitions parts
  action [:apply, :rebalance]
end
swift_ringfile "object.builder" do
  disks disks_o
  replicas replicas
  min_part_hours min_move
  partitions parts
  action [:apply, :rebalance]
end

proxy_nodes = node_search_with_cache("roles:swift-proxy")
proxy_nodes.each do |p|
  storage_ip = Swift::Evaluator.get_ip_by_type(p, :storage_ip_expr)
  target_nodes << storage_ip
end

target_nodes.uniq!
Chef::Log.debug("nodes to notify: #{target_nodes.join ' '}")

builder_ip = Swift::Evaluator.get_ip_by_type(node, :storage_ip_expr)

target_nodes.each {|t|
  # No point in pushing it to ourselves
  next if t == builder_ip

  execute "push account ring-to #{t}" do
    command "rsync account.ring.gz #{node[:swift][:user]}@#{t}::ring"
    cwd "/etc/swift"
    ignore_failure true
    action :nothing
    subscribes :run, resources(swift_ringfile: "account.builder")
  end
  execute "push container ring-to #{t}" do
    command "rsync container.ring.gz #{node[:swift][:user]}@#{t}::ring"
    cwd "/etc/swift"
    ignore_failure true
    action :nothing
    subscribes :run, resources(swift_ringfile: "container.builder")
  end
  execute "push object ring-to #{t}" do
    command "rsync object.ring.gz #{node[:swift][:user]}@#{t}::ring"
    cwd "/etc/swift"
    ignore_failure true
    action :nothing
    subscribes :run, resources(swift_ringfile: "object.builder")
  end
}