Implement ringbuilder
This commit adds a class, defined resources and native types that can be used together to manage the creation, configuration, and rebalancing of rings. Creates the following native types: ring_account_device ring_container_device ring_object_device The implementation of these types is provided by swift-ring-builder and most of the functionality is provided by the parent provider (SwiftRingBuilder) Each of the providers is hard-coded to find the relevent ring database in /etc/swift. This directory location can currently not be configured. Each provider implements self.instances so the current state can of the ring can be queried from puppet. These providers do not handle either the creation or the rebalancing of the rings, they are intended to be used in combination with defined resource types that perform that functionality: swift::ringbuilder::create swift::ringbuilder::rebalance The swift::ringbuilder class is also created as a part of this commit. This class does the following: - creates object, account, and container rings (it uses the same parameters to create these rings) - creates the rebalance defines - sets up the following relationships: for each ring type, create should be applied before the native types which should refresh the rebalance
This commit is contained in:
parent
50eaa8e66d
commit
917426380e
lib/puppet
manifests
@ -0,0 +1,15 @@
|
||||
require File.join(File.dirname(__FILE__), '..', 'swift_ring_builder')
|
||||
Puppet::Type.type(:ring_account_device).provide(
|
||||
:swift_ring_builder,
|
||||
:parent => Puppet::Provider::SwiftRingBuilder
|
||||
) do
|
||||
|
||||
optional_commands :swift_ring_builder => 'swift-ring-builder'
|
||||
|
||||
# TODO maybe this should be a parameter eventually so that
|
||||
# it can be configurable
|
||||
def self.builder_file_path
|
||||
'/etc/swift/account.builder'
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,15 @@
|
||||
require File.join(File.dirname(__FILE__), '..', 'swift_ring_builder')
|
||||
Puppet::Type.type(:ring_container_device).provide(
|
||||
:swift_ring_builder,
|
||||
:parent => Puppet::Provider::SwiftRingBuilder
|
||||
) do
|
||||
|
||||
optional_commands :swift_ring_builder => 'swift-ring-builder'
|
||||
|
||||
# TODO maybe this should be a parameter eventually so that
|
||||
# it can be configurable
|
||||
def self.builder_file_path
|
||||
'/etc/swift/container.builder'
|
||||
end
|
||||
|
||||
end
|
15
lib/puppet/provider/ring_object_device/swift_ring_builder.rb
Normal file
15
lib/puppet/provider/ring_object_device/swift_ring_builder.rb
Normal file
@ -0,0 +1,15 @@
|
||||
require File.join(File.dirname(__FILE__), '..', 'swift_ring_builder')
|
||||
Puppet::Type.type(:ring_object_device).provide(
|
||||
:swift_ring_builder,
|
||||
:parent => Puppet::Provider::SwiftRingBuilder
|
||||
) do
|
||||
|
||||
optional_commands :swift_ring_builder => 'swift-ring-builder'
|
||||
|
||||
# TODO maybe this should be a parameter eventually so that
|
||||
# it can be configurable
|
||||
def self.builder_file_path
|
||||
'/etc/swift/object.builder'
|
||||
end
|
||||
|
||||
end
|
126
lib/puppet/provider/swift_ring_builder.rb
Normal file
126
lib/puppet/provider/swift_ring_builder.rb
Normal file
@ -0,0 +1,126 @@
|
||||
class Puppet::Provider::SwiftRingBuilder < Puppet::Provider
|
||||
|
||||
def self.instances
|
||||
# TODO iterate through the databases
|
||||
# and add the database that we used a property
|
||||
ring.keys.collect do |name|
|
||||
new(:name => name)
|
||||
end
|
||||
end
|
||||
|
||||
def self.ring
|
||||
@my_ring ||= lookup_ring
|
||||
end
|
||||
|
||||
def self.lookup_ring
|
||||
object_hash = {}
|
||||
if File.exists?(builder_file_path)
|
||||
swift_ring_builder(builder_file_path).split("\n")[4..-1].each do |row|
|
||||
if row =~ /^\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+\.\d+)\s+(\d+)\s+(-?\d+\.\d+)\s+(\S*)$/
|
||||
object_hash["#{$3}:#{$4}"] = {
|
||||
:id => $1,
|
||||
:zone => $2,
|
||||
:device_name => $5,
|
||||
:weight => $6,
|
||||
:partitions => $7,
|
||||
:balance => $8,
|
||||
:meta => $9
|
||||
}
|
||||
else
|
||||
Puppet.warning("Unexpected line: #{row}")
|
||||
end
|
||||
end
|
||||
end
|
||||
object_hash
|
||||
end
|
||||
|
||||
def ring
|
||||
self.class.ring
|
||||
end
|
||||
|
||||
def builder_file_path
|
||||
self.class.builder_file_path
|
||||
end
|
||||
|
||||
def exists?
|
||||
ring[resource[:name]]
|
||||
end
|
||||
|
||||
def create
|
||||
[:zone, :device_name, :weight].each do |param|
|
||||
raise(Puppet::Error, "#{param} is required") unless resource[param]
|
||||
end
|
||||
swift_ring_builder(
|
||||
builder_file_path,
|
||||
'add',
|
||||
"z#{resource[:zone]}-#{resource[:name]}/#{resource[:device_name]}",
|
||||
resource[:weight]
|
||||
)
|
||||
end
|
||||
|
||||
def id
|
||||
ring[resource[:name]][:id]
|
||||
end
|
||||
|
||||
def id=(id)
|
||||
raise(Puppet::Error, "Cannot assign id, it is immutable")
|
||||
end
|
||||
|
||||
def zone
|
||||
ring[resource[:name]][:zone]
|
||||
end
|
||||
|
||||
# TODO - is updating the zone supported?
|
||||
def zone=(zone)
|
||||
Puppet.warning('Setting zone is not yet supported, I am not even sure if it is supported')
|
||||
end
|
||||
|
||||
def device_name
|
||||
ring[resource[:name]][:device_name]
|
||||
end
|
||||
|
||||
def device_name=(name)
|
||||
Puppet.warning('I think it makes sense to set the name, it is just not yet supported')
|
||||
end
|
||||
|
||||
def weight
|
||||
ring[resource[:name]][:weight]
|
||||
# get the weight
|
||||
end
|
||||
|
||||
def weight=(weight)
|
||||
swift_ring_builder(
|
||||
builder_file_path,
|
||||
'set_weight',
|
||||
"d#{ring[resource[:name]][:id]}",
|
||||
resource[:weight]
|
||||
)
|
||||
# requires a rebalance
|
||||
end
|
||||
|
||||
def partitions
|
||||
ring[resource[:name]][:partitions]
|
||||
end
|
||||
|
||||
def partitions=(part)
|
||||
raise(Puppet::Error, "Cannot set partitions, it is set by rebalancing")
|
||||
end
|
||||
|
||||
def balance
|
||||
ring[resource[:name]][:balance]
|
||||
end
|
||||
|
||||
def balance=(balance)
|
||||
raise(Puppet::Error, "Cannot set balance, it is set by rebalancing")
|
||||
end
|
||||
|
||||
def meta
|
||||
ring[resource[:name]][:meta]
|
||||
end
|
||||
|
||||
def meta=(meta)
|
||||
raise(Puppet::Error, "Cannot set meta, I am not sure if it makes sense or what it is for")
|
||||
end
|
||||
|
||||
end
|
||||
|
30
lib/puppet/type/ring_account_device.rb
Normal file
30
lib/puppet/type/ring_account_device.rb
Normal file
@ -0,0 +1,30 @@
|
||||
Puppet::Type.newtype(:ring_account_device) do
|
||||
require 'ipaddr'
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
validate do |value|
|
||||
address = value.split(':')
|
||||
raise(Puppet::Error, "invalid name #{value}") unless address.size == 2
|
||||
IPAddr.new(address[0])
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:zone)
|
||||
|
||||
newproperty(:device_name)
|
||||
|
||||
newproperty(:weight)
|
||||
|
||||
newproperty(:meta)
|
||||
|
||||
[:id, :partitions, :balance].each do |param|
|
||||
newproperty(param) do
|
||||
validate do |value|
|
||||
raise(Puppet::Error, "#{param} is a read only property, cannot be assigned")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
30
lib/puppet/type/ring_container_device.rb
Normal file
30
lib/puppet/type/ring_container_device.rb
Normal file
@ -0,0 +1,30 @@
|
||||
Puppet::Type.newtype(:ring_container_device) do
|
||||
require 'ipaddr'
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
validate do |value|
|
||||
address = value.split(':')
|
||||
raise(Puppet::Error, "invalid name #{value}") unless address.size == 2
|
||||
IPAddr.new(address[0])
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:zone)
|
||||
|
||||
newproperty(:device_name)
|
||||
|
||||
newproperty(:weight)
|
||||
|
||||
newproperty(:meta)
|
||||
|
||||
[:id, :partitions, :balance].each do |param|
|
||||
newproperty(param) do
|
||||
validate do |value|
|
||||
raise(Puppet::Error, "#{param} is a read only property, cannot be assigned")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
30
lib/puppet/type/ring_object_device.rb
Normal file
30
lib/puppet/type/ring_object_device.rb
Normal file
@ -0,0 +1,30 @@
|
||||
Puppet::Type.newtype(:ring_object_device) do
|
||||
require 'ipaddr'
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
validate do |value|
|
||||
address = value.split(':')
|
||||
raise(Puppet::Error, "invalid name #{value}") unless address.size == 2
|
||||
IPAddr.new(address[0])
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:zone)
|
||||
|
||||
newproperty(:device_name)
|
||||
|
||||
newproperty(:weight)
|
||||
|
||||
newproperty(:meta)
|
||||
|
||||
[:id, :partitions, :balance].each do |param|
|
||||
newproperty(param) do
|
||||
validate do |value|
|
||||
raise(Puppet::Error, "#{param} is a read only property, cannot be assigned")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -1,13 +1,26 @@
|
||||
#
|
||||
# role for deploying
|
||||
#
|
||||
class swift::ringbuider(
|
||||
|
||||
class swift::ringbuilder(
|
||||
$part_power = undef,
|
||||
$replicas = undef,
|
||||
$min_part_hours = undef
|
||||
) {
|
||||
# search for all nodes that have class swift::storage
|
||||
#
|
||||
# determine what their swift drives are (how can I determine this?)
|
||||
#exec {
|
||||
# command =>
|
||||
#}
|
||||
|
||||
Class['swift'] -> Class['swift::ringbuilder']
|
||||
|
||||
swift::ringbuilder::create{ ['object', 'account', 'container']:
|
||||
part_power => $part_power,
|
||||
replicas => $replicas,
|
||||
min_part_hours => $min_part_hours,
|
||||
}
|
||||
|
||||
Swift::Ringbuilder::Create['object'] -> Ring_object_device <| |> ~> Swift::Ringbuilder::Rebalance['object']
|
||||
|
||||
Swift::Ringbuilder::Create['container'] -> Ring_container_device <| |> ~> Swift::Ringbuilder::Rebalance['container']
|
||||
|
||||
Swift::Ringbuilder::Create['account'] -> Ring_account_device <| |> ~> Swift::Ringbuilder::Rebalance['account']
|
||||
|
||||
swift::ringbuilder::rebalance{ ['object', 'account', 'container']: }
|
||||
|
||||
}
|
||||
|
15
manifests/ringbuilder/create.pp
Normal file
15
manifests/ringbuilder/create.pp
Normal file
@ -0,0 +1,15 @@
|
||||
define ringbuilder::create(
|
||||
$part_power = 18,
|
||||
$replicas = 5,
|
||||
$min_part_hours = 1
|
||||
) {
|
||||
|
||||
validate_re($name, '^object|container|account$')
|
||||
|
||||
exec { "create_${name}":
|
||||
command => "swift-ring-builder /etc/swift/${name}.builder create ${part_power} ${replicas} ${min_part_hours}",
|
||||
path => ['/usr/bin'],
|
||||
creates => "/etc/swift/${name}.builder",
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
define ringbuilder::rebalance() {
|
||||
|
||||
validate_re($name, '^object|contianer|account$')
|
||||
|
||||
exec { "rebalance_${name}":
|
||||
command => "swift-ring-builder ${name}.builder rebalance",
|
||||
command => "swift-ring-builder /etc/swift/${name}.builder rebalance",
|
||||
path => ['/usr/bin'],
|
||||
refreshonly => true,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user