Pull in att-cloud swift cookbook (forked from rcbops)
Change-Id: Icdee121c28a2fce0261b567eceaab4d46fd0b64c
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Berksfile.lock
|
||||
validation.pem
|
||||
metadata.json
|
||||
*~
|
||||
.bundle/
|
||||
cookbooks/
|
||||
.cookbooks
|
||||
.vagrant
|
||||
*.swp
|
7
Berksfile
Normal file
7
Berksfile
Normal file
@@ -0,0 +1,7 @@
|
||||
site :opscode
|
||||
|
||||
cookbook 'swift', :path => '.'
|
||||
cookbook 'apt', :git => 'git://github.com/opscode-cookbooks/apt.git'
|
||||
cookbook 'statsd', :git => 'git://github.com/att-cloud/cookbook-statsd.git'
|
||||
cookbook 'memcached'
|
||||
cookbook 'sysctl'
|
9
Gemfile
Normal file
9
Gemfile
Normal file
@@ -0,0 +1,9 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "chef", "~> 11.4.4"
|
||||
gem "json", "<= 1.7.7" # chef dependency
|
||||
gem "berkshelf", "~> 1.4.5"
|
||||
gem "chefspec", "~> 1.3.0"
|
||||
gem "foodcritic"
|
||||
gem "strainer"
|
||||
gem "webmock", "~> 1.11.0"
|
202
Gemfile.lock
Normal file
202
Gemfile.lock
Normal file
@@ -0,0 +1,202 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.2.13)
|
||||
i18n (= 0.6.1)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.4)
|
||||
akami (1.2.0)
|
||||
gyoku (>= 0.4.0)
|
||||
nokogiri (>= 1.4.0)
|
||||
berkshelf (1.4.5)
|
||||
activesupport (>= 3.2.0)
|
||||
addressable
|
||||
celluloid (>= 0.14.0)
|
||||
chozo (>= 0.6.1)
|
||||
faraday (>= 0.8.5)
|
||||
hashie (>= 2.0.2)
|
||||
json (>= 1.5.0)
|
||||
minitar
|
||||
mixlib-config (~> 1.1)
|
||||
mixlib-shellout (~> 1.1)
|
||||
multi_json (~> 1.5)
|
||||
retryable
|
||||
ridley (~> 0.12.4)
|
||||
solve (>= 0.4.2)
|
||||
thor (~> 0.18.0)
|
||||
yajl-ruby
|
||||
builder (3.2.0)
|
||||
celluloid (0.14.0)
|
||||
timers (>= 1.0.0)
|
||||
chef (11.4.4)
|
||||
erubis
|
||||
highline (>= 1.6.9)
|
||||
json (>= 1.4.4, <= 1.7.7)
|
||||
mixlib-authentication (>= 1.3.0)
|
||||
mixlib-cli (~> 1.3.0)
|
||||
mixlib-config (>= 1.1.2)
|
||||
mixlib-log (>= 1.3.0)
|
||||
mixlib-shellout
|
||||
net-ssh (~> 2.6)
|
||||
net-ssh-multi (~> 1.1.0)
|
||||
ohai (>= 0.6.0)
|
||||
rest-client (>= 1.0.4, < 1.7.0)
|
||||
yajl-ruby (~> 1.1)
|
||||
chefspec (1.3.0)
|
||||
chef (>= 10.0)
|
||||
erubis
|
||||
fauxhai (>= 0.1.1, < 2.0)
|
||||
minitest-chef-handler (>= 0.6.0)
|
||||
rspec (~> 2.0)
|
||||
chozo (0.6.1)
|
||||
activesupport (>= 3.2.0)
|
||||
hashie (>= 2.0.2)
|
||||
multi_json (>= 1.3.0)
|
||||
ci_reporter (1.8.4)
|
||||
builder (>= 2.1.2)
|
||||
crack (0.3.2)
|
||||
diff-lcs (1.2.4)
|
||||
erubis (2.7.0)
|
||||
faraday (0.8.7)
|
||||
multipart-post (~> 1.1)
|
||||
fauxhai (1.1.1)
|
||||
httparty
|
||||
net-ssh
|
||||
ohai
|
||||
ffi (1.8.1)
|
||||
foodcritic (2.1.0)
|
||||
erubis
|
||||
gherkin (~> 2.11.7)
|
||||
nokogiri (~> 1.5.4)
|
||||
rak (~> 1.4)
|
||||
treetop (~> 1.4.10)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
gherkin (2.11.8)
|
||||
multi_json (~> 1.3)
|
||||
gssapi (1.0.3)
|
||||
ffi (>= 1.0.1)
|
||||
gyoku (1.0.0)
|
||||
builder (>= 2.1.2)
|
||||
hashie (2.0.5)
|
||||
highline (1.6.19)
|
||||
httparty (0.11.0)
|
||||
multi_json (~> 1.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
httpclient (2.2.0.2)
|
||||
httpi (0.9.7)
|
||||
rack
|
||||
i18n (0.6.1)
|
||||
ipaddress (0.8.0)
|
||||
json (1.7.7)
|
||||
little-plugger (1.1.3)
|
||||
logging (1.6.2)
|
||||
little-plugger (>= 1.1.3)
|
||||
mime-types (1.23)
|
||||
minitar (0.5.4)
|
||||
minitest (4.7.4)
|
||||
minitest-chef-handler (1.0.1)
|
||||
chef
|
||||
ci_reporter
|
||||
minitest (~> 4.7.3)
|
||||
mixlib-authentication (1.3.0)
|
||||
mixlib-log
|
||||
mixlib-cli (1.3.0)
|
||||
mixlib-config (1.1.2)
|
||||
mixlib-log (1.6.0)
|
||||
mixlib-shellout (1.1.0)
|
||||
multi_json (1.7.4)
|
||||
multi_xml (0.5.4)
|
||||
multipart-post (1.2.0)
|
||||
net-http-persistent (2.8)
|
||||
net-ssh (2.6.7)
|
||||
net-ssh-gateway (1.2.0)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh-multi (1.1)
|
||||
net-ssh (>= 2.1.4)
|
||||
net-ssh-gateway (>= 0.99.0)
|
||||
nokogiri (1.5.9)
|
||||
nori (1.1.5)
|
||||
ohai (6.16.0)
|
||||
ipaddress
|
||||
mixlib-cli
|
||||
mixlib-config
|
||||
mixlib-log
|
||||
mixlib-shellout
|
||||
systemu
|
||||
yajl-ruby
|
||||
polyglot (0.3.3)
|
||||
rack (1.5.2)
|
||||
rak (1.4)
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
retryable (1.3.3)
|
||||
ridley (0.12.4)
|
||||
addressable
|
||||
celluloid (~> 0.14.0)
|
||||
chozo (>= 0.6.0)
|
||||
erubis
|
||||
faraday (>= 0.8.4)
|
||||
hashie (>= 2.0.2)
|
||||
mixlib-authentication (>= 1.3.0)
|
||||
mixlib-config (>= 1.1.0)
|
||||
mixlib-log (>= 1.3.0)
|
||||
mixlib-shellout (>= 1.1.0)
|
||||
net-http-persistent (>= 2.8)
|
||||
net-ssh
|
||||
retryable
|
||||
solve (>= 0.4.4)
|
||||
winrm (~> 1.1.0)
|
||||
rspec (2.13.0)
|
||||
rspec-core (~> 2.13.0)
|
||||
rspec-expectations (~> 2.13.0)
|
||||
rspec-mocks (~> 2.13.0)
|
||||
rspec-core (2.13.1)
|
||||
rspec-expectations (2.13.0)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.13.1)
|
||||
rubyntlm (0.1.1)
|
||||
savon (0.9.5)
|
||||
akami (~> 1.0)
|
||||
builder (>= 2.1.2)
|
||||
gyoku (>= 0.4.0)
|
||||
httpi (~> 0.9)
|
||||
nokogiri (>= 1.4.0)
|
||||
nori (~> 1.0)
|
||||
wasabi (~> 1.0)
|
||||
solve (0.4.4)
|
||||
json
|
||||
strainer (2.1.0)
|
||||
berkshelf (~> 1.3)
|
||||
systemu (2.5.2)
|
||||
thor (0.18.1)
|
||||
timers (1.1.0)
|
||||
treetop (1.4.12)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
uuidtools (2.1.4)
|
||||
wasabi (1.0.0)
|
||||
nokogiri (>= 1.4.0)
|
||||
webmock (1.11.0)
|
||||
addressable (>= 2.2.7)
|
||||
crack (>= 0.3.2)
|
||||
winrm (1.1.2)
|
||||
gssapi (~> 1.0.0)
|
||||
httpclient (~> 2.2.0.2)
|
||||
logging (~> 1.6.1)
|
||||
nokogiri (~> 1.5.0)
|
||||
rubyntlm (~> 0.1.1)
|
||||
savon (= 0.9.5)
|
||||
uuidtools (~> 2.1.2)
|
||||
yajl-ruby (1.1.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
berkshelf (~> 1.4.5)
|
||||
chef (~> 11.4.4)
|
||||
chefspec (~> 1.3.0)
|
||||
foodcritic
|
||||
json (<= 1.7.7)
|
||||
strainer
|
||||
webmock (~> 1.11.0)
|
234
README.md
234
README.md
@@ -1,37 +1,260 @@
|
||||
Description
|
||||
===========
|
||||
|
||||
Installs the OpenStack Object Storage service **Swift** as part of the OpenStack reference deployment Chef for OpenStack. The http://github.com/mattray/chef-openstack-repo contains documentation for using this cookbook in the context of a full OpenStack deployment. Swift is currently installed from packages.
|
||||
Installs the OpenStack Object Storage service **Swift** as part of the OpenStack reference deployment Chef for OpenStack. The http://github.com/stackforge/chef-openstack-repo contains documentation for using this cookbook in the context of a full OpenStack deployment. Swift is currently installed from packages.
|
||||
|
||||
https://wiki.openstack.org/wiki/Swift
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
Clients
|
||||
--------
|
||||
|
||||
* CentOS >= 6.3
|
||||
* Ubuntu >= 12.04
|
||||
|
||||
Chef
|
||||
---------
|
||||
|
||||
* 11.4.4
|
||||
|
||||
Cookbooks
|
||||
---------
|
||||
|
||||
Usage
|
||||
* memcached
|
||||
* sysctl
|
||||
|
||||
Roles
|
||||
=====
|
||||
|
||||
* swift-account-server - storage node for account data
|
||||
* swift-container-server - storage node for container data
|
||||
* swift-object-server - storage node for object server
|
||||
* swift-proxy-server - proxy for swift storge nodes
|
||||
* swift-setup - server responsible for generating initial settings
|
||||
* swift-management-server - responsible for ring generation
|
||||
|
||||
The swift-management-server role performs the following functions:
|
||||
|
||||
* proxy node that knows super admin password
|
||||
* ring repository and ring building workstation
|
||||
* generally always has the swift-setup role too
|
||||
* there can only be _one_ swift-management-server
|
||||
|
||||
There *must* be node with the the swift-managment-server role to act
|
||||
as the ring repository.
|
||||
|
||||
In small environments, it is likely that all storage machines will
|
||||
have all-in-one roles, with a load balancer ahead of it
|
||||
|
||||
In larger environments, where it is cost effective to split the proxy
|
||||
and storage layer, storage nodes will carry
|
||||
swift-{account,container,object}-server roles, and there will be
|
||||
dedicated hosts with the swift-proxy-server role.
|
||||
|
||||
In really really huge environments, it's possible that the storage
|
||||
node will be split into swift-{container,accout}-server nodes and
|
||||
swift-object-server nodes.
|
||||
|
||||
|
||||
Attributes
|
||||
==========
|
||||
|
||||
* ```default[:swift][:authmode]``` - "swauth" or "keystone" (default "swauth"). Right now, only swauth is supported (defaults to swauth)
|
||||
|
||||
* ```default[:swift][:swift_secret_databag_name]``` - this cookbook supports an optional secret databag where we will retrieve the following attributes overriding any default attributes below. (defaults to nil)
|
||||
|
||||
```
|
||||
{
|
||||
"id": "swift_dal2",
|
||||
"swift_hash": "1a7c0568fa84"
|
||||
"swift_authkey": "keY4all"
|
||||
"dispersion_auth_user": "ops:dispersion",
|
||||
"dispersion_auth_key": "dispersionpass"
|
||||
}
|
||||
```
|
||||
|
||||
* ```default[:swift][:swift_hash]``` - swift_hash_path_suffix in /etc/swift/swift.conf (defaults to 107c0568ea84)
|
||||
|
||||
* ```default[:swift][:audit_hour]``` - Hour to run swift_auditor on storage nodes (defaults to 5)
|
||||
|
||||
* ```default[:swift][:disk_enum_expr]``` - Eval-able expression that lists
|
||||
candidate disk nodes for disk probing. The result shoule be a hash
|
||||
with keys being the device name (without the leading "/dev/") and a
|
||||
hash block of any extra info associated with the device. For
|
||||
example: { "sdc" => { "model": "Hitachi 7K3000" }}. Largely,
|
||||
though, if you are going to make a list of valid devices, you
|
||||
probably know all the valid devices, and don't need to pass any
|
||||
metadata about them, so { "sdc" => {}} is probably enough. Example
|
||||
expression: Hash[('a'..'f').to_a.collect{|x| [ "sd{x}", {} ]}]
|
||||
|
||||
* ```default[:swift][:ring][:part_power]``` - controls the size of the ring (defaults to 18)
|
||||
|
||||
* ```default[:swift][:ring][:min_part_hours]``` - the minimum number of hours before swift is allowed to migrate a partition (defaults to 1)
|
||||
|
||||
* ```default[:swift][:ring][:replicas]``` - how many replicas swift should retain (defaults to 3)
|
||||
|
||||
* ```default[:swift][:disk_test_filter]``` - an array of expressions that must
|
||||
all be true in order a block deviced to be considered for
|
||||
formatting and inclusion in the cluster. Each rule gets evaluated
|
||||
with "candidate" set to the device name (without the leading
|
||||
"/dev/") and info set to the node hash value. Default rules:
|
||||
|
||||
* "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~
|
||||
/vd[^a]/"
|
||||
|
||||
* "File.exists?('/dev/ + candidate)"
|
||||
|
||||
* "not system('/sbin/sfdisk -V /dev/' + candidate + '>/dev/null 2>&2')"
|
||||
|
||||
* "info['removable'] = 0" ])
|
||||
|
||||
* ```default[:swift][:expected_disks]``` - an array of device names that the
|
||||
operator expecs to be identified by the previous two values. This
|
||||
acts as a second-check on discovered disks. If this array doesn't
|
||||
match the found disks, then chef processing will be stopped.
|
||||
Example: ("b".."f").collect{|x| "sd#{x}"}. Default: none.
|
||||
|
||||
There are other attributes that must be set depending on authmode.
|
||||
For "swauth", the following attributes are used:
|
||||
|
||||
* ```default[:swift][:authkey]``` - swauth super admin key if using swauth (defaults to test)
|
||||
|
||||
In addition, because swift is typically deployed as a cluster
|
||||
there are some attributes used to find interfaces and ip addresses
|
||||
on storage nodes:
|
||||
|
||||
* ```default[:swift][:git_builder_ip]``` - the IP address of the management server which other cluster members will use as their git pull target for ring updates (defaults to 127.0.0.1)
|
||||
* ```default[:swift][:network][:proxy-bind-ip]``` - the IP address to bind to
|
||||
on the proxy servers (defaults to 0.0.0.0 for all addresses)
|
||||
* ```default[:swift][:network][:proxy-bind-port]``` - the port to bind to
|
||||
on the proxy servers (defaults to 8080)
|
||||
* ```default[:swift][:network][:account-bind-ip]``` - the IP address to bind to
|
||||
on the account servers (defaults to 0.0.0.0 for all addresses)
|
||||
* ```default[:swift][:network][:account-bind-port]``` - the port to bind to
|
||||
on the account servers (defaults to 6002)
|
||||
* ```default[:swift][:network][:container-bind-ip]``` - the IP address to bind to
|
||||
on the container servers (defaults to 0.0.0.0 for all addresses)
|
||||
* ```default[:swift][:network][:container-bind-port]``` - the port to bind to
|
||||
on the container servers (defaults to 6002)
|
||||
* ```default[:swift][:network][:object-bind-ip]``` - the IP address to bind to
|
||||
on the object servers (defaults to 0.0.0.0 for all addresses)
|
||||
* ```default[:swift][:network][:object-bind-port]``` - the port to bind to
|
||||
on the container servers (defaults to 6002)
|
||||
* ```default[:swift][:network][:object-cidr]``` - the CIDR network for your object
|
||||
servers in order to build the ring (defaults to 10.0.0.0/24)
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Example environment
|
||||
-------------------
|
||||
|
||||
```json
|
||||
{
|
||||
"default_attributes": {
|
||||
"swift": {
|
||||
"swift_hash": "107c0568ea84",
|
||||
"authmode": "swauth",
|
||||
"authkey": "test"
|
||||
"auto_rebuild_rings": false
|
||||
"git_builder_ip": "10.0.0.10"
|
||||
"swauth": {
|
||||
"url": "http://10.0.0.10:8080/v1/"
|
||||
}
|
||||
},
|
||||
},
|
||||
"name": "swift",
|
||||
"chef_type": "environment",
|
||||
"json_class": "Chef::Environment"
|
||||
}
|
||||
```
|
||||
|
||||
This sets up defaults for a swauth-based cluster with the storage
|
||||
network on 10.0.0.0/24.
|
||||
|
||||
Example all-in-one
|
||||
--------------------------
|
||||
|
||||
Example all-in-one storage node config (note there should only ever be
|
||||
one node with the swift-setup and swift-management roles)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "storage1",
|
||||
"name": "storage1",
|
||||
"json_class": "Chef::Node",
|
||||
"run_list": [
|
||||
"role[swift-setup]",
|
||||
"role[swift-management-server]",
|
||||
"role[swift-account-server]",
|
||||
"role[swift-object-server]",
|
||||
"role[swift-container-server]",
|
||||
"role[swift-proxy-server]"
|
||||
],
|
||||
"chef_environment": "development",
|
||||
"normal": {
|
||||
"swift": {
|
||||
"zone": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Standalone Storage Server
|
||||
-------------------------
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "swift-object-server",
|
||||
"json_class": "Chef::Role",
|
||||
"run_list": [
|
||||
"recipe[swift::object-server]"
|
||||
],
|
||||
"description": "A storage server role.",
|
||||
"chef_type": "role"
|
||||
}
|
||||
```
|
||||
|
||||
Standalone Proxy Server
|
||||
-----------------------
|
||||
|
||||
```json
|
||||
"run_list": [
|
||||
"role[swift-proxy-server]"
|
||||
]
|
||||
```
|
||||
|
||||
Testing
|
||||
=====
|
||||
=======
|
||||
|
||||
This cookbook is using [ChefSpec](https://github.com/acrmp/chefspec) for testing. Run the following before commiting. It will run your tests, and check for lint errors.
|
||||
|
||||
$ ./run_tests.bash
|
||||
|
||||
There is also a Vagrant test environment that you can launch in order to integration
|
||||
test this cookbook. See the <a href="tests/README.md" target="_blank">tests/README.md</a> file for more information on launching the environment.
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
$ bundle install
|
||||
$ bundle exec berks install
|
||||
$ bundle exec strainer test
|
||||
|
||||
License and Author
|
||||
==================
|
||||
|
||||
| | |
|
||||
|:---------------------|:---------------------------------------------------|
|
||||
| **Author** | Matt Ray (<matt@opscode.com>) |
|
||||
| **Authors** | Alan Meadows (<am240k@att.com>) |
|
||||
| | Oisin Feely (<of3434@att.com>) |
|
||||
| | Ron Pedde (<ron.pedde@rackspace.com>) |
|
||||
| | Will Kelly (<will.kelly@rackspace.com>) |
|
||||
| | |
|
||||
| **Copyright** | Copyright (c) 2013, Opscode, Inc. |
|
||||
| **Copyright** | Copyright (c) 2013, AT&T, Inc. |
|
||||
| | Copyright (c) 2012, Rackspace US, Inc. |
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -44,3 +267,4 @@ 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.
|
||||
|
||||
|
4
Strainerfile
Normal file
4
Strainerfile
Normal file
@@ -0,0 +1,4 @@
|
||||
# Strainerfile
|
||||
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
|
194
attributes/default.rb
Normal file
194
attributes/default.rb
Normal file
@@ -0,0 +1,194 @@
|
||||
#--------------------
|
||||
# node/ring settings
|
||||
#--------------------
|
||||
|
||||
default["swift"]["state"] = {}
|
||||
default["swift"]["swift_hash"] = "107c0568ea84"
|
||||
default["swift"]["audit_hour"] = "5"
|
||||
default["swift"]["disk_enum_expr"] = "node[:block_device]"
|
||||
default["swift"]["auto_rebuild_rings"] = false
|
||||
default["swift"]["git_builder_ip"] = "127.0.0.1"
|
||||
|
||||
# the release only has any effect on ubuntu, and must be
|
||||
# a valid release on http://ubuntu-cloud.archive.canonical.com/ubuntu
|
||||
default["swift"]["release"] = "folsom"
|
||||
|
||||
# we support an optional secret databag where we will retrieve the
|
||||
# following attributes overriding any default attributes here
|
||||
#
|
||||
# {
|
||||
# "id": "swift_dal2",
|
||||
# "swift_hash": "107c0568ea84"
|
||||
# "swift_authkey": "keW4all"
|
||||
# "dispersion_auth_user": "test:test",
|
||||
# "dispersion_auth_key": "test"
|
||||
# }
|
||||
default["swift"]["swift_secret_databag_name"] = nil
|
||||
|
||||
#--------------------
|
||||
# authentication
|
||||
#--------------------
|
||||
|
||||
default["swift"]["authmode"] = "swauth"
|
||||
default["swift"]["authkey"] = "test"
|
||||
default["swift"]["swift_url"] = "http://127.0.0.1:8080/v1/"
|
||||
default["swift"]["swauth_url"] = "http://127.0.0.1:8080/v1/"
|
||||
default["swift"]["auth_url"] = "http://127.0.0.1:8080/auth/v1.0"
|
||||
|
||||
#---------------------
|
||||
# dispersion settings
|
||||
#---------------------
|
||||
|
||||
default["swift"]["dispersion"]["auth_user"] = "test:test"
|
||||
default["swift"]["dispersion"]["auth_key"] = "test"
|
||||
|
||||
|
||||
# settings for the swift ring - these default settings are
|
||||
# a safe setting for testing but part_power should be set to
|
||||
# 26 in production to allow a swift cluster with 50,000 spindles
|
||||
default["swift"]["ring"]["part_power"] = 18
|
||||
default["swift"]["ring"]["min_part_hours"] = 1
|
||||
default["swift"]["ring"]["replicas"] = 3
|
||||
|
||||
#------------------
|
||||
# statistics
|
||||
#------------------
|
||||
default["swift"]["enable_statistics"] = true
|
||||
|
||||
#------------------
|
||||
# network settings
|
||||
#------------------
|
||||
|
||||
# the cidr configuration items are unimportant for a single server
|
||||
# configuration, but in a multi-server setup, the cidr should match
|
||||
# the interface appropriate to that service as they are used to
|
||||
# resolve the appropriate addresses to use for internode
|
||||
# communication
|
||||
|
||||
# proxy servers
|
||||
default["swift"]["network"]["proxy-bind-ip"] = "0.0.0.0"
|
||||
default["swift"]["network"]["proxy-bind-port"] = "8080"
|
||||
default["swift"]["network"]["proxy-cidr"] = "10.0.0.0/24"
|
||||
|
||||
# account servers
|
||||
default["swift"]["network"]["account-bind-ip"] = "0.0.0.0"
|
||||
default["swift"]["network"]["account-bind-port"] = "6002"
|
||||
|
||||
# container servers
|
||||
default["swift"]["network"]["container-bind-ip"] = "0.0.0.0"
|
||||
default["swift"]["network"]["container-bind-port"] = "6001"
|
||||
|
||||
# object servers
|
||||
default["swift"]["network"]["object-bind-ip"] = "0.0.0.0"
|
||||
default["swift"]["network"]["object-bind-port"] = "6000"
|
||||
default["swift"]["network"]["object-cidr"] = "10.0.0.0/24"
|
||||
|
||||
#------------------
|
||||
# sysctl
|
||||
#------------------
|
||||
|
||||
# set sysctl properties for time waits
|
||||
default['sysctl']['params']['net']['ipv4']['tcp_tw_recycle'] = 1
|
||||
default['sysctl']['params']['net']['ipv4']['tcp_tw_reuse'] = 1
|
||||
default['sysctl']['params']['net']['ipv4']['tcp_syncookies'] = 0
|
||||
|
||||
# N.B. conntrack_max may also need to be adjusted if
|
||||
# server is running a stateful firewall
|
||||
|
||||
#------------------
|
||||
# disk search
|
||||
#------------------
|
||||
|
||||
# disk_test_filter is an array of predicates to test against disks to
|
||||
# determine if a disk should be formatted and configured for swift.
|
||||
# Each predicate is evaluated in turn, and a false from the predicate
|
||||
# will result in the disk not being considered as a candidate for
|
||||
# formatting.
|
||||
default["swift"]["disk_test_filter"] = [ "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~ /vd[^a]/ or candidate =~ /xvd[^a]/",
|
||||
"File.exist?('/dev/' + candidate)",
|
||||
"not system('/sbin/parted /dev/' + candidate + ' -s print | grep linux-swap')",
|
||||
"not info.has_key?('removable') or info['removable'] == 0.to_s" ]
|
||||
|
||||
#------------------
|
||||
# packages
|
||||
#------------------
|
||||
|
||||
|
||||
# Leveling between distros
|
||||
case platform
|
||||
when "redhat"
|
||||
default["swift"]["platform"] = {
|
||||
"disk_format" => "ext4",
|
||||
"proxy_packages" => ["openstack-swift-proxy", "sudo", "cronie", "python-memcached"],
|
||||
"object_packages" => ["openstack-swift-object", "sudo", "cronie"],
|
||||
"container_packages" => ["openstack-swift-container", "sudo", "cronie"],
|
||||
"account_packages" => ["openstack-swift-account", "sudo", "cronie"],
|
||||
"swift_packages" => ["openstack-swift", "sudo", "cronie"],
|
||||
"swauth_packages" => ["openstack-swauth", "sudo", "cronie"],
|
||||
"rsync_packages" => ["rsync"],
|
||||
"git_packages" => ["xinetd", "git", "git-daemon"],
|
||||
"service_prefix" => "openstack-",
|
||||
"service_suffix" => "",
|
||||
"git_dir" => "/var/lib/git",
|
||||
"git_service" => "git",
|
||||
"service_provider" => Chef::Provider::Service::Redhat,
|
||||
"override_options" => ""
|
||||
}
|
||||
#
|
||||
# python-iso8601 is a missing dependency for swift.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=875948
|
||||
when "centos"
|
||||
default["swift"]["platform"] = {
|
||||
"disk_format" => "xfs",
|
||||
"proxy_packages" => ["openstack-swift-proxy", "sudo", "cronie", "python-iso8601", "python-memcached" ],
|
||||
"object_packages" => ["openstack-swift-object", "sudo", "cronie", "python-iso8601" ],
|
||||
"container_packages" => ["openstack-swift-container", "sudo", "cronie", "python-iso8601" ],
|
||||
"account_packages" => ["openstack-swift-account", "sudo", "cronie", "python-iso8601" ],
|
||||
"swift_packages" => ["openstack-swift", "sudo", "cronie", "python-iso8601" ],
|
||||
"swauth_packages" => ["openstack-swauth", "sudo", "cronie", "python-iso8601" ],
|
||||
"rsync_packages" => ["rsync"],
|
||||
"git_packages" => ["xinetd", "git", "git-daemon"],
|
||||
"service_prefix" => "openstack-",
|
||||
"service_suffix" => "",
|
||||
"git_dir" => "/var/lib/git",
|
||||
"git_service" => "git",
|
||||
"service_provider" => Chef::Provider::Service::Redhat,
|
||||
"override_options" => ""
|
||||
}
|
||||
when "fedora"
|
||||
default["swift"]["platform"] = {
|
||||
"disk_format" => "xfs",
|
||||
"proxy_packages" => ["openstack-swift-proxy", "python-memcached"],
|
||||
"object_packages" => ["openstack-swift-object"],
|
||||
"container_packages" => ["openstack-swift-container"],
|
||||
"account_packages" => ["openstack-swift-account"],
|
||||
"swift_packages" => ["openstack-swift"],
|
||||
"swauth_packages" => ["openstack-swauth"],
|
||||
"rsync_packages" => ["rsync"],
|
||||
"git_packages" => ["git", "git-daemon"],
|
||||
"service_prefix" => "openstack-",
|
||||
"service_suffix" => ".service",
|
||||
"git_dir" => "/var/lib/git",
|
||||
"git_service" => "git",
|
||||
"service_provider" => Chef::Provider::Service::Systemd,
|
||||
"override_options" => ""
|
||||
}
|
||||
when "ubuntu"
|
||||
default["swift"]["platform"] = {
|
||||
"disk_format" => "xfs",
|
||||
"proxy_packages" => ["swift-proxy", "python-memcache"],
|
||||
"object_packages" => ["swift-object"],
|
||||
"container_packages" => ["swift-container"],
|
||||
"account_packages" => ["swift-account", "python-swiftclient"],
|
||||
"swift_packages" => ["swift"],
|
||||
"swauth_packages" => ["swauth"],
|
||||
"rsync_packages" => ["rsync"],
|
||||
"git_packages" => ["git-daemon-sysvinit"],
|
||||
"service_prefix" => "",
|
||||
"service_suffix" => "",
|
||||
"git_dir" => "/var/cache/git",
|
||||
"git_service" => "git-daemon",
|
||||
"service_provider" => Chef::Provider::Service::Upstart,
|
||||
"override_options" => "-o Dpkg::Options:='--force-confold' -o Dpkg::Option:='--force-confdef'"
|
||||
}
|
||||
end
|
53
files/default/5EDB1B62EC4926EA
Normal file
53
files/default/5EDB1B62EC4926EA
Normal file
@@ -0,0 +1,53 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1.4.11 (GNU/Linux)
|
||||
|
||||
mQINBFAqSlgBEADPKwXUwqbgoDYgR20zFypxSZlSbrttOKVPEMb0HSUx9Wj8VvNC
|
||||
r+mT4E9wAyq7NTIs5ad2cUhXoyenrjcfGqK6k9R6yRHDbvAxCSWTnJjw7mzsajDN
|
||||
ocXC6THKVW8BSjrh0aOBLpht6d5QCO2vyWxw65FKM65GOsbX03ZngUPMuOuiOEHQ
|
||||
Zo97VSH2pSB+L+B3d9B0nw3QnU8qZMne+nVWYLYRXhCIxSv1/h39SXzHRgJoRUFH
|
||||
vL2aiiVrn88NjqfDW15HFhVJcGOFuACZnRA0/EqTq0qNo3GziQO4mxuZi3bTVL5s
|
||||
GABiYW9uIlokPqcS7Fa0FRVIU9R+bBdHZompcYnKAeGag+uRvuTqC3MMRcLUS9Oi
|
||||
/P9I8fPARXUPwzYN3fagCGB8ffYVqMunnFs0L6td08BgvWwer+Buu4fPGsQ5OzMc
|
||||
lgZ0TJmXyOlIW49lc1UXnORp4sm7HS6okA7P6URbqyGbaplSsNUVTgVbi+vc8/jY
|
||||
dfExt/3HxVqgrPlq9htqYgwhYvGIbBAxmeFQD8Ak/ShSiWb1FdQ+f7Lty+4mZLfN
|
||||
8x4zPZ//7fD5d/PETPh9P0msF+lLFlP564+1j75wx+skFO4v1gGlBcDaeipkFzeo
|
||||
zndAgpegydKSNTF4QK9iTYobTIwsYfGuS8rV21zE2saLM0CE3T90aHYB/wARAQAB
|
||||
tD1DYW5vbmljYWwgQ2xvdWQgQXJjaGl2ZSBTaWduaW5nIEtleSA8ZnRwbWFzdGVy
|
||||
QGNhbm9uaWNhbC5jb20+iQI3BBMBCAAhBQJQKkpYAhsDBQsJCAcDBRUKCQgLBRYC
|
||||
AwEAAh4BAheAAAoJEF7bG2LsSSbqKxkQAIKtgImrk02YCDldg6tLt3b69ZK0kIVI
|
||||
3Xso/zCBZbrYFmgGQEFHAa58mIgpv5GcgHHxWjpX3n4tu2RM9EneKvFjFBstTTgo
|
||||
yuCgFr7iblvs/aMW4jFJAiIbmjjXWVc0CVB/JlLqzBJ/MlHdR9OWmojN9ZzoIA+i
|
||||
+tWlypgUot8iIxkR6JENxit5v9dN8i6anmnWybQ6PXFMuNi6GzQ0JgZIVs37n0ks
|
||||
2wh0N8hBjAKuUgqu4MPMwvNtz8FxEzyKwLNSMnjLAhzml/oje/Nj1GBB8roj5dmw
|
||||
7PSul5pAqQ5KTaXzl6gJN5vMEZzO4tEoGtRpA0/GTSXIlcx/SGkUK5+lqdQIMdyS
|
||||
n8bImU6V6rDSoOaI9YWHZtpv5WeUsNTdf68jZsFCRD+2+NEmIqBVm11yhmUoasC6
|
||||
dYw5l9P/PBdwmFm6NBUSEwxb+ROfpL1ICaZk9Jy++6akxhY//+cYEPLin02r43Z3
|
||||
o5Piqujrs1R2Hs7kX84gL5SlBzTM4Ed+ob7KVtQHTefpbO35bQllkPNqfBsC8AIC
|
||||
8xvTP2S8FicYOPATEuiRWs7Kn31TWC2iwswRKEKVRmN0fdpu/UPdMikyoNu9szBZ
|
||||
RxvkRAezh3WheJ6MW6Fmg9d+uTFJohZt5qHdpxYa4beuN4me8LF0TYzgfEbFT6b9
|
||||
D6IyTFoT0LequQINBFAqSlgBEADmL3TEq5ejBYrA+64zo8FYvCF4gziPa5rCIJGZ
|
||||
/gZXQ7pm5zek/lOe9C80mhxNWeLmrWMkMOWKCeaDMFpMBOQhZZmRdakOnH/xxO5x
|
||||
+fRdOOhy+5GTRJiwkuGOV6rB9eYJ3UN9caP2hfipCMpJjlg3j/GwktjhuqcBHXhA
|
||||
HMhzxEOIDE5hmpDqZ051f8LGXld9aSL8RctoYFM8sgafPVmICTCq0Wh03dr5c2JA
|
||||
gEXy3ushYm/8i2WFmyldo7vbtTfx3DpmJc/EMpGKV+GxcI3/ERqSkde0kWlmfPZb
|
||||
o/5+hRqSryqfQtRKnFEQgAqAhPIwXwOkjCpPnDNfrkvzVEtl2/BWP/1/SOqzXjk9
|
||||
TIb1Q7MHANeFMrTCprzPLX6IdC4zLp+LpV91W2zygQJzPgWqH/Z/WFH4gXcBBqmI
|
||||
8bFpMPONYc9/67AWUABo2VOCojgtQmjxuFn+uGNw9PvxJAF3yjl781PVLUw3n66d
|
||||
wHRmYj4hqxNDLywhhnL/CC7KUDtBnUU/CKn/0Xgm9oz3thuxG6i3F3pQgpp7MeMn
|
||||
tKhLFWRXo9Bie8z/c0NV4K5HcpbGa8QPqoDseB5WaO4yGIBOt+nizM4DLrI+v07y
|
||||
Xe3Jm7zBSpYSrGarZGK68qamS3XPzMshPdoXXz33bkQrTPpivGYQVRZuzd/R6b+6
|
||||
IurV+QARAQABiQIfBBgBCAAJBQJQKkpYAhsMAAoJEF7bG2LsSSbq59EP/1U3815/
|
||||
yHV3cf/JeHgh6WS/Oy2kRHp/kJt3ev/l/qIxfMIpyM3u/D6siORPTUXHPm3AaZrb
|
||||
w0EDWByA3jHQEzlLIbsDGZgrnl+mxFuHwC1yEuW3xrzgjtGZCJureZ/BD6xfRuRc
|
||||
mvnetAZv/z98VN/oj3rvYhUi71NApqSvMExpNBGrdO6gQlI5azhOu8xGNy4OSke8
|
||||
J6pAsMUXIcEwjVEIvewJuqBW/3rj3Hh14tmWjQ7shNnYBuSJwbLeUW2e8bURnfXE
|
||||
TxrCmXzDmQldD5GQWCcD5WDosk/HVHBmHlqrqy0VO2nE3c73dQlNcI4jVWeC4b4Q
|
||||
SpYVsFz/6Iqy5ZQkCOpQ57MCf0B6P5nF92c5f3TYPMxHf0x3DrjDbUVZytxDiZZa
|
||||
XsbZzsejbbc1bSNp4hb+IWhmWoFnq/hNHXzKPHBTapObnQju+9zUlQngV0BlPT62
|
||||
hOHOw3Pv7suOuzzfuOO7qpz0uAy8cFKe7kBtLSFVjBwaG5JX89mgttYW+lw9Rmsb
|
||||
p9Iw4KKFHIBLOwk7s+u0LUhP3d8neBI6NfkOYKZZCm3CuvkiOeQP9/2okFjtj+29
|
||||
jEL+9KQwrGNFEVNe85Un5MJfYIjgyqX3nJcwypYxidntnhMhr2VD3HL2R/4CiswB
|
||||
Oa4g9309p/+af/HU1smBrOfIeRoxb8jQoHu3
|
||||
=xg4S
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
88
files/default/cluster_stats.py
Executable file
88
files/default/cluster_stats.py
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import errno
|
||||
import subprocess
|
||||
|
||||
USING_COLLECTD=0
|
||||
|
||||
try:
|
||||
import collectd
|
||||
USING_COLLECTD=1
|
||||
except:
|
||||
pass
|
||||
|
||||
# ===============================================================================
|
||||
# [2012-06-19 21:37:04] Checking ring md5sum's on 3 hosts...
|
||||
# 3/3 hosts matched, 0 error[s] while checking hosts.
|
||||
# ===============================================================================
|
||||
def get_md5sums():
|
||||
retval = 0
|
||||
output = subprocess.Popen(['swift-recon', '--objmd5'], stdout=subprocess.PIPE).communicate()[0]
|
||||
for line in output.split("\n"):
|
||||
result = re.search("([0-9]+) error", line)
|
||||
if result:
|
||||
retval = result.group(1)
|
||||
return retval
|
||||
|
||||
|
||||
# ===============================================================================
|
||||
# [2012-06-19 21:36:27] Checking replication times on 3 hosts...
|
||||
# [Replication Times] shortest: 0.00546943346659, longest: 0.00739345153173, avg: 0.00669538444943
|
||||
# ===============================================================================
|
||||
def get_replication_times():
|
||||
retval = {}
|
||||
output = subprocess.Popen(['swift-recon', '-r'], stdout=subprocess.PIPE).communicate()[0]
|
||||
for line in output.split("\n"):
|
||||
result = re.search("shortest: ([0-9\.]+), longest: ([0-9\.]+), avg: ([0-9\.]+)", line)
|
||||
if result:
|
||||
retval['shortest'] = float(result.group(1))
|
||||
retval['longest'] = float(result.group(2))
|
||||
retval['average'] = float(result.group(3))
|
||||
return retval
|
||||
|
||||
def get_all():
|
||||
stats = {}
|
||||
stats['md5sums'] = get_md5sums()
|
||||
stats['replication_times'] = get_replication_times()
|
||||
return stats
|
||||
|
||||
def config_callback(conf):
|
||||
pass
|
||||
|
||||
def read_callback():
|
||||
stats = get_all()
|
||||
|
||||
if not stats:
|
||||
return
|
||||
|
||||
# blarg, this should be fixed
|
||||
for key in stats.keys():
|
||||
path = '%s' % key
|
||||
value = stats[key]
|
||||
|
||||
if type(value) != type({}):
|
||||
# must be an int
|
||||
val = collectd.Values(plugin=path)
|
||||
val.type = 'gauge'
|
||||
val.values = [int(value)]
|
||||
val.dispatch()
|
||||
else:
|
||||
# must be a hash
|
||||
for subvalue in value.keys():
|
||||
path = '%s.%s' % (key, subvalue)
|
||||
val = collectd.Values(plugin=path)
|
||||
val.type = 'gauge'
|
||||
if type(value[subvalue]) == type("string"):
|
||||
val.values = [int(value[subvalue])]
|
||||
else:
|
||||
val.values = value[subvalue]
|
||||
val.dispatch()
|
||||
|
||||
if not USING_COLLECTD:
|
||||
stats = get_all()
|
||||
print stats
|
||||
else:
|
||||
collectd.register_config(config_callback)
|
||||
collectd.register_read(read_callback)
|
16
files/default/git-daemon.default
Normal file
16
files/default/git-daemon.default
Normal file
@@ -0,0 +1,16 @@
|
||||
# Defaults for git-daemon initscript
|
||||
# sourced by /etc/init.d/git-daemon
|
||||
# installed at /etc/default/git-daemon by the maintainer scripts
|
||||
|
||||
#
|
||||
# This is a POSIX shell fragment
|
||||
#
|
||||
|
||||
GIT_DAEMON_ENABLE=true
|
||||
GIT_DAEMON_USER=gitdaemon
|
||||
GIT_DAEMON_DIRECTORY=/var/cache/git
|
||||
GIT_DAEMON_BASE_PATH=/var/cache/git
|
||||
|
||||
|
||||
# Additional options that are passed to the Daemon.
|
||||
GIT_DAEMON_OPTIONS=""
|
44
files/default/rsync.init
Normal file
44
files/default/rsync.init
Normal file
@@ -0,0 +1,44 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# chkconfig: 2345 50 50
|
||||
# description: rsync service
|
||||
|
||||
# source function library
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
PROG='/usr/bin/rsync'
|
||||
BASE=${0##*/}
|
||||
|
||||
# Adapt the --config parameter to point to your rsync daemon configuration
|
||||
# The config file must contain following line:
|
||||
# pid file = /var/run/<filename>.pid
|
||||
# Where <filename> is the filename of the init script (= this file)
|
||||
OPTIONS="--daemon --config=/etc/rsyncd.conf"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n $"Starting $BASE: "
|
||||
daemon --check $BASE $PROG $OPTIONS
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$BASE
|
||||
echo
|
||||
;;
|
||||
stop)
|
||||
echo -n $"Shutting down $BASE: "
|
||||
killproc $BASE
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BASE
|
||||
echo
|
||||
;;
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
11
files/default/rsync.service
Normal file
11
files/default/rsync.service
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Rsync Server
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/usr/bin/rsync --daemon
|
||||
PIDFile=/var/run/rsyncd.pid
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
98
files/default/swift_stats.py
Executable file
98
files/default/swift_stats.py
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import errno
|
||||
|
||||
from resource import getpagesize
|
||||
|
||||
USING_COLLECTD=0
|
||||
|
||||
try:
|
||||
import collectd
|
||||
USING_COLLECTD=1
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_unmounts(mountpath="/srv/node/"):
|
||||
try:
|
||||
candidates = [ x for x in os.listdir(mountpath) if os.path.isdir(mountpath + x) ]
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return 0
|
||||
|
||||
mounts = []
|
||||
with open('/proc/mounts', 'r') as procmounts:
|
||||
for line in procmounts:
|
||||
_, mounted_path, _, _, _, _ = line.rstrip().split()
|
||||
if mounted_path.startswith(mountpath):
|
||||
mounts.append(mounted_path.split('/')[-1])
|
||||
|
||||
return len(set(candidates) - set(mounts))
|
||||
|
||||
def get_sockstats():
|
||||
sockstat = {}
|
||||
try:
|
||||
with open('/proc/net/sockstat') as proc_sockstat:
|
||||
for entry in proc_sockstat:
|
||||
if entry.startswith("TCP: inuse"):
|
||||
tcpstats = entry.split()
|
||||
sockstat['tcp_in_use'] = int(tcpstats[2])
|
||||
sockstat['orphan'] = int(tcpstats[4])
|
||||
sockstat['time_wait'] = int(tcpstats[6])
|
||||
sockstat['tcp_mem_allocated_bytes'] = \
|
||||
int(tcpstats[10]) * getpagesize()
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
try:
|
||||
with open('/proc/net/sockstat6') as proc_sockstat6:
|
||||
for entry in proc_sockstat6:
|
||||
if entry.startswith("TCP6: inuse"):
|
||||
sockstat['tcp6_in_use'] = int(entry.split()[2])
|
||||
except IOError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return sockstat
|
||||
|
||||
def get_all():
|
||||
stats = {}
|
||||
stats['socket'] = get_sockstats()
|
||||
stats['unmounts'] = get_unmounts()
|
||||
return stats
|
||||
|
||||
def config_callback(conf):
|
||||
pass
|
||||
|
||||
def read_callback():
|
||||
stats = get_all()
|
||||
|
||||
if not stats:
|
||||
return
|
||||
|
||||
# blarg, this should be fixed
|
||||
for key in stats.keys():
|
||||
path = "%s" % key
|
||||
value = stats[key]
|
||||
|
||||
if type(value) != type({}):
|
||||
# must be an int
|
||||
val = collectd.Values(plugin=path)
|
||||
val.type = 'gauge'
|
||||
val.values = [int(value)]
|
||||
val.dispatch()
|
||||
else:
|
||||
# must be a hash
|
||||
for subvalue in value.keys():
|
||||
path = '%s.%s' % (key, subvalue)
|
||||
val = collectd.Values(plugin=path)
|
||||
val.type = 'gauge'
|
||||
val.values = [int(value[subvalue])]
|
||||
val.dispatch()
|
||||
|
||||
if not USING_COLLECTD:
|
||||
stats = get_all()
|
||||
print stats
|
||||
else:
|
||||
collectd.register_config(config_callback)
|
||||
collectd.register_read(read_callback)
|
34
libraries/drive_utils.rb
Normal file
34
libraries/drive_utils.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Library:: drive_utils
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
#
|
||||
|
||||
module DriveUtils
|
||||
def locate_disks(enum_expression, filter_expressions)
|
||||
candidate_disks = eval(enum_expression)
|
||||
candidate_expression = "candidate_disks.select{|candidate,info| (" +
|
||||
filter_expressions.map{|x| "(#{x})"}.join(" and ") + ")}"
|
||||
# TODO(mancdaz): fix this properly so the above works in the first place
|
||||
candidate_expression.gsub!(/\[\'removable\'\] = 0/, "['removable'].to_i == 0")
|
||||
drives = Hash[eval(candidate_expression)]
|
||||
Chef::Log.info("Using candidate drives: #{drives.keys.join(", ")}")
|
||||
drives.keys
|
||||
end
|
||||
end
|
||||
|
45
libraries/ip_utils.rb
Normal file
45
libraries/ip_utils.rb
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Library:: ip_utils
|
||||
#
|
||||
# Copyright 2013, ATT 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.
|
||||
#
|
||||
# Author: Alan Meadows <alan.meadows@gmail.com>
|
||||
#
|
||||
|
||||
require "ipaddr"
|
||||
|
||||
module IPUtils
|
||||
def locate_ip_in_cidr(network, node)
|
||||
Chef::Log.debug("Searching for ip within #{network} on node #{node.name}")
|
||||
net = IPAddr.new(network)
|
||||
node["network"]["interfaces"].each do |interface|
|
||||
if interface[1].has_key?("addresses") then
|
||||
interface[1]["addresses"].each do |k,v|
|
||||
if v["family"] == "inet6" or (v["family"] == "inet" and v["prefixlen"] != "32") then
|
||||
addr=IPAddr.new(k)
|
||||
if net.include?(addr) then
|
||||
return k
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
error = "Can't find address within network #{network} for node #{node.name}"
|
||||
Chef::Log.error(error)
|
||||
raise error
|
||||
end
|
||||
end
|
19
metadata.rb
Normal file
19
metadata.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
name "swift"
|
||||
maintainer "ATT, Inc."
|
||||
license "Apache 2.0"
|
||||
description "Installs and configures Openstack Swift"
|
||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||
version "1.0.16"
|
||||
recipe "swift::account-server", "Installs the swift account server"
|
||||
recipe "swift::object-server", "Installs the swift object server"
|
||||
recipe "swift::proxy-server", "Installs the swift proxy server"
|
||||
recipe "swift::container-server", "Installs the swift container server"
|
||||
|
||||
%w{ centos ubuntu }.each do |os|
|
||||
supports os
|
||||
end
|
||||
|
||||
depends "memcached"
|
||||
depends "sysctl"
|
||||
depends "statsd"
|
||||
depends "apt"
|
264
providers/disk.rb
Normal file
264
providers/disk.rb
Normal file
@@ -0,0 +1,264 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
require 'chef/mixin/shell_out'
|
||||
include Chef::Mixin::ShellOut
|
||||
|
||||
def load_current_resource
|
||||
dev_name = @new_resource.name
|
||||
@current = Chef::Resource::SwiftDisk.new(dev_name)
|
||||
|
||||
parted_partition_parse dev_name
|
||||
parts = @current.part()
|
||||
|
||||
if not @current.blocks
|
||||
# parted didn't return anything -- empty disk.
|
||||
# get size from sfdisk
|
||||
sfdisk_get_size(dev_name)
|
||||
end
|
||||
|
||||
Chef::Log.info("About to print partition table")
|
||||
|
||||
s = <<EOF
|
||||
current state for dev #{dev_name}
|
||||
Size in 1K blocks: #{@current.blocks}
|
||||
EOF
|
||||
|
||||
Chef::Log.info("Printing partition table")
|
||||
|
||||
num = 0
|
||||
parts.each { | p |
|
||||
s << "partition " << num
|
||||
s << " start/end/size (1k): #{p[:start]}/#{p[:end]}/#{p[:size]}"
|
||||
s << " type: #{p[:type]}"
|
||||
s << "\n"
|
||||
num+=1
|
||||
} if !parts.nil?
|
||||
Chef::Log.info(s)
|
||||
end
|
||||
|
||||
=begin
|
||||
sample output
|
||||
# sfdisk /dev/sdb -g
|
||||
/dev/sdb: 261 cylinders, 255 heads, 63 sectors/track
|
||||
=end
|
||||
def sfdisk_get_size(dev_name)
|
||||
out = %x{sfdisk #{dev_name} -s}
|
||||
Chef::Log.info("updating geo using sfdisk: #{out}")
|
||||
|
||||
# sfdisk sees the world as 1k blocks
|
||||
@current.blocks(out.to_i)
|
||||
end
|
||||
|
||||
def parted_partition_parse(dev_name)
|
||||
Chef::Log.debug("reading partition table for #{dev_name}")
|
||||
=begin
|
||||
Run parted to get basic info about the disk
|
||||
sample output:
|
||||
~# parted -m -s /dev/sda unit b print
|
||||
BYT;
|
||||
/dev/vda:8589934592B:virtblk:512:512:msdos:Virtio Block Device;
|
||||
1:1048576B:8589934591B:8588886016B:ext3::;
|
||||
=end
|
||||
pipe= IO.popen("parted -m -s #{dev_name} unit b print") # this can return 1, but it's ok (if no partition table present, we'll create it)
|
||||
result = pipe.readlines
|
||||
parted_parse_results result
|
||||
end
|
||||
|
||||
def parted_parse_results(input)
|
||||
Chef::Log.debug("read:" + input.inspect)
|
||||
input = input.to_a
|
||||
part_tab = []
|
||||
catch (:parse_error) do
|
||||
line = input.shift # Error or BYT;
|
||||
throw :parse_error if line =~ /^Error:/
|
||||
|
||||
line = input.shift
|
||||
throw :parse_error unless line =~ /\/dev\/([^\/]+):([0-9]+)B:(.*):.*$/
|
||||
|
||||
dev = Regexp.last_match(1)
|
||||
blocks = Regexp.last_match(2).to_i / 1024
|
||||
|
||||
if(@current.blocks and @current.blocks != blocks)
|
||||
throw "Our disk size changed. Expecting: #{@current.blocks}, got #{blocks}"
|
||||
end
|
||||
|
||||
@current.blocks(blocks)
|
||||
|
||||
input.each { |line|
|
||||
# 1:1048576B:8589934591B:8588886016B:ext3::;
|
||||
|
||||
throw :parse_error unless line =~ /([0-9]):([0-9]+)B:([0-9]+)B:([0-9]+)B:(.*):(.*):(.*);$/
|
||||
part_num = Regexp.last_match(1).to_i
|
||||
part_info = {
|
||||
:num => part_num,
|
||||
:start => Regexp.last_match(2).to_i / 1024,
|
||||
:end => Regexp.last_match(3).to_i / 1024,
|
||||
:size => Regexp.last_match(4).to_i / 1024,
|
||||
:type => Regexp.last_match(5),
|
||||
:system => Regexp.last_match(6),
|
||||
:flags => Regexp.last_match(7) }
|
||||
part_tab << part_info
|
||||
}
|
||||
end
|
||||
|
||||
@current.part(part_tab)
|
||||
part_tab
|
||||
end
|
||||
|
||||
action :list do
|
||||
Chef::Log.info("at some point there'll be a list")
|
||||
end
|
||||
|
||||
####
|
||||
# compare the requested partition table parameters to what exists
|
||||
# if differences found - remove all current partitions, and create new ones.
|
||||
# An existing partition is considered a match if:
|
||||
# - it has the same serial # (1,2,3)
|
||||
# - it has the same size
|
||||
#
|
||||
# We also want to start to partition at 1M to be correctly aligned
|
||||
# even due to 4K sector size and controller stripe sizes.
|
||||
#
|
||||
# Plus, then parted doesn't bitch every time you run it.
|
||||
|
||||
action :ensure_exists do
|
||||
Chef::Log.info("Entering :ensure_exists")
|
||||
|
||||
req = @new_resource.part
|
||||
cur = @current.part
|
||||
dev_name = @new_resource.name
|
||||
update = false
|
||||
|
||||
recreate, delete_existing = false
|
||||
|
||||
disk_blocks = @current.blocks #1k blocks
|
||||
|
||||
if (cur.nil?)
|
||||
recreate = true;
|
||||
else
|
||||
idx = 0
|
||||
current_block=0
|
||||
|
||||
Chef::Log.info("Checking partition #{idx}")
|
||||
|
||||
req.each { |params|
|
||||
if (cur[idx].nil?)
|
||||
recreate = true
|
||||
Chef::Log.info("no current #{idx}")
|
||||
next
|
||||
end
|
||||
|
||||
req_size = params[:size] # size in Mb - convert to blocks
|
||||
if (req_size == :remaining)
|
||||
req_size = disk_blocks - current_block
|
||||
else
|
||||
req_size = req_size * 1024
|
||||
end
|
||||
|
||||
cur_size = cur[idx][:size]
|
||||
|
||||
cur_min, cur_max = req_size*0.9, req_size*1.1
|
||||
if !(cur_size > cur_min and cur_size < cur_max)
|
||||
recreate = true
|
||||
end
|
||||
|
||||
current_block += cur[idx][:size]
|
||||
Chef::Log.info("partition #{idx} #{(recreate ? 'differs' : 'is same')}: #{cur_size}/#{req_size}")
|
||||
idx+=1
|
||||
}
|
||||
end
|
||||
|
||||
if !recreate
|
||||
Chef::Log.info("partition table matches - not recreating")
|
||||
else
|
||||
### make sure to ensure that there are no mounted
|
||||
### filesystems on the device
|
||||
re = /^(#{Regexp.escape(dev_name)}[0-9]+)/
|
||||
mounted = []
|
||||
shell_out!("mount").stdout.each_line { |line|
|
||||
md = re.match(line)
|
||||
next unless md
|
||||
mounted << md[1]
|
||||
}
|
||||
mounted.each { |m|
|
||||
Chef::Log.info("unmounting #{m}")
|
||||
shell_out!("umount #{m}")
|
||||
}
|
||||
|
||||
# Nuke current partition table.
|
||||
execute "create new partition table" do
|
||||
command "parted -s -m #{dev_name} mktable gpt"
|
||||
end
|
||||
|
||||
# create new partitions
|
||||
idx = 0
|
||||
req.each { | params |
|
||||
start_block = 0
|
||||
|
||||
if idx == 0
|
||||
start_block = "1M"
|
||||
end
|
||||
|
||||
if (params[:size] == :remaining)
|
||||
requested_size = "100%"
|
||||
else
|
||||
requested_size = "#{params[:size]}M"
|
||||
end
|
||||
|
||||
s = "parted -m -s #{dev_name} "
|
||||
s << "mkpart #{idx} #{start_block} #{requested_size}" # #{params[:type]}
|
||||
Chef::Log.info("creating new partition #{idx+1} with:" + s)
|
||||
execute "creating partition #{idx}" do
|
||||
command s
|
||||
end
|
||||
idx+=1
|
||||
|
||||
}
|
||||
update = true
|
||||
end
|
||||
|
||||
# walk through the partitions and enforce disk format
|
||||
idx=1
|
||||
req.each do |params|
|
||||
device = "#{dev_name}#{idx}"
|
||||
Chef::Log.info("Checking #{device}")
|
||||
|
||||
if ::File.exist?(device)
|
||||
# FIXME: check the format on the file system. This should be
|
||||
# handled by a disk format provider. Maybe the xfs/btrfs/etc
|
||||
# providers?
|
||||
Chef::Log.info("Testing file system on #{device} for type #{params[:type]}")
|
||||
|
||||
case params[:type]
|
||||
when "xfs"
|
||||
if not system("xfs_admin -l #{device}")
|
||||
Mixlib::ShellOut.new("mkfs.xfs -f -i size=512 #{device}").run_command
|
||||
update = true
|
||||
end
|
||||
when "ext4"
|
||||
if not system("tune2fs -l #{device} | grep \"Filesystem volume name:\" | awk \'{print $4}\' | grep -v \"<none>\"")
|
||||
Mixlib::ShellOut.new("mkfs.ext4 #{device}").run_command
|
||||
update = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
new_resource.updated_by_last_action(update)
|
||||
end
|
||||
|
168
providers/mounts.rb
Normal file
168
providers/mounts.rb
Normal file
@@ -0,0 +1,168 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Provider:: mounts
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
#
|
||||
|
||||
require "chef/util/file_edit"
|
||||
|
||||
action :ensure_exists do
|
||||
proposed_devices = @new_resource.devices
|
||||
path = @new_resource.name
|
||||
dev_info = {}
|
||||
|
||||
Chef::Log.info("IN MOUNTS")
|
||||
|
||||
new_resource.updated_by_last_action(false)
|
||||
|
||||
# walk through the devices, gathering information
|
||||
proposed_devices.each do |device|
|
||||
next if !::File.exists?("/dev/#{device}")
|
||||
|
||||
info = {}
|
||||
info["device"] = device
|
||||
info["ip"] = @new_resource.ip
|
||||
info["format"] = @new_resource.format
|
||||
info["uuid"] = `blkid /dev/#{device} -s UUID -o value`.strip
|
||||
info["mountpoint"] = info["uuid"].split("-").join("")
|
||||
info["mounted"] = system("mount | grep '#{path}/#{info["mountpoint"]}\'")
|
||||
info["size"] = `sfdisk -s /dev/#{device}`.to_i / 1024
|
||||
|
||||
next if (info["uuid"] == '')
|
||||
|
||||
dev_info[info["uuid"]] = info
|
||||
end
|
||||
|
||||
Chef::Log.info("Physical Inventory:")
|
||||
dev_info.each do |_,v|
|
||||
Chef::Log.info("Device: #{v['device']}, UUID: #{v['uuid']}, Mounted: #{v['mounted']}, Format: #{v['format']}")
|
||||
end
|
||||
|
||||
# make sure we have a "path"
|
||||
Directory(path) do
|
||||
group "swift"
|
||||
owner "swift"
|
||||
recursive true
|
||||
end.run_action(:create)
|
||||
|
||||
# find what should be mounted, and what IS mounted
|
||||
mounts=node["filesystem"].inject({}) { |hsh, (k,v)| hsh.merge(v["mount"] => k) }
|
||||
valid_mounts = dev_info.inject([]) {|ary, (_,v)| ary << "#{path}/#{v['mountpoint']}"}
|
||||
mountpoints = Dir.new(path).reject {|x| x[/^\./] }.collect { |d| "#{path}/#{d}" }
|
||||
inverted_mounts = dev_info.inject({}) {|hsh,(k,v)| hsh.merge({v["mountpoint"] => v.merge("uuid" => k)})}
|
||||
fstabs=::File.readlines("/etc/fstab").inject({}) do |hash,line|
|
||||
line = line.split("#")[0].split()
|
||||
Chef::Log.info("#{line[0]} ... #{line[1]}")
|
||||
hash.merge(line[1] => line[0])
|
||||
end.reject { |k,v| !k or !v or !k.length or !v.length }
|
||||
|
||||
Chef::Log.info("Mounts: #{mounts}")
|
||||
Chef::Log.info("Valid Mounts: #{valid_mounts}")
|
||||
Chef::Log.info("Mountpoints: #{mountpoints}")
|
||||
Chef::Log.info("Fstabs: #{fstabs}")
|
||||
|
||||
# mounts in /srv/node that shouldn't be there
|
||||
(mounts.keys.select{|x| x and x[/^#{path}/]} - valid_mounts).each do |dev|
|
||||
Chef::Log.info("Unmounting #{dev}")
|
||||
system("umount #{dev}") if system("mount | grep '#{dev}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
|
||||
# fstab entries that don't need to be there anymore
|
||||
(fstabs.keys.select {|k| k.start_with? path} - valid_mounts).each do |dev|
|
||||
fe = Chef::Util::FileEdit.new("/etc/fstab")
|
||||
fe.search_file_delete_line(Regexp.new(dev.gsub("/","\/")))
|
||||
fe.write_file
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
|
||||
# directories/mountpoints in /srv/node that are now useless
|
||||
(mountpoints - valid_mounts).each do |mountpoint|
|
||||
Chef::Log.info("rmdiring #{mountpoint}")
|
||||
begin
|
||||
Dir.rmdir(mountpoint)
|
||||
rescue SystemCallError
|
||||
Chef::Log.info("Directory #{mountpoint} appears non-empty")
|
||||
end
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
|
||||
# new, unmounted devices
|
||||
(valid_mounts - mounts.keys).each do |mountpoint|
|
||||
info = inverted_mounts[mountpoint.gsub("#{path}/","")]
|
||||
|
||||
Chef::Log.info("mounting #{mountpoint} (#{info['device']})")
|
||||
|
||||
mount_path = "#{path}/#{info['mountpoint']}"
|
||||
|
||||
Directory(mount_path) do
|
||||
group "swift"
|
||||
owner "swift"
|
||||
recursive true
|
||||
end.run_action(:create)
|
||||
|
||||
case info['format']
|
||||
when 'ext4'
|
||||
mount_options = "noatime,nodiratime,nobarrier,user_xattr"
|
||||
when 'xfs'
|
||||
case node["platform"]
|
||||
when "ubuntu","debian"
|
||||
mount_options = "noatime,nodiratime,nobarrier,logbufs=8,nobootwait"
|
||||
else
|
||||
mount_options = "noatime,nodiratime,nobarrier,logbufs=8"
|
||||
end
|
||||
end
|
||||
|
||||
mt = Mount(mount_path) do
|
||||
device info['uuid']
|
||||
device_type :uuid
|
||||
options mount_options
|
||||
dump 0
|
||||
fstype info['format']
|
||||
action :nothing
|
||||
end
|
||||
|
||||
if not fstabs.has_key?(mount_path)
|
||||
# then its a brand-new drive, freshly formatted
|
||||
Chef::Log.info("Mounting new device #{info['mountpoint']}")
|
||||
mt.run_action(:enable)
|
||||
mt.run_action(:mount)
|
||||
end
|
||||
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
|
||||
dev_info.reject { |k,v| v["mounted"] }.keys.each do |uuid|
|
||||
dev_info[uuid]["mounted"] = system("mount | grep '#{path}/#{dev_info[uuid]["mountpoint"]}\'")
|
||||
end
|
||||
|
||||
if @new_resource.publish_attributes and dev_info != {}
|
||||
dev_info.each do |k,v|
|
||||
node.set["swift"]["state"]["devs"][k] = {
|
||||
:device => v["device"],
|
||||
:size => v["size"],
|
||||
:uuid => v["uuid"],
|
||||
:mounted => v["mounted"],
|
||||
:format => v["format"],
|
||||
:mountpoint => v["mountpoint"],
|
||||
:ip => v["ip"]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
262
providers/ring_script.rb
Normal file
262
providers/ring_script.rb
Normal file
@@ -0,0 +1,262 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Resource:: ring_script
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
#
|
||||
|
||||
require "pp"
|
||||
|
||||
def generate_script
|
||||
# need to load and parse the existing rings.
|
||||
ports = { "object" => "6000", "container" => "6001", "account" => "6002" }
|
||||
must_rebalance = false
|
||||
|
||||
ring_path = @new_resource.ring_path
|
||||
ring_data = { :raw => {}, :parsed => {}, :in_use => {} }
|
||||
disk_data = {}
|
||||
dirty_cluster_reasons = []
|
||||
|
||||
[ "account", "container", "object" ].each do |which|
|
||||
ring_data[:raw][which] = nil
|
||||
|
||||
if ::File.exist?("#{ring_path}/#{which}.builder")
|
||||
IO.popen("su swift -c 'swift-ring-builder #{ring_path}/#{which}.builder'") do |pipe|
|
||||
ring_data[:raw][which] = pipe.readlines
|
||||
# Chef::Log.debug("#{ which.capitalize } Ring data: #{ring_data[:raw][which]}")
|
||||
ring_data[:parsed][which] = parse_ring_output(ring_data[:raw][which])
|
||||
|
||||
node.set["swift"]["state"]["ring"][which] = ring_data[:parsed][which]
|
||||
end
|
||||
else
|
||||
Chef::Log.info("#{which.capitalize} ring builder files do not exist!")
|
||||
end
|
||||
|
||||
# collect all the ring data, and note what disks are in use. All I really
|
||||
# need is a hash of device and id
|
||||
|
||||
ring_data[:in_use][which] ||= {}
|
||||
if ring_data[:parsed][which][:hosts]
|
||||
ring_data[:parsed][which][:hosts].each do |ip, dev|
|
||||
dev.each do |dev_id, devhash|
|
||||
ring_data[:in_use][which].store(devhash[:device], devhash[:id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Chef::Log.debug("#{which.capitalize} Ring - In use: #{PP.pp(ring_data[:in_use][which],dump='')}")
|
||||
|
||||
# figure out what's present in the cluster
|
||||
disk_data[which] = {}
|
||||
disk_state,_,_ = Chef::Search::Query.new.search(:node,"chef_environment:#{node.chef_environment} AND roles:swift-#{which}-server")
|
||||
|
||||
# for a running track of available disks
|
||||
disk_data[:available] ||= {}
|
||||
disk_data[:available][which] ||= {}
|
||||
|
||||
disk_state.each do |swiftnode|
|
||||
if swiftnode[:swift][:state] and swiftnode[:swift][:state][:devs]
|
||||
swiftnode[:swift][:state][:devs].each do |k,v|
|
||||
disk_data[which][v[:ip]] = disk_data[which][v[:ip]] || {}
|
||||
disk_data[which][v[:ip]][k] = {}
|
||||
v.keys.each { |x| disk_data[which][v[:ip]][k].store(x,v[x]) }
|
||||
|
||||
if swiftnode[:swift].has_key?("#{which}-zone")
|
||||
disk_data[which][v[:ip]][k]["zone"]=swiftnode[:swift]["#{which}-zone"]
|
||||
elsif swiftnode[:swift].has_key?("zone")
|
||||
disk_data[which][v[:ip]][k]["zone"]=swiftnode[:swift]["zone"]
|
||||
else
|
||||
raise "Node #{swiftnode[:hostname]} has no zone assigned"
|
||||
end
|
||||
|
||||
disk_data[:available][which][v[:mountpoint]] = v[:ip]
|
||||
|
||||
if not v[:mounted]
|
||||
dirty_cluster_reasons << "Disk #{v[:name]} (#{v[:uuid]}) is not mounted on host #{v[:ip]} (#{swiftnode[:hostname]})"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Chef::Log.debug("#{which.capitalize} Ring - Avail: #{PP.pp(disk_data[:available][which],dump='')}")
|
||||
end
|
||||
|
||||
# Have the raw data, now bump it together and drop the script
|
||||
|
||||
s = "#!/bin/bash\n\n# This script is automatically generated.\n"
|
||||
s << "# Running it will likely blow up your system if you don't review it carefully.\n"
|
||||
s << "# You have been warned.\n\n"
|
||||
if not node["swift"]["auto_rebuild_rings"]
|
||||
s << "if [ \"$1\" != \"--force\" ]; then\n"
|
||||
s << " echo \"Auto rebuild rings is disabled, so you must use --force to generate rings\"\n"
|
||||
s << " exit 0\n"
|
||||
s << "fi\n\n"
|
||||
end
|
||||
|
||||
# Chef::Log.debug("#{PP.pp(disk_data, dump='')}")
|
||||
|
||||
new_disks = {}
|
||||
missing_disks = {}
|
||||
new_servers = []
|
||||
|
||||
[ "account", "container", "object" ].each do |which|
|
||||
# remove available disks that are already in the ring
|
||||
new_disks[which] = disk_data[:available][which].reject{ |k,v| ring_data[:in_use][which].has_key?(k) }
|
||||
|
||||
# find all in-ring disks that are not in the cluster
|
||||
missing_disks[which] = ring_data[:in_use][which].reject{ |k,v| disk_data[:available][which].has_key?(k) }
|
||||
|
||||
Chef::Log.debug("#{which.capitalize} Ring - Missing: #{PP.pp(missing_disks[which],dump='')}")
|
||||
Chef::Log.debug("#{which.capitalize} Ring - New: #{PP.pp(new_disks[which],dump='')}")
|
||||
|
||||
s << "\n# -- #{which.capitalize} Servers --\n\n"
|
||||
disk_data[which].keys.sort.each do |ip|
|
||||
s << "# #{ip}\n"
|
||||
disk_data[which][ip].keys.sort.each do |k|
|
||||
v = disk_data[which][ip][k]
|
||||
s << "# " + v.keys.sort.select{|x| ["ip", "device", "uuid"].include?(x)}.collect{|x| v[x] }.join(", ")
|
||||
if new_disks[which].has_key?(v["mountpoint"])
|
||||
s << " (NEW!)"
|
||||
new_servers << ip unless new_servers.include?(ip)
|
||||
end
|
||||
s << "\n"
|
||||
end
|
||||
end
|
||||
|
||||
# for all those servers, check if they are already in the ring. If not,
|
||||
# then we need to add them to the ring. For those that *were* in the
|
||||
# ring, and are no longer in the ring, we need to delete those.
|
||||
|
||||
s << "\n"
|
||||
|
||||
# add the new disks
|
||||
disk_data[which].keys.sort.each do |ip|
|
||||
disk_data[which][ip].keys.sort.each do |uuid|
|
||||
v = disk_data[which][ip][uuid]
|
||||
if new_disks[which].has_key?(v['mountpoint'])
|
||||
s << "swift-ring-builder #{ring_path}/#{which}.builder add z#{v['zone']}-#{v['ip']}:#{ports[which]}/#{v['mountpoint']} #{v['size']}\n"
|
||||
must_rebalance = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# remove the disks -- sort to ensure consistent order
|
||||
missing_disks[which].keys.sort.each do |mountpoint|
|
||||
diskinfo=ring_data[:parsed][which][:hosts].select{|k,v| v.has_key?(mountpoint)}.collect{|_,v| v[mountpoint]}[0]
|
||||
Chef::Log.debug("Missing diskinfo: #{PP.pp(diskinfo,dump='')}")
|
||||
description = Hash[diskinfo.select{|k,v| [:zone, :ip, :device].include?(k)}].collect{|k,v| "#{k}: #{v}" }.join(", ")
|
||||
s << "# #{description}\n"
|
||||
s << "swift-ring-builder #{ring_path}/#{which}.builder remove d#{missing_disks[which][mountpoint]}\n"
|
||||
must_rebalance = true
|
||||
end
|
||||
|
||||
s << "\n"
|
||||
|
||||
if(must_rebalance)
|
||||
s << "swift-ring-builder #{ring_path}/#{which}.builder rebalance\n\n\n"
|
||||
else
|
||||
s << "# #{which.capitalize} ring has no outstanding changes!\n\n"
|
||||
end
|
||||
|
||||
# we'll only rebalance if we meet the minimums for new adds
|
||||
if node["swift"].has_key?("wait_for")
|
||||
if node["swift"]["wait_for"] > new_servers.count
|
||||
Chef::Log.debug("New servers, but not enough to force a rebalance")
|
||||
must_rebalance = false
|
||||
end
|
||||
end
|
||||
end
|
||||
[ s, must_rebalance ]
|
||||
end
|
||||
|
||||
# Parse the raw output of swift-ring-builder
|
||||
def parse_ring_output(ring_data)
|
||||
output = { :state => {} }
|
||||
|
||||
ring_data.each do |line|
|
||||
if line =~ /build version ([0-9]+)/
|
||||
output[:state][:build_version] = $1
|
||||
elsif line =~ /^Devices:\s+id\s+region\s+zone\s+/
|
||||
next
|
||||
elsif line =~ /^Devices:\s+id\s+zone\s+/
|
||||
next
|
||||
elsif line =~ /^\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+)\s+(\S+)\s+([0-9.]+)\s+(\d+)\s+([-0-9.]+)\s*$/
|
||||
output[:hosts] ||= {}
|
||||
output[:hosts][$3] ||= {}
|
||||
|
||||
output[:hosts][$3][$5] = {}
|
||||
|
||||
output[:hosts][$3][$5][:id] = $1
|
||||
output[:hosts][$3][$5][:region] = $2
|
||||
output[:hosts][$3][$5][:zone] = $3
|
||||
output[:hosts][$3][$5][:ip] = $4
|
||||
output[:hosts][$3][$5][:port] = $5
|
||||
output[:hosts][$3][$5][:device] = $6
|
||||
output[:hosts][$3][$5][:weight] = $7
|
||||
output[:hosts][$3][$5][:partitions] = $8
|
||||
output[:hosts][$3][$5][:balance] = $9
|
||||
elsif line =~ /^\s+(\d+)\s+(\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+)\s+(\S+)\s+([0-9.]+)\s+(\d+)\s+([-0-9.]+)\s*$/
|
||||
output[:hosts] ||= {}
|
||||
output[:hosts][$3] ||= {}
|
||||
|
||||
output[:hosts][$3][$5] = {}
|
||||
|
||||
output[:hosts][$3][$5][:id] = $1
|
||||
output[:hosts][$3][$5][:zone] = $2
|
||||
output[:hosts][$3][$5][:ip] = $3
|
||||
output[:hosts][$3][$5][:port] = $4
|
||||
output[:hosts][$3][$5][:device] = $5
|
||||
output[:hosts][$3][$5][:weight] = $6
|
||||
output[:hosts][$3][$5][:partitions] = $7
|
||||
output[:hosts][$3][$5][:balance] = $8
|
||||
elsif line =~ /(\d+) partitions, (\d+\.\d+) replicas, (\d+) regions, (\d+) zones, (\d+) devices, (\d+\.\d+) balance$/
|
||||
output[:state][:partitions] = $1
|
||||
output[:state][:replicas] = $2
|
||||
output[:state][:regions] = $3
|
||||
output[:state][:zones] = $4
|
||||
output[:state][:devices] = $5
|
||||
output[:state][:balance] = $6
|
||||
elsif line =~ /(\d+) partitions, (\d+) replicas, (\d+) zones, (\d+) devices, (\d+\.\d+) balance$/
|
||||
output[:state][:partitions] = $1
|
||||
output[:state][:replicas] = $2
|
||||
output[:state][:zones] = $3
|
||||
output[:state][:devices] = $4
|
||||
output[:state][:balance] = $5
|
||||
elsif line =~ /^The minimum number of hours before a partition can be reassigned is (\d+)$/
|
||||
output[:state][:min_part_hours] = $1
|
||||
else
|
||||
raise "Cannot parse ring builder output for #{line}"
|
||||
end
|
||||
end
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
action :ensure_exists do
|
||||
Chef::Log.debug("Ensuring #{new_resource.name}")
|
||||
new_resource.updated_by_last_action(false)
|
||||
s,must_update = generate_script
|
||||
|
||||
script_file = File new_resource.name do
|
||||
owner new_resource.owner
|
||||
group new_resource.group
|
||||
mode new_resource.mode
|
||||
content s
|
||||
end
|
||||
|
||||
script_file.run_action(:create)
|
||||
new_resource.updated_by_last_action(must_update)
|
||||
end
|
96
recipes/account-server.rb
Normal file
96
recipes/account-server.rb
Normal file
@@ -0,0 +1,96 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: account-server
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "swift::common"
|
||||
include_recipe "swift::storage-common"
|
||||
include_recipe "swift::disks"
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
platform_options["account_packages"].each.each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"] # retain configs
|
||||
end
|
||||
end
|
||||
|
||||
# epel/f-17 missing init scripts for the non-major services.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor reaper replicator}.each do |svc|
|
||||
template "/etc/systemd/system/openstack-swift-account-#{svc}.service" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0644"
|
||||
source "simple-systemd-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Account #{svc.capitalize}",
|
||||
:user => "swift",
|
||||
:exec => "/usr/bin/swift-account-#{svc} " +
|
||||
"/etc/swift/account-server.conf"
|
||||
})
|
||||
only_if { platform?(%w{fedora}) }
|
||||
end
|
||||
end
|
||||
|
||||
# TODO(breu): track against upstream epel packages to determine if this
|
||||
# is still necessary
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor reaper replicator}.each do |svc|
|
||||
template "/etc/init.d/openstack-swift-account-#{svc}" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0755"
|
||||
source "simple-redhat-init-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Account #{svc.capitalize}",
|
||||
:exec => "account-#{svc}"
|
||||
})
|
||||
only_if { platform?(%w{redhat centos}) }
|
||||
end
|
||||
end
|
||||
|
||||
%w{swift-account swift-account-auditor swift-account-reaper swift-account-replicator}.each do |svc|
|
||||
service_name = platform_options["service_prefix"] + svc + platform_options["service_suffix"]
|
||||
service svc do
|
||||
service_name service_name
|
||||
provider platform_options["service_provider"]
|
||||
supports :status => true, :restart => true
|
||||
action [:enable, :start]
|
||||
only_if "[ -e /etc/swift/account-server.conf ] && [ -e /etc/swift/account.ring.gz ]"
|
||||
end
|
||||
end
|
||||
|
||||
# retrieve bind information from node
|
||||
bind_ip = node["swift"]["network"]["bind_ip"]
|
||||
bind_port = node["swift"]["network"]["bind_port"]
|
||||
|
||||
# create account server template
|
||||
template "/etc/swift/account-server.conf" do
|
||||
source "account-server.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
variables("bind_ip" => node["swift"]["network"]["account-bind-ip"],
|
||||
"bind_port" => node["swift"]["network"]["account-bind-port"])
|
||||
|
||||
notifies :restart, "service[swift-account]", :immediately
|
||||
notifies :restart, "service[swift-account-auditor]", :immediately
|
||||
notifies :restart, "service[swift-account-reaper]", :immediately
|
||||
notifies :restart, "service[swift-account-replicator]", :immediately
|
||||
end
|
110
recipes/common.rb
Normal file
110
recipes/common.rb
Normal file
@@ -0,0 +1,110 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: swift-common
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
class Chef::Recipe
|
||||
include DriveUtils
|
||||
end
|
||||
|
||||
include_recipe 'sysctl::default'
|
||||
|
||||
# optionally statsd daemon for stats collection
|
||||
if node["swift"]["enable_statistics"]
|
||||
include_recipe 'statsd::server'
|
||||
end
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
# update repository if requested with the ubuntu cloud
|
||||
case node["platform"]
|
||||
when "ubuntu"
|
||||
|
||||
Chef::Log.info("Creating apt repository for http://ubuntu-cloud.archive.canonical.com/ubuntu")
|
||||
Chef::Log.info("chefspec: #{node['lsb']['codename']}-updates/#{node['swift']['release']}")
|
||||
apt_repository "ubuntu_cloud" do
|
||||
uri "http://ubuntu-cloud.archive.canonical.com/ubuntu"
|
||||
distribution "#{node['lsb']['codename']}-updates/#{node['swift']['release']}"
|
||||
components ["main"]
|
||||
key "5EDB1B62EC4926EA"
|
||||
action :add
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
platform_options["swift_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
end
|
||||
end
|
||||
|
||||
directory "/etc/swift" do
|
||||
action :create
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0700"
|
||||
only_if "/usr/bin/id swift"
|
||||
end
|
||||
|
||||
# determine hash
|
||||
if node['swift']['swift_secret_databag_name'].nil?
|
||||
swifthash = node['swift']['swift_hash']
|
||||
else
|
||||
swift_secrets = Chef::EncryptedDataBagItem.load "secrets", node['swift']['swift_secret_databag_name']
|
||||
swifthash = swift_secrets['swift_hash']
|
||||
end
|
||||
|
||||
|
||||
file "/etc/swift/swift.conf" do
|
||||
action :create
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0700"
|
||||
content "[swift-hash]\nswift_hash_path_suffix=#{swifthash}\n"
|
||||
only_if "/usr/bin/id swift"
|
||||
end
|
||||
|
||||
# need a swift user
|
||||
user "swift" do
|
||||
shell "/bin/bash"
|
||||
action :modify
|
||||
only_if "/usr/bin/id swift"
|
||||
end
|
||||
|
||||
package "git" do
|
||||
action :install
|
||||
end
|
||||
|
||||
# drop a ring puller script
|
||||
# TODO: make this smarter
|
||||
git_builder_ip = node["swift"]["git_builder_ip"]
|
||||
template "/etc/swift/pull-rings.sh" do
|
||||
source "pull-rings.sh.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0700"
|
||||
variables({
|
||||
:builder_ip => git_builder_ip,
|
||||
:service_prefix => platform_options["service_prefix"]
|
||||
})
|
||||
only_if "/usr/bin/id swift"
|
||||
end
|
||||
|
||||
execute "/etc/swift/pull-rings.sh" do
|
||||
cwd "/etc/swift"
|
||||
only_if "[ -x /etc/swift/pull-rings.sh ]"
|
||||
end
|
93
recipes/container-server.rb
Normal file
93
recipes/container-server.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: swift-container-server
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "swift::common"
|
||||
include_recipe "swift::storage-common"
|
||||
include_recipe "swift::disks"
|
||||
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
platform_options["container_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"]
|
||||
end
|
||||
end
|
||||
|
||||
# epel/f-17 missing init scripts for the non-major services.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor updater replicator}.each do |svc|
|
||||
template "/etc/systemd/system/openstack-swift-container-#{svc}.service" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0644"
|
||||
source "simple-systemd-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Container #{svc.capitalize}",
|
||||
:user => "swift",
|
||||
:exec => "/usr/bin/swift-container-#{svc} " +
|
||||
"/etc/swift/container-server.conf"
|
||||
})
|
||||
only_if { platform?(%w{fedora}) }
|
||||
end
|
||||
end
|
||||
|
||||
# TODO(breu): track against upstream epel packages to determine if this
|
||||
# is still necessary
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor updater replicator}.each do |svc|
|
||||
template "/etc/init.d/openstack-swift-container-#{svc}" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0755"
|
||||
source "simple-redhat-init-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Container #{svc.capitalize}",
|
||||
:exec => "container-#{svc}"
|
||||
})
|
||||
only_if { platform?(%w{redhat centos}) }
|
||||
end
|
||||
end
|
||||
|
||||
%w{swift-container swift-container-auditor swift-container-replicator swift-container-updater}.each do |svc|
|
||||
service_name=platform_options["service_prefix"] + svc + platform_options["service_suffix"]
|
||||
|
||||
service svc do
|
||||
service_name service_name
|
||||
provider platform_options["service_provider"]
|
||||
supports :status => true, :restart => true
|
||||
action [:enable, :start]
|
||||
only_if "[ -e /etc/swift/container-server.conf ] && [ -e /etc/swift/container.ring.gz ]"
|
||||
end
|
||||
end
|
||||
|
||||
template "/etc/swift/container-server.conf" do
|
||||
source "container-server.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
variables("bind_ip" => node["swift"]["network"]["container-bind-ip"],
|
||||
"bind_port" => node["swift"]["network"]["container-bind-port"])
|
||||
|
||||
notifies :restart, "service[swift-container]", :immediately
|
||||
notifies :restart, "service[swift-container-replicator]", :immediately
|
||||
notifies :restart, "service[swift-container-updater]", :immediately
|
||||
notifies :restart, "service[swift-container-auditor]", :immediately
|
||||
end
|
66
recipes/disks.rb
Normal file
66
recipes/disks.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: disks
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
# Inspired by: Andi Abes @ Dell
|
||||
|
||||
class Chef::Recipe
|
||||
include IPUtils
|
||||
end
|
||||
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
package "xfsprogs" do
|
||||
action :install
|
||||
only_if { platform?(%w{ubuntu debian fedora centos}) }
|
||||
end
|
||||
|
||||
%w(parted util-linux).each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
end
|
||||
end
|
||||
|
||||
disk_enum_expr = node["swift"]["disk_enum_expr"]
|
||||
disk_test_filter = node["swift"]["disk_test_filter"]
|
||||
|
||||
disks = locate_disks(disk_enum_expr, disk_test_filter)
|
||||
|
||||
disks.each do |disk|
|
||||
swift_disk "/dev/#{disk}" do
|
||||
part [{:type => platform_options["disk_format"] , :size => :remaining}]
|
||||
action :ensure_exists
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: "#{x}1" is only really valid for {v,s,h}dx. Doesn't
|
||||
# work for loop or probably for hp-style /dev/cciss/c0d0p1x0t0g0m1whatever
|
||||
#
|
||||
# additionally, there is an implicit assumption that bind ports
|
||||
# for all object/container/account services are on the same net
|
||||
disk_ip = locate_ip_in_cidr(node["swift"]["network"]["object-cidr"], node)
|
||||
|
||||
swift_mounts "/srv/node" do
|
||||
action :ensure_exists
|
||||
publish_attributes "swift/state/devs"
|
||||
devices disks.collect { |x| "#{x}1" }
|
||||
ip disk_ip
|
||||
format platform_options["disk_format"]
|
||||
end
|
||||
|
55
recipes/management-server.rb
Normal file
55
recipes/management-server.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: management-server
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "swift::common"
|
||||
|
||||
# FIXME: This should probably be a role (ring-builder?), so you don't end up
|
||||
# with multiple repos!
|
||||
include_recipe "swift::ring-repo"
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
if node["swift"]["authmode"] == "swauth"
|
||||
platform_options["swauth_packages"].each.each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"] # retain configs
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# determine where to find dispersion login information
|
||||
if node['swift']['swift_secret_databag_name'].nil?
|
||||
auth_user = node["swift"]["dispersion"]["auth_user"]
|
||||
auth_key = node["swift"]["dispersion"]["auth_key"]
|
||||
else
|
||||
swift_secrets = Chef::EncryptedDataBagItem.load "secrets", node['swift']['swift_secret_databag_name']
|
||||
auth_user = swift_secrets['dispersion_auth_user']
|
||||
auth_key = swift_secrets['dispersion_auth_key']
|
||||
end
|
||||
|
||||
template "/etc/swift/dispersion.conf" do
|
||||
source "dispersion.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
variables("auth_url" => node["swift"]["auth_url"],
|
||||
"auth_user" => auth_user,
|
||||
"auth_key" => auth_key)
|
||||
end
|
20
recipes/memcached.rb
Normal file
20
recipes/memcached.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: memcached
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "memcached"
|
101
recipes/object-server.rb
Normal file
101
recipes/object-server.rb
Normal file
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: swift-object-server
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "swift::common"
|
||||
include_recipe "swift::storage-common"
|
||||
include_recipe "swift::disks"
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
platform_options["object_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"] # retain configs
|
||||
end
|
||||
end
|
||||
|
||||
# epel/f-17 missing init scripts for the non-major services.
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor updater replicator}.each do |svc|
|
||||
template "/etc/systemd/system/openstack-swift-object-#{svc}.service" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0644"
|
||||
source "simple-systemd-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Object #{svc.capitalize}",
|
||||
:user => "swift",
|
||||
:exec => "/usr/bin/swift-object-#{svc} " +
|
||||
"/etc/swift/object-server.conf"
|
||||
})
|
||||
only_if { platform?(%w{fedora})}
|
||||
end
|
||||
end
|
||||
|
||||
# TODO(breu): track against upstream epel packages to determine if this
|
||||
# is still necessary
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=807170
|
||||
%w{auditor updater replicator}.each do |svc|
|
||||
template "/etc/init.d/openstack-swift-object-#{svc}" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0755"
|
||||
source "simple-redhat-init-config.erb"
|
||||
variables({ :description => "OpenStack Object Storage (swift) - " +
|
||||
"Object #{svc.capitalize}",
|
||||
:exec => "object-#{svc}"
|
||||
})
|
||||
only_if { platform?(%w{redhat centos}) }
|
||||
end
|
||||
end
|
||||
|
||||
%w{swift-object swift-object-replicator swift-object-auditor swift-object-updater}.each do |svc|
|
||||
service_name=platform_options["service_prefix"] + svc + platform_options["service_suffix"]
|
||||
|
||||
service svc do
|
||||
service_name service_name
|
||||
provider platform_options["service_provider"]
|
||||
# the default ubuntu provider uses invoke-rc.d, which apparently is
|
||||
# status-illy broken in ubuntu
|
||||
supports :status => false, :restart => true
|
||||
action [:enable, :start]
|
||||
only_if "[ -e /etc/swift/object-server.conf ] && [ -e /etc/swift/object.ring.gz ]"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
template "/etc/swift/object-server.conf" do
|
||||
source "object-server.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
variables("bind_ip" => node["swift"]["network"]["object-bind-ip"],
|
||||
"bind_port" => node["swift"]["network"]["object-bind-port"])
|
||||
|
||||
notifies :restart, "service[swift-object]", :immediately
|
||||
notifies :restart, "service[swift-object-replicator]", :immediately
|
||||
notifies :restart, "service[swift-object-updater]", :immediately
|
||||
notifies :restart, "service[swift-object-auditor]", :immediately
|
||||
end
|
||||
|
||||
cron "swift-recon" do
|
||||
minute "*/5"
|
||||
command "swift-recon-cron /etc/swift/object-server.conf"
|
||||
user "swift"
|
||||
end
|
116
recipes/proxy-server.rb
Normal file
116
recipes/proxy-server.rb
Normal file
@@ -0,0 +1,116 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: proxy-server
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
|
||||
include_recipe "swift::common"
|
||||
include_recipe "swift::memcached"
|
||||
|
||||
class Chef::Recipe
|
||||
include IPUtils
|
||||
end
|
||||
|
||||
if node.run_list.expand(node.chef_environment).recipes.include?("swift::setup")
|
||||
Chef::Log.info("I ran the swift::setup so I will use my own swift passwords")
|
||||
else
|
||||
setup = search(:node, "chef_environment:#{node.chef_environment} AND roles:swift-setup")
|
||||
if setup.length == 0
|
||||
Chef::Application.fatal! "You must have run the swift::setup recipe (on this or another node) before running the swift::proxy recipe on this node"
|
||||
elsif setup.length == 1
|
||||
Chef::Log.info "Found swift::setup node: #{setup[0].name}"
|
||||
node.set["swift"]["service_pass"] = setup[0]["swift"]["service_pass"]
|
||||
elsif setup.length >1
|
||||
Chef::Application.fatal! "You have multiple nodes in your environment that have run swift-setup, and that is not allowed"
|
||||
end
|
||||
end
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
# install platform-specific packages
|
||||
platform_options["proxy_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"]
|
||||
end
|
||||
end
|
||||
|
||||
package "python-swauth" do
|
||||
action :install
|
||||
only_if { node["swift"]["authmode"] == "swauth" }
|
||||
end
|
||||
|
||||
package "python-swift-informant" do
|
||||
action :install
|
||||
only_if { node["swift"]["use_informant"] }
|
||||
end
|
||||
|
||||
package "python-keystone" do
|
||||
action :install
|
||||
only_if { node["swift"]["authmode"] == "keystone" }
|
||||
end
|
||||
|
||||
directory "/var/cache/swift" do
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode 00700
|
||||
end
|
||||
|
||||
swift_proxy_service = platform_options["service_prefix"] + "swift-proxy" + platform_options["service_suffix"]
|
||||
service "swift-proxy" do
|
||||
# openstack-swift-proxy.service on fedora-17, swift-proxy on ubuntu
|
||||
service_name swift_proxy_service
|
||||
provider platform_options["service_provider"]
|
||||
supports :status => true, :restart => true
|
||||
action [ :enable, :start ]
|
||||
only_if "[ -e /etc/swift/proxy-server.conf ] && [ -e /etc/swift/object.ring.gz ]"
|
||||
end
|
||||
|
||||
# use localhost when using chef solo otherwise, include all memcache
|
||||
# servers from all known proxies
|
||||
if Chef::Config[:solo]
|
||||
memcache_servers = [ "127.0.0.1:11211" ]
|
||||
else
|
||||
memcache_servers = []
|
||||
proxy_nodes = search(:node, "chef_environment:#{node.chef_environment} AND roles:swift-proxy-server")
|
||||
proxy_nodes.each do |proxy|
|
||||
proxy_ip = locate_ip_in_cidr(node["swift"]["network"]["proxy-cidr"], proxy)
|
||||
next if not proxy_ip # skip nil ips so we dont break the config
|
||||
server_str = "#{proxy_ip}:11211"
|
||||
memcache_servers << server_str unless memcache_servers.include?(server_str)
|
||||
end
|
||||
end
|
||||
|
||||
# determine authkey to use
|
||||
if node['swift']['swift_secret_databag_name'].nil?
|
||||
authkey = node['swift']['authkey']
|
||||
else
|
||||
swift_secrets = Chef::EncryptedDataBagItem.load "secrets", node['swift']['swift_secret_databag_name']
|
||||
authkey = swift_secrets['swift_authkey']
|
||||
end
|
||||
|
||||
# create proxy config file
|
||||
template "/etc/swift/proxy-server.conf" do
|
||||
source "proxy-server.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
variables("authmode" => node["swift"]["authmode"],
|
||||
"bind_host" => node["swift"]["network"]["proxy-bind-ip"],
|
||||
"bind_port" => node["swift"]["network"]["proxy-bind-port"],
|
||||
"authkey" => authkey,
|
||||
"memcache_servers" => memcache_servers)
|
||||
notifies :restart, "service[swift-proxy]", :immediately
|
||||
end
|
183
recipes/ring-repo.rb
Normal file
183
recipes/ring-repo.rb
Normal file
@@ -0,0 +1,183 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: ring-repo
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
# This recipe creates a git ring repository on the management node
|
||||
# for purposes of ring synchronization
|
||||
#
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
ring_options = node["swift"]["ring"]
|
||||
|
||||
platform_options["git_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
end
|
||||
end
|
||||
|
||||
service "xinetd" do
|
||||
supports :status => false, :restart => true
|
||||
action [ :enable, :start ]
|
||||
only_if { platform?(%w{centos redhat fedora}) }
|
||||
end
|
||||
|
||||
execute "create empty git repo" do
|
||||
cwd "/tmp"
|
||||
umask 022
|
||||
command "mkdir $$; cd $$; git init; echo \"backups\" \> .gitignore; git add .gitignore; git commit -m 'initial commit' --author='chef <chef@openstack>'; git push file:///#{platform_options["git_dir"]}/rings master"
|
||||
user "swift"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
directory "git-directory" do
|
||||
path "#{platform_options["git_dir"]}/rings"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0755"
|
||||
recursive true
|
||||
action :create
|
||||
end
|
||||
|
||||
execute "initialize git repo" do
|
||||
cwd "#{platform_options["git_dir"]}/rings"
|
||||
umask 022
|
||||
user "swift"
|
||||
command "git init --bare && touch git-daemon-export-ok"
|
||||
creates "#{platform_options["git_dir"]}/rings/config"
|
||||
action :run
|
||||
notifies :run, "execute[create empty git repo]", :immediately
|
||||
end
|
||||
|
||||
# epel/f-17 missing systemd-ified inits
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=737183
|
||||
template "/etc/systemd/system/git.service" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0644"
|
||||
source "simple-systemd-config.erb"
|
||||
variables({ :description => "Git daemon service",
|
||||
:user => "nobody",
|
||||
:exec => "/usr/libexec/git-core/git-daemon " +
|
||||
"--base-path=/var/lib/git --export-all --user-path=public_git" +
|
||||
"--syslog --verbose"
|
||||
})
|
||||
only_if { platform?(%w{fedora}) }
|
||||
end
|
||||
|
||||
case node["platform"]
|
||||
when "centos","redhat","fedora"
|
||||
service "git-daemon" do
|
||||
service_name platform_options["git_service"]
|
||||
action [ :enable ]
|
||||
end
|
||||
when "ubuntu","debian"
|
||||
service "git-daemon" do
|
||||
service_name platform_options["git_service"]
|
||||
action [ :enable, :start ]
|
||||
end
|
||||
end
|
||||
|
||||
cookbook_file "/etc/default/git-daemon" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "644"
|
||||
source "git-daemon.default"
|
||||
action :create
|
||||
notifies :restart, "service[git-daemon]", :immediately
|
||||
not_if { platform?(%w{fedora centos redhat}) }
|
||||
end
|
||||
|
||||
directory "/etc/swift/ring-workspace" do
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0755"
|
||||
action :create
|
||||
end
|
||||
|
||||
execute "checkout-rings" do
|
||||
cwd "/etc/swift/ring-workspace"
|
||||
command "git clone file://#{platform_options["git_dir"]}/rings"
|
||||
user "swift"
|
||||
creates "/etc/swift/ring-workspace/rings"
|
||||
end
|
||||
|
||||
[ "account", "container", "object" ].each do |ring_type|
|
||||
|
||||
part_power = ring_options["part_power"]
|
||||
min_part_hours = ring_options["min_part_hours"]
|
||||
replicas = ring_options["replicas"]
|
||||
|
||||
Chef::Log.info("Building initial ring #{ring_type} using part_power=#{part_power}, " +
|
||||
"min_part_hours=#{min_part_hours}, replicas=#{replicas}")
|
||||
execute "add #{ring_type}.builder" do
|
||||
cwd "/etc/swift/ring-workspace/rings"
|
||||
command "git add #{ring_type}.builder && git commit -m 'initial ring builders' --author='chef <chef@openstack>'"
|
||||
user "swift"
|
||||
action :nothing
|
||||
end
|
||||
|
||||
execute "create #{ring_type} builder" do
|
||||
cwd "/etc/swift/ring-workspace/rings"
|
||||
command "swift-ring-builder #{ring_type}.builder create #{part_power} #{replicas} #{min_part_hours}"
|
||||
user "swift"
|
||||
creates "/etc/swift/ring-workspace/rings/#{ring_type}.builder"
|
||||
notifies :run, "execute[add #{ring_type}.builder]", :immediate
|
||||
end
|
||||
end
|
||||
|
||||
bash "rebuild-rings" do
|
||||
action :nothing
|
||||
cwd "/etc/swift/ring-workspace/rings"
|
||||
user "swift"
|
||||
code <<-EOF
|
||||
set -x
|
||||
|
||||
# Should this be done?
|
||||
git reset --hard
|
||||
git clean -df
|
||||
|
||||
../generate-rings.sh
|
||||
for d in object account container; do swift-ring-builder ${d}.builder; done
|
||||
|
||||
add=0
|
||||
if test -n "$(find . -maxdepth 1 -name '*gz' -print -quit)"
|
||||
then
|
||||
git add *builder *gz
|
||||
add=1
|
||||
else
|
||||
git add *builder
|
||||
add=1
|
||||
fi
|
||||
if [ $add -ne 0 ]
|
||||
then
|
||||
git commit -m "Autobuild of rings on $(date +%Y%m%d) by Chef" --author="chef <chef@openstack>"
|
||||
git push
|
||||
fi
|
||||
|
||||
EOF
|
||||
end
|
||||
|
||||
swift_ring_script "/etc/swift/ring-workspace/generate-rings.sh" do
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0700"
|
||||
ring_path "/etc/swift/ring-workspace/rings"
|
||||
action :ensure_exists
|
||||
notifies :run, "bash[rebuild-rings]", :immediate
|
||||
end
|
||||
|
85
recipes/rsync.rb
Normal file
85
recipes/rsync.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: rsync
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
platform_options["rsync_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :install
|
||||
options platform_options["override_options"]
|
||||
end
|
||||
end
|
||||
|
||||
# epel/f-17 broken: https://bugzilla.redhat.com/show_bug.cgi?id=737710
|
||||
cookbook_file "/etc/systemd/system/rsync.service" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0644"
|
||||
source "rsync.service"
|
||||
action :create
|
||||
only_if { platform?(%w{fedora}) }
|
||||
end
|
||||
|
||||
# rhel based systems install rsync and run it with rsync. We don't want to do that
|
||||
cookbook_file "/etc/init.d/rsyncd" do
|
||||
owner "root"
|
||||
group "root"
|
||||
mode "0755"
|
||||
source "rsync.init"
|
||||
action :create
|
||||
only_if { platform?(%w{centos redhat scientific}) }
|
||||
end
|
||||
|
||||
# FIXME: chicken and egg
|
||||
case node["platform"]
|
||||
when "centos","redhat","fedora"
|
||||
# enable rsyncd
|
||||
rsync_servicename = "rsyncd"
|
||||
service "rsyncd" do
|
||||
supports :status => false, :restart => true, :start => true, :stop => true
|
||||
action [ :enable, :start ]
|
||||
only_if "[ -f /etc/rsyncd.conf ]"
|
||||
end
|
||||
# disable rsync (the one via xinetd)
|
||||
service "rsync" do
|
||||
supports :status => false, :restart => false, :start => false, :stop => false
|
||||
action [ :disable ]
|
||||
end
|
||||
when "ubuntu","debian"
|
||||
rsync_servicename = "rsync"
|
||||
service "rsync" do
|
||||
supports :status => false, :restart => true
|
||||
action [ :enable, :start ]
|
||||
only_if "[ -f /etc/rsyncd.conf ]"
|
||||
end
|
||||
end
|
||||
|
||||
template "/etc/rsyncd.conf" do
|
||||
source "rsyncd.conf.erb"
|
||||
mode "0644"
|
||||
notifies :restart, "service[#{rsync_servicename}]", :immediately
|
||||
end
|
||||
|
||||
execute "enable rsync" do
|
||||
command "sed -i 's/RSYNC_ENABLE=false/RSYNC_ENABLE=true/' /etc/default/rsync"
|
||||
only_if "grep -q 'RSYNC_ENABLE=false' /etc/default/rsync"
|
||||
notifies :restart, "service[rsync]", :immediately
|
||||
action :run
|
||||
not_if { platform?(%w{fedora centos redhat scientific}) }
|
||||
end
|
58
recipes/setup.rb
Normal file
58
recipes/setup.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: setup
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
|
||||
include_recipe "swift::common"
|
||||
|
||||
# make sure we die if there are multiple swift-setups
|
||||
if Chef::Config[:solo]
|
||||
Chef::Application.fatal! "This recipe uses search. Chef Solo does not support search."
|
||||
else
|
||||
setup_role_count = search(:node, "chef_environment:#{node.chef_environment} AND roles:swift-setup").length
|
||||
if setup_role_count > 1
|
||||
Chef::Application.fatal! "You can only have one node with the swift-setup role"
|
||||
end
|
||||
end
|
||||
|
||||
unless node["swift"]["service_pass"]
|
||||
Chef::Log.info("Running swift setup - setting swift passwords")
|
||||
end
|
||||
|
||||
platform_options = node["swift"]["platform"]
|
||||
|
||||
# install platform-specific packages
|
||||
platform_options["proxy_packages"].each do |pkg|
|
||||
package pkg do
|
||||
action :upgrade
|
||||
options platform_options["override_options"]
|
||||
end
|
||||
end
|
||||
|
||||
package "python-swauth" do
|
||||
action :upgrade
|
||||
only_if { node["swift"]["authmode"] == "swauth" }
|
||||
end
|
||||
|
||||
package "python-swift-informant" do
|
||||
action :upgrade
|
||||
only_if { node["swift"]["use_informant"] }
|
||||
end
|
||||
|
||||
package "python-keystone" do
|
||||
action :upgrade
|
||||
only_if { node["swift"]["authmode"] == "keystone" }
|
||||
end
|
41
recipes/storage-common.rb
Normal file
41
recipes/storage-common.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Recipe:: storage-common
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
|
||||
include_recipe "swift::rsync"
|
||||
|
||||
template "/etc/swift/drive-audit.conf" do
|
||||
source "drive-audit.conf.erb"
|
||||
owner "swift"
|
||||
group "swift"
|
||||
mode "0600"
|
||||
end
|
||||
|
||||
cron "drive-audit" do
|
||||
hour node["swift"]["audit_hour"]
|
||||
minute "10"
|
||||
command "swift-drive-audit /etc/swift/drive-audit.conf"
|
||||
end
|
||||
|
||||
directory "/var/cache/swift" do
|
||||
group "swift"
|
||||
owner "swift"
|
||||
recursive true
|
||||
action :create
|
||||
mode 00700
|
||||
end
|
44
resources/disk.rb
Normal file
44
resources/disk.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
=begin
|
||||
Ensure that a disk's partition table matches expectations.
|
||||
Sample use:
|
||||
|
||||
swift_disk "/dev/sdb" do
|
||||
part(
|
||||
{[:type => "xfs", :size =>swift_disk::ONE_GIG*4 ],
|
||||
[:type => "xfs", :size =>swift_disk::remaining})
|
||||
action :ensure_exists
|
||||
end
|
||||
|
||||
=end
|
||||
|
||||
actions :ensure_exists
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@action = :ensure_exists
|
||||
end
|
||||
|
||||
attribute :name, :kind_of => String
|
||||
attribute :size, :kind_of => Integer
|
||||
attribute :blocks, :kind_of => Integer
|
||||
attribute :device, :kind_of => String
|
||||
attribute :part, :kind_of => Array
|
||||
attribute :status, :kind_of => Symbol
|
71
resources/mounts.rb
Normal file
71
resources/mounts.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Cookbook Name:: swift
|
||||
# Resource:: mounts
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
#
|
||||
|
||||
=begin
|
||||
Ensure that swift mounts are strongly enforced. This
|
||||
will ensure specified drives are mounted, and unspecified
|
||||
drives are not mounted. In addition, if there is a stale
|
||||
mountpoint (from disk failure, maybe?), then that mountpoint
|
||||
will try to be unmounted
|
||||
|
||||
Sample use:
|
||||
|
||||
swift_mounts "/srv/node" do
|
||||
devices [ "sdb1", "sdc1" ]
|
||||
action :ensure_exists
|
||||
ip "10.1.1.1"
|
||||
end
|
||||
|
||||
It will force mounts based on fs uuid (mangled to remove
|
||||
dashes) and return a structure that describes the disks
|
||||
mounted.
|
||||
|
||||
As this is expected to be consumed for the purposes of
|
||||
swift, the ip address should be the address that gets
|
||||
embedded into the ring (i.e. the listen port of the storage server)
|
||||
|
||||
Example return structure:
|
||||
|
||||
{ "2a9452c5-d929-43d9-9631-4340ace45279": {
|
||||
"device": "sdb1",
|
||||
"ip": "10.1.1.1",
|
||||
"mounted": "true",
|
||||
"mountpoint": "2a9452c5d92943d996314340ace45279",
|
||||
"size": 1022 (in 1k increments)
|
||||
"uuid": "2a9452c5-d929-43d9-9631-4340ace45279"
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
actions :ensure_exists
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@action = :ensure_exists
|
||||
end
|
||||
|
||||
attribute :name, :kind_of => String
|
||||
attribute :devices, :kind_of => Array
|
||||
attribute :ip, :kind_of => String, :default => "127.0.0.1"
|
||||
attribute :publish_attributes, :kind_of => String, :default => nil
|
||||
attribute :format, :kind_of => String, :default => "xfs"
|
44
resources/ring_script.rb
Normal file
44
resources/ring_script.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright 2012, Rackspace US, 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.
|
||||
#
|
||||
# Author: Ron Pedde <ron.pedde@rackspace.com>
|
||||
#
|
||||
|
||||
=begin
|
||||
Build a proposed ring-building script
|
||||
Sample use:
|
||||
|
||||
swift_ring_script "/tmp/build-rings.sh" do
|
||||
owner "root"
|
||||
group "swift"
|
||||
mode "0700"
|
||||
ring_path "/etc/swift/ring-workspace"
|
||||
action :ensure_exists
|
||||
end
|
||||
|
||||
=end
|
||||
|
||||
actions :ensure_exists
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
@action = :ensure_exists
|
||||
end
|
||||
|
||||
attribute :name, :kind_of => String
|
||||
attribute :owner, :kind_of => String, :default => "root"
|
||||
attribute :group, :kind_of => String, :default => "root"
|
||||
attribute :mode, :kind_of => String, :default => "0600"
|
||||
attribute :ring_path, :kind_of => String, :default => "/etc/swift"
|
23
run_tests.bash
Executable file
23
run_tests.bash
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# A script to run tests locally before committing.
|
||||
|
||||
set -e
|
||||
|
||||
COOKBOOK=$(awk '/^name/ {print $NF}' metadata.rb |tr -d \"\')
|
||||
if [ -z $COOKBOOK ]; then
|
||||
echo "Cookbook name not defined in metadata.rb"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BUNDLE_PATH=${BUNDLE_PATH:-.bundle}
|
||||
BERKSHELF_PATH=${BERKSHELF_PATH:-.cookbooks}
|
||||
|
||||
echo "Using bundle path: $BUNDLE_PATH"
|
||||
echo "Using berkshelf path: $BERKSHELF_PATH"
|
||||
|
||||
bundle install --path=${BUNDLE_PATH}
|
||||
bundle exec berks install --path=${BERKSHELF_PATH}
|
||||
bundle exec rspec ${BERKSHELF_PATH}/${COOKBOOK}
|
||||
bundle exec foodcritic -f any -t ~FC003 -t ~FC023 ${BERKSHELF_PATH}/${COOKBOOK}
|
||||
|
67
spec/account_spec.rb
Normal file
67
spec/account_spec.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::account-server' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['network']['account-bind-ip'] = '10.0.0.1'
|
||||
@node.set['swift']['network']['account-bind-port'] = '8080'
|
||||
@node.set['swift']['disk_enum_expr'] = "[{ 'sda' => {}}]"
|
||||
@node.set['swift']['disk_test_filter'] = [ "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~ /vd[^a]/ or candidate =~ /xvd[^a]/",
|
||||
"File.exist?('/dev/' + candidate)",
|
||||
"not system('/sbin/parted /dev/' + candidate + ' -s print | grep linux-swap')",
|
||||
"not info.has_key?('removable') or info['removable'] == 0.to_s"]
|
||||
|
||||
# mock out an interface on the storage node
|
||||
@node.set["network"] = MOCK_NODE_NETWORK_DATA['network']
|
||||
|
||||
@chef_run.converge "swift::account-server"
|
||||
end
|
||||
|
||||
it "installs swift account packages" do
|
||||
expect(@chef_run).to install_package "swift-account"
|
||||
end
|
||||
|
||||
it "installs swiftclient package" do
|
||||
expect(@chef_run).to install_package "python-swiftclient"
|
||||
end
|
||||
|
||||
it "starts swift account services on boot" do
|
||||
%w{swift-account swift-account-auditor swift-account-reaper swift-account-replicator}.each do |svc|
|
||||
expect(@chef_run).to set_service_to_start_on_boot svc
|
||||
end
|
||||
end
|
||||
|
||||
describe "/etc/swift/account-server.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/account-server.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
92
spec/common_spec.rb
Normal file
92
spec/common_spec.rb
Normal file
@@ -0,0 +1,92 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::common' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['platform_family'] = "debian"
|
||||
@node.set['lsb']['codename'] = "precise"
|
||||
@node.set['swift']['release'] = "folsom"
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['git_builder_ip'] = '10.0.0.10'
|
||||
|
||||
# TODO: this does not work
|
||||
# ::Chef::Log.should_receive(:info).with("chefspec: precise-updates/folsom")
|
||||
|
||||
@chef_run.converge "swift::common"
|
||||
end
|
||||
|
||||
|
||||
it 'should set syctl paramaters' do
|
||||
# N.B. we could examine chef log
|
||||
pending "TODO: right now theres no way to do lwrp and test for this"
|
||||
end
|
||||
|
||||
it 'installs git package for ring management' do
|
||||
expect(@chef_run).to install_package "git"
|
||||
end
|
||||
|
||||
describe "/etc/swift" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.directory "/etc/swift"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "700"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "/etc/swift/swift.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.file "/etc/swift/swift.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "700"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "/etc/swift/pull-rings.sh" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/pull-rings.sh"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "700"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
63
spec/container_spec.rb
Normal file
63
spec/container_spec.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::container-server' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['network']['container-bind-ip'] = '10.0.0.1'
|
||||
@node.set['swift']['network']['container-bind-port'] = '8080'
|
||||
@node.set['swift']['disk_enum_expr'] = "[{ 'sda' => {}}]"
|
||||
@node.set['swift']['disk_test_filter'] = [ "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~ /vd[^a]/ or candidate =~ /xvd[^a]/",
|
||||
"File.exist?('/dev/' + candidate)",
|
||||
"not system('/sbin/parted /dev/' + candidate + ' -s print | grep linux-swap')",
|
||||
"not info.has_key?('removable') or info['removable'] == 0.to_s"]
|
||||
|
||||
# mock out an interface on the storage node
|
||||
@node.set["network"] = MOCK_NODE_NETWORK_DATA['network']
|
||||
|
||||
@chef_run.converge "swift::container-server"
|
||||
end
|
||||
|
||||
it "installs swift container packages" do
|
||||
expect(@chef_run).to install_package "swift-container"
|
||||
end
|
||||
|
||||
it "starts swift container services on boot" do
|
||||
%w{swift-container swift-container-auditor swift-container-replicator swift-container-updater}.each do |svc|
|
||||
expect(@chef_run).to set_service_to_start_on_boot svc
|
||||
end
|
||||
end
|
||||
|
||||
describe "/etc/swift/container-server.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/container-server.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
43
spec/disks_spec.rb
Normal file
43
spec/disks_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::disks' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['platform_family'] = "debian"
|
||||
@node.set['lsb']['codename'] = "precise"
|
||||
@node.set['swift']['release'] = "folsom"
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['git_builder_ip'] = '10.0.0.10'
|
||||
@node.set['swift']['disk_enum_expr'] = "[{ 'sda' => {}}]"
|
||||
@node.set['swift']['disk_test_filter'] = [ "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~ /vd[^a]/ or candidate =~ /xvd[^a]/",
|
||||
"File.exist?('/dev/' + candidate)",
|
||||
"not system('/sbin/parted /dev/' + candidate + ' -s print | grep linux-swap')",
|
||||
"not info.has_key?('removable') or info['removable'] == 0.to_s"]
|
||||
|
||||
# mock out an interface on the storage node
|
||||
@node.set["network"] = MOCK_NODE_NETWORK_DATA['network']
|
||||
|
||||
@chef_run.converge "swift::disks"
|
||||
end
|
||||
|
||||
it 'installs xfs progs package' do
|
||||
expect(@chef_run).to install_package "xfsprogs"
|
||||
end
|
||||
|
||||
it 'installs parted package' do
|
||||
expect(@chef_run).to install_package "parted"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
47
spec/management_spec.rb
Normal file
47
spec/management_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::management-server' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
|
||||
@chef_run.converge "swift::management-server"
|
||||
end
|
||||
|
||||
it "installs swift swauth package" do
|
||||
expect(@chef_run).to install_package "swauth"
|
||||
end
|
||||
|
||||
describe "/etc/swift/dispersion.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/dispersion.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
71
spec/object_spec.rb
Normal file
71
spec/object_spec.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::object-server' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['network']['object-bind-ip'] = '10.0.0.1'
|
||||
@node.set['swift']['network']['object-bind-port'] = '8080'
|
||||
@node.set['swift']['disk_enum_expr'] = "[{ 'sda' => {}}]"
|
||||
@node.set['swift']['disk_test_filter'] = [ "candidate =~ /sd[^a]/ or candidate =~ /hd[^a]/ or candidate =~ /vd[^a]/ or candidate =~ /xvd[^a]/",
|
||||
"File.exist?('/dev/' + candidate)",
|
||||
"not system('/sbin/parted /dev/' + candidate + ' -s print | grep linux-swap')",
|
||||
"not info.has_key?('removable') or info['removable'] == 0.to_s"]
|
||||
|
||||
# mock out an interface on the storage node
|
||||
@node.set["network"] = MOCK_NODE_NETWORK_DATA['network']
|
||||
|
||||
@chef_run.converge "swift::object-server"
|
||||
end
|
||||
|
||||
it "installs swift packages" do
|
||||
expect(@chef_run).to install_package "swift-object"
|
||||
end
|
||||
|
||||
it "starts swift object services on boot" do
|
||||
%w{swift-object swift-object-replicator swift-object-auditor swift-object-updater}.each do |svc|
|
||||
expect(@chef_run).to set_service_to_start_on_boot svc
|
||||
end
|
||||
end
|
||||
|
||||
describe "/var/spool/crontab/root" do
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: check for recon script"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "/etc/swift/object-server.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/object-server.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
60
spec/proxy_spec.rb
Normal file
60
spec/proxy_spec.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::proxy-server' do
|
||||
|
||||
#--------------
|
||||
# UBUNTU
|
||||
#--------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['network']['proxy-bind-ip'] = '10.0.0.1'
|
||||
@node.set['swift']['network']['proxy-bind-port'] = '8080'
|
||||
@chef_run.converge "swift::proxy-server"
|
||||
end
|
||||
|
||||
it "installs memcache python packages" do
|
||||
expect(@chef_run).to install_package "python-memcache"
|
||||
end
|
||||
|
||||
it "installs swift packages" do
|
||||
expect(@chef_run).to install_package "swift-proxy"
|
||||
end
|
||||
|
||||
it "installs swauth package if swauth is selected" do
|
||||
expect(@chef_run).to install_package "python-swauth"
|
||||
end
|
||||
|
||||
it "starts swift-proxy on boot" do
|
||||
expect(@chef_run).to set_service_to_start_on_boot "swift-proxy"
|
||||
end
|
||||
|
||||
describe "/etc/swift/proxy-server.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/proxy-server.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
43
spec/ring-repo_spec.rb
Normal file
43
spec/ring-repo_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::ring-repo' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['platform_family'] = "debian"
|
||||
@node.set['lsb']['codename'] = "precise"
|
||||
@node.set['swift']['release'] = "folsom"
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['git_builder_ip'] = '10.0.0.10'
|
||||
@chef_run.converge "swift::ring-repo"
|
||||
end
|
||||
|
||||
it 'installs git package for ring management' do
|
||||
expect(@chef_run).to install_package "git-daemon-sysvinit"
|
||||
end
|
||||
|
||||
it "starts xinetd services on boot" do
|
||||
%w{xinetd}.each do |svc|
|
||||
expect(@chef_run).to set_service_to_start_on_boot svc
|
||||
end
|
||||
end
|
||||
|
||||
describe "/etc/swift/ring-workspace/generate-rings.sh" do
|
||||
|
||||
it "gets installed" do
|
||||
pending "TODO: determine some way to ensure this LWRP script gets created"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
51
spec/rsync_spec.rb
Normal file
51
spec/rsync_spec.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::rsync' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['platform_family'] = "debian"
|
||||
@node.set['lsb']['codename'] = "precise"
|
||||
@node.set['swift']['release'] = "folsom"
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@node.set['swift']['git_builder_ip'] = '10.0.0.10'
|
||||
@chef_run.converge "swift::rsync"
|
||||
end
|
||||
|
||||
it 'installs git package for ring management' do
|
||||
expect(@chef_run).to install_package "rsync"
|
||||
end
|
||||
|
||||
it "starts rsync service on boot" do
|
||||
%w{rsync}.each do |svc|
|
||||
expect(@chef_run).to set_service_to_start_on_boot svc
|
||||
end
|
||||
end
|
||||
|
||||
describe "/etc/rsyncd.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/rsyncd.conf"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "644"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
49
spec/spec_helper.rb
Normal file
49
spec/spec_helper.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require "chefspec"
|
||||
|
||||
::LOG_LEVEL = :fatal
|
||||
::REDHAT_OPTS = {
|
||||
:platform => "redhat",
|
||||
:log_level => ::LOG_LEVEL
|
||||
}
|
||||
::UBUNTU_OPTS = {
|
||||
:platform => "ubuntu",
|
||||
:version => "12.04",
|
||||
:log_level => ::LOG_LEVEL
|
||||
}
|
||||
|
||||
MOCK_NODE_NETWORK_DATA =
|
||||
{
|
||||
"ipaddress" => '10.0.0.2',
|
||||
"fqdn" => 'localhost.localdomain',
|
||||
"hostname" => 'localhost',
|
||||
"network" => {
|
||||
"default_interface" => "eth0",
|
||||
"interfaces" => {
|
||||
"eth0" => {
|
||||
"addresses" => {
|
||||
"fe80::a00:27ff:feca:ab08" => {"scope" => "Link", "prefixlen" => "64", "family" => "inet6"},
|
||||
"10.0.0.2" => {"netmask" => "255.255.255.0", "broadcast" => "10.0.0.255", "family" => "inet"},
|
||||
"08:00:27:CA:AB:08" => {"family" => "lladdr"}
|
||||
},
|
||||
},
|
||||
"lo" => {
|
||||
"addresses" => {
|
||||
"::1" => {"scope" => "Node", "prefixlen" => "128", "family" => "inet6"},
|
||||
"127.0.0.1" => {"netmask" => "255.0.0.0", "family" => "inet"}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
def swift_stubs
|
||||
# create mock cluster
|
||||
n = Chef::Node.new()
|
||||
n.name('manager')
|
||||
n.default_attrs = {
|
||||
"swift" => {
|
||||
"service_pass" => "foobar"
|
||||
}
|
||||
}
|
||||
Chef::Recipe.any_instance.stub(:search).with(:node, 'chef_environment:_default AND roles:swift-setup').and_return([n])
|
||||
end
|
58
spec/storage-common_spec.rb
Normal file
58
spec/storage-common_spec.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'swift::storage-common' do
|
||||
|
||||
#-------------------
|
||||
# UBUNTU
|
||||
#-------------------
|
||||
|
||||
describe "ubuntu" do
|
||||
|
||||
before do
|
||||
swift_stubs
|
||||
@chef_run = ::ChefSpec::ChefRunner.new ::UBUNTU_OPTS
|
||||
@node = @chef_run.node
|
||||
@node.set['lsb']['code'] = 'precise'
|
||||
@node.set['swift']['authmode'] = 'swauth'
|
||||
@chef_run.converge "swift::storage-common"
|
||||
end
|
||||
|
||||
describe "/var/cache/swift" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.directory "/var/cache/swift"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "700"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "/etc/swift/drive-audit.conf" do
|
||||
|
||||
before do
|
||||
@file = @chef_run.template "/etc/swift/drive-audit.conf"
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "swift", "swift"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
|
||||
it "template contents" do
|
||||
pending "TODO: implement"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
78
templates/default/account-server.conf.erb
Normal file
78
templates/default/account-server.conf.erb
Normal file
@@ -0,0 +1,78 @@
|
||||
[DEFAULT]
|
||||
# bind_ip = 0.0.0.0
|
||||
# bind_port = 6002
|
||||
# backlog = 4096
|
||||
# workers = 1
|
||||
# user = swift
|
||||
# swift_dir = /etc/swift
|
||||
# devices = /srv/node
|
||||
# mount_check = true
|
||||
# You can specify default log routing here if you want:
|
||||
# log_name = swift
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
#####
|
||||
bind_ip = <%= @bind_ip %>
|
||||
bind_port = <%= @bind_port %>
|
||||
workers = 10
|
||||
<% if node[:swift][:enable_statistics] -%>
|
||||
log_statsd_host = localhost
|
||||
log_statsd_port = 8125
|
||||
log_statsd_default_sample_rate = 1
|
||||
log_statsd_metric_prefix = openstack.swift.<%= node[:hostname] %>
|
||||
<% end %>
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = account-server
|
||||
|
||||
[app:account-server]
|
||||
use = egg:swift#account
|
||||
# You can override the default log routing for this app here:
|
||||
# set log_name = account-server
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_requests = True
|
||||
|
||||
[account-replicator]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = account-replicator
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# vm_test_mode = no
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# per_diff = 1000
|
||||
# max_diffs = 100
|
||||
# concurrency = 8
|
||||
# interval = 30
|
||||
# How long without an error before a node's error count is reset. This will
|
||||
# also be how long before a node is reenabled after suppression is triggered.
|
||||
# error_suppression_interval = 60
|
||||
# How many errors can accumulate before a node is temporarily ignored.
|
||||
# error_suppression_limit = 10
|
||||
# node_timeout = 10
|
||||
# conn_timeout = 0.5
|
||||
# The replicator also performs reclamation
|
||||
# reclaim_age = 86400
|
||||
|
||||
[account-auditor]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = account-auditor
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# Will audit, at most, 1 account per device per interval
|
||||
# interval = 1800
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
|
||||
[account-reaper]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = account-reaper
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# concurrency = 25
|
||||
# interval = 3600
|
||||
# node_timeout = 10
|
||||
# conn_timeout = 0.5
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
88
templates/default/container-server.conf.erb
Normal file
88
templates/default/container-server.conf.erb
Normal file
@@ -0,0 +1,88 @@
|
||||
[DEFAULT]
|
||||
# bind_ip = 0.0.0.0
|
||||
# bind_port = 6001
|
||||
# backlog = 4096
|
||||
# workers = 1
|
||||
# user = swift
|
||||
# swift_dir = /etc/swift
|
||||
# devices = /srv/node
|
||||
# mount_check = true
|
||||
# This is a comma separated list of hosts allowed in the X-Container-Sync-To
|
||||
# field for containers.
|
||||
# allowed_sync_hosts = 127.0.0.1
|
||||
# You can specify default log routing here if you want:
|
||||
# log_name = swift
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
####
|
||||
bind_ip = <%= @bind_ip %>
|
||||
bind_port = <%= @bind_port %>
|
||||
workers = 10
|
||||
<% if node[:swift][:enable_statistics] -%>
|
||||
log_statsd_host = localhost
|
||||
log_statsd_port = 8125
|
||||
log_statsd_default_sample_rate = 1
|
||||
log_statsd_metric_prefix = openstack.swift.<%= node[:hostname] %>
|
||||
<% end %>
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = container-server
|
||||
|
||||
[app:container-server]
|
||||
use = egg:swift#container
|
||||
# You can override the default log routing for this app here:
|
||||
# set log_name = container-server
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_requests = True
|
||||
# node_timeout = 3
|
||||
# conn_timeout = 0.5
|
||||
|
||||
[container-replicator]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = container-replicator
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# vm_test_mode = no
|
||||
# per_diff = 1000
|
||||
# max_diffs = 100
|
||||
# concurrency = 8
|
||||
# interval = 30
|
||||
# node_timeout = 10
|
||||
# conn_timeout = 0.5
|
||||
# The replicator also performs reclamation
|
||||
# reclaim_age = 604800
|
||||
|
||||
[container-updater]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = container-updater
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# interval = 300
|
||||
# concurrency = 4
|
||||
# node_timeout = 3
|
||||
# conn_timeout = 0.5
|
||||
# slowdown will sleep that amount between containers
|
||||
# slowdown = 0.01
|
||||
# Seconds to suppress updating an account that has generated an error
|
||||
# account_suppression_time = 60
|
||||
|
||||
[container-auditor]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = container-auditor
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# Will audit, at most, 1 container per device per interval
|
||||
# interval = 1800
|
||||
|
||||
[container-sync]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = container-sync
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# If you need to use an HTTP Proxy, set it here; defaults to no proxy.
|
||||
# sync_proxy = http://127.0.0.1:8888
|
||||
# Will sync, at most, each container once per interval
|
||||
# interval = 300
|
||||
# Maximum amount of time to spend syncing each container per pass
|
||||
# container_time = 60
|
13
templates/default/dispersion.conf.erb
Normal file
13
templates/default/dispersion.conf.erb
Normal file
@@ -0,0 +1,13 @@
|
||||
[dispersion]
|
||||
auth_url = <%= @auth_url %>
|
||||
auth_user = <%= @auth_user %>
|
||||
auth_key = <%= @auth_key %>
|
||||
auth_version = 1.0
|
||||
endpoint_type = publicURL
|
||||
swift_dir = /etc/swift
|
||||
dispersion_coverage = 5
|
||||
retries = 5
|
||||
concurrency = 25
|
||||
container_report = yes
|
||||
object_report = yes
|
||||
dump_json = no
|
5
templates/default/drive-audit.conf.erb
Normal file
5
templates/default/drive-audit.conf.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
[drive-audit]
|
||||
log_facility = LOG_LOCAL0
|
||||
log_level = INFO
|
||||
device_dir = /srv/node
|
||||
minutes = 60
|
104
templates/default/object-server.conf.erb
Normal file
104
templates/default/object-server.conf.erb
Normal file
@@ -0,0 +1,104 @@
|
||||
[DEFAULT]
|
||||
# bind_ip = 0.0.0.0
|
||||
# bind_port = 6000
|
||||
# backlog = 4096
|
||||
# workers = 1
|
||||
# user = swift
|
||||
# swift_dir = /etc/swift
|
||||
# devices = /srv/node
|
||||
# mount_check = true
|
||||
# expiring_objects_container_divisor = 86400
|
||||
# You can specify default log routing here if you want:
|
||||
# log_name = swift
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
#####
|
||||
bind_ip = <%= @bind_ip %>
|
||||
bind_port = <%= @bind_port %>
|
||||
workers = 10
|
||||
<% if node[:swift][:enable_statistics] -%>
|
||||
log_statsd_host = localhost
|
||||
log_statsd_port = 8125
|
||||
log_statsd_default_sample_rate = 1
|
||||
log_statsd_metric_prefix = openstack.swift.<%= node[:hostname] %>
|
||||
<% end %>
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = recon object-server
|
||||
|
||||
[app:object-server]
|
||||
use = egg:swift#object
|
||||
# You can override the default log routing for this app here:
|
||||
# set log_name = object-server
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_requests = True
|
||||
# node_timeout = 3
|
||||
# conn_timeout = 0.5
|
||||
# network_chunk_size = 65536
|
||||
# disk_chunk_size = 65536
|
||||
# max_upload_time = 86400
|
||||
# slow = 1
|
||||
# on PUTs, sync data every n MB
|
||||
# mb_per_sync = 512
|
||||
# Comma separated list of headers that can be set in metadata on an object.
|
||||
# This list is in addition to X-Object-Meta-* headers and cannot include
|
||||
# Content-Type, etag, Content-Length, or deleted
|
||||
# allowed_headers = Content-Disposition, Content-Encoding, X-Delete-At, X-Object-Manifest
|
||||
|
||||
[filter:recon]
|
||||
use = egg:swift#recon
|
||||
recon_cache_path = /var/cache/swift
|
||||
|
||||
[object-replicator]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = object-replicator
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# vm_test_mode = no
|
||||
# daemonize = on
|
||||
# run_pause = 30
|
||||
# concurrency = 1
|
||||
# stats_interval = 300
|
||||
# max duration of a partition rsync
|
||||
# rsync_timeout = 900
|
||||
# passed to rsync for io op timeout
|
||||
# rsync_io_timeout = 30
|
||||
# max duration of an http request
|
||||
# http_timeout = 60
|
||||
# attempts to kill all workers if nothing replicates for lockup_timeout seconds
|
||||
# lockup_timeout = 1800
|
||||
# The replicator also performs reclamation
|
||||
# reclaim_age = 604800
|
||||
# enable logging of replication stats for recon
|
||||
# recon_enable = no
|
||||
# recon_cache_path = /var/cache/swift
|
||||
#####
|
||||
recon_enable = yes
|
||||
recon_cache_path = /var/cache/swift
|
||||
concurrency = 2
|
||||
|
||||
|
||||
[object-updater]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = object-updater
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# interval = 300
|
||||
# concurrency = 1
|
||||
# node_timeout = 10
|
||||
# conn_timeout = 0.5
|
||||
# slowdown will sleep that amount between objects
|
||||
# slowdown = 0.01
|
||||
concurrency = 2
|
||||
|
||||
[object-auditor]
|
||||
# You can override the default log routing for this app here (don't use set!):
|
||||
# log_name = object-auditor
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
# files_per_second = 20
|
||||
# bytes_per_second = 10000000
|
||||
# log_time = 3600
|
||||
# zero_byte_files_per_second = 50
|
||||
|
262
templates/default/proxy-server.conf.erb
Normal file
262
templates/default/proxy-server.conf.erb
Normal file
@@ -0,0 +1,262 @@
|
||||
<%
|
||||
|
||||
case @authmode
|
||||
when "keystone"
|
||||
pipeline="authtoken keystoneauth"
|
||||
when "swauth"
|
||||
pipeline="swauth"
|
||||
end
|
||||
|
||||
account_management=false
|
||||
if node[:roles].include?("swift-management-server") and node[:swift][:authmode] == "swauth" then
|
||||
account_management="true"
|
||||
end
|
||||
-%>
|
||||
# This file is managed by chef. Do not edit it.
|
||||
#
|
||||
# Cluster info:
|
||||
# Auth mode: <%= node[:swift][:authmode] %>
|
||||
# Management server: <%= node[:roles].include?("swift-management-server") %>
|
||||
# Account management enabled: <%= account_management %>
|
||||
# Auth pipeline: <%= pipeline %>
|
||||
|
||||
[DEFAULT]
|
||||
# bind_ip = 0.0.0.0
|
||||
# bind_port = 8080
|
||||
# backlog = 4096
|
||||
# swift_dir = /etc/swift
|
||||
# workers = 1
|
||||
# user = swift
|
||||
# cert_file = /etc/swift/proxy.crt
|
||||
# key_file = /etc/swift/proxy.key
|
||||
# expiring_objects_container_divisor = 86400
|
||||
# You can specify default log routing here if you want:
|
||||
# log_name = swift
|
||||
# log_facility = LOG_LOCAL0
|
||||
# log_level = INFO
|
||||
######
|
||||
workers = <%= [ node[:cpu][:total] - 1, 1 ].max %>
|
||||
bind_ip = <%= @bind_host %>
|
||||
bind_port = <%= @bind_port %>
|
||||
<% if node[:swift][:enable_statistics] -%>
|
||||
log_statsd_host = localhost
|
||||
log_statsd_port = 8125
|
||||
log_statsd_default_sample_rate = 1
|
||||
log_statsd_metric_prefix = openstack.swift.<%= node[:hostname] %>
|
||||
<% end %>
|
||||
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = catch_errors healthcheck cache ratelimit <%= pipeline %> proxy-logging proxy-server
|
||||
|
||||
[app:proxy-server]
|
||||
use = egg:swift#proxy
|
||||
# You can override the default log routing for this app here:
|
||||
# set log_name = proxy-server
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set access_log_name = proxy-server
|
||||
# set access_log_facility = LOG_LOCAL0
|
||||
# set access_log_level = INFO
|
||||
# set log_headers = False
|
||||
# recheck_account_existence = 60
|
||||
# recheck_container_existence = 60
|
||||
# object_chunk_size = 8192
|
||||
# client_chunk_size = 8192
|
||||
# node_timeout = 10
|
||||
# client_timeout = 60
|
||||
# conn_timeout = 0.5
|
||||
# How long without an error before a node's error count is reset. This will
|
||||
# also be how long before a node is reenabled after suppression is triggered.
|
||||
# error_suppression_interval = 60
|
||||
# How many errors can accumulate before a node is temporarily ignored.
|
||||
# error_suppression_limit = 10
|
||||
# If set to 'true' any authorized user may create and delete accounts; if
|
||||
# 'false' no one, even authorized, can.
|
||||
# allow_account_management = false
|
||||
# Set object_post_as_copy = false to turn on fast posts where only the metadata
|
||||
# changes are stored anew and the original data file is kept in place. This
|
||||
# makes for quicker posts; but since the container metadata isn't updated in
|
||||
# this mode, features like container sync won't be able to sync posts.
|
||||
# object_post_as_copy = true
|
||||
# If set to 'true' authorized accounts that do not yet exist within the Swift
|
||||
# cluster will be automatically created.
|
||||
# account_autocreate = false
|
||||
######
|
||||
#
|
||||
# N.B. ideally allow_account_management would only be set on the
|
||||
# management server, but swauth will delete using the cluster url
|
||||
# and not the local url
|
||||
# allow_account_managemnet = <%= account_management %>
|
||||
allow_account_management = true
|
||||
|
||||
<% if @authmode == "keystone" -%>
|
||||
account_autocreate = true
|
||||
<% end %>
|
||||
|
||||
<% if @authmode == "swauth" -%>
|
||||
[filter:swauth]
|
||||
use = egg:swauth#swauth
|
||||
# set log_name = swauth
|
||||
# super_admin_key = <secret_key>
|
||||
######
|
||||
<% if account_management -%>
|
||||
super_admin_key = <%= @authkey %>
|
||||
default_swift_cluster = local#<%= node[:swift][:swift_url] %>#<%= node[:swift][:swauth_url] %>
|
||||
<% else %>
|
||||
default_swift_cluster = local#<%= node[:swift][:swift_url] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
[filter:healthcheck]
|
||||
use = egg:swift#healthcheck
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = healthcheck
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
|
||||
[filter:cache]
|
||||
use = egg:swift#memcache
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = cache
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
# Default for memcache_servers is to try to read the property from
|
||||
# memcache.conf (see memcache.conf-sample) or lacking that file, it will
|
||||
# default to the value below. You can specify multiple servers separated with
|
||||
# commas, as in: 10.1.2.3:11211,10.1.2.4:11211
|
||||
# memcache_servers = 127.0.0.1:11211
|
||||
#####
|
||||
memcache_servers = <%= @memcache_servers.join(",") %>
|
||||
|
||||
[filter:ratelimit]
|
||||
use = egg:swift#ratelimit
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = ratelimit
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
# clock_accuracy should represent how accurate the proxy servers' system clocks
|
||||
# are with each other. 1000 means that all the proxies' clock are accurate to
|
||||
# each other within 1 millisecond. No ratelimit should be higher than the
|
||||
# clock accuracy.
|
||||
# clock_accuracy = 1000
|
||||
# max_sleep_time_seconds = 60
|
||||
# log_sleep_time_seconds of 0 means disabled
|
||||
# log_sleep_time_seconds = 0
|
||||
# allows for slow rates (e.g. running up to 5 sec's behind) to catch up.
|
||||
# rate_buffer_seconds = 5
|
||||
# account_ratelimit of 0 means disabled
|
||||
# account_ratelimit = 0
|
||||
|
||||
# these are comma separated lists of account names
|
||||
# account_whitelist = a,b
|
||||
# account_blacklist = c,d
|
||||
|
||||
# with container_limit_x = r
|
||||
# for containers of size x limit requests per second to r. The container
|
||||
# rate will be linearly interpolated from the values given. With the values
|
||||
# below, a container of size 5 will get a rate of 75.
|
||||
# container_ratelimit_0 = 100
|
||||
# container_ratelimit_10 = 50
|
||||
# container_ratelimit_50 = 20
|
||||
|
||||
[filter:domain_remap]
|
||||
use = egg:swift#domain_remap
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = domain_remap
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
# storage_domain = example.com
|
||||
# path_root = v1
|
||||
# reseller_prefixes = AUTH
|
||||
|
||||
[filter:catch_errors]
|
||||
use = egg:swift#catch_errors
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = catch_errors
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
|
||||
[filter:cname_lookup]
|
||||
# Note: this middleware requires python-dnspython
|
||||
use = egg:swift#cname_lookup
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = cname_lookup
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set log_headers = False
|
||||
# storage_domain = example.com
|
||||
# lookup_depth = 1
|
||||
|
||||
# Note: Put staticweb just after your auth filter(s) in the pipeline
|
||||
[filter:staticweb]
|
||||
use = egg:swift#staticweb
|
||||
# Seconds to cache container x-container-meta-web-* header values.
|
||||
# cache_timeout = 300
|
||||
# You can override the default log routing for this filter here:
|
||||
# set log_name = staticweb
|
||||
# set log_facility = LOG_LOCAL0
|
||||
# set log_level = INFO
|
||||
# set access_log_name = staticweb
|
||||
# set access_log_facility = LOG_LOCAL0
|
||||
# set access_log_level = INFO
|
||||
# set log_headers = False
|
||||
|
||||
# Note: Put tempurl just before your auth filter(s) in the pipeline
|
||||
[filter:tempurl]
|
||||
use = egg:swift#tempurl
|
||||
#
|
||||
# The headers to remove from incoming requests. Simply a whitespace delimited
|
||||
# list of header names and names can optionally end with '*' to indicate a
|
||||
# prefix match. incoming_allow_headers is a list of exceptions to these
|
||||
# removals.
|
||||
# incoming_remove_headers = x-timestamp
|
||||
#
|
||||
# The headers allowed as exceptions to incoming_remove_headers. Simply a
|
||||
# whitespace delimited list of header names and names can optionally end with
|
||||
# '*' to indicate a prefix match.
|
||||
# incoming_allow_headers =
|
||||
#
|
||||
# The headers to remove from outgoing responses. Simply a whitespace delimited
|
||||
# list of header names and names can optionally end with '*' to indicate a
|
||||
# prefix match. outgoing_allow_headers is a list of exceptions to these
|
||||
# removals.
|
||||
# outgoing_remove_headers = x-object-meta-*
|
||||
#
|
||||
# The headers allowed as exceptions to outgoing_remove_headers. Simply a
|
||||
# whitespace delimited list of header names and names can optionally end with
|
||||
# '*' to indicate a prefix match.
|
||||
# outgoing_allow_headers = x-object-meta-public-*
|
||||
|
||||
# Note: Put formpost just before your auth filter(s) in the pipeline
|
||||
[filter:formpost]
|
||||
use = egg:swift#formpost
|
||||
|
||||
[filter:keystoneauth]
|
||||
operator_roles = Member,admin
|
||||
use = egg:swift#keystoneauth
|
||||
|
||||
[filter:proxy-logging]
|
||||
use = egg:swift#proxy_logging
|
||||
# access_log_name = proxy
|
||||
# access_log_facility = LOG_LOCAL0
|
||||
# access_log_level = INFO
|
||||
# access_log_address = /dev/log
|
||||
# If set, access_log_udp_host will override access_log_address
|
||||
# access_log_udp_host =
|
||||
# access_log_udp_port = 514
|
||||
# You can use log_statsd_* from [DEFAULT] or override them here:
|
||||
# access_log_statsd_host = localhost
|
||||
# access_log_statsd_port = 8125
|
||||
# access_log_statsd_default_sample_rate = 1
|
||||
# access_log_statsd_metric_prefix =
|
||||
# access_log_headers = False
|
||||
# What HTTP methods are allowed for StatsD logging (comma-sep); request methods
|
||||
# not in this list will have "BAD_METHOD" for the <verb> portion of the metric.
|
||||
# log_statsd_valid_http_methods = GET,HEAD,POST,PUT,DELETE,COPY
|
||||
|
29
templates/default/pull-rings.sh.erb
Normal file
29
templates/default/pull-rings.sh.erb
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this has to be run as root to restart the services...
|
||||
|
||||
if [ ! -d /etc/swift/rings ] || [ ! -e /etc/swift/rings/.git/config ]; then
|
||||
rm -rf /etc/swift/rings
|
||||
git clone git://<%= @builder_ip %>/rings /etc/swift/rings
|
||||
fi
|
||||
|
||||
cd /etc/swift/rings
|
||||
git reset --hard
|
||||
git clean -df
|
||||
git pull
|
||||
|
||||
[ -e /etc/swift/rings ] && chown -R swift: /etc/swift/rings
|
||||
|
||||
for d in object account container; do
|
||||
if [ -e /etc/swift/rings/${d}.ring.gz ]; then
|
||||
if [ ! -e ../${d}.ring.gz ] || [ "$(md5sum ${d}.ring.gz | cut -f1 -d' ')" != "$(md5sum ../${d}.ring.gz | cut -f1 -d' ')" ]; then
|
||||
cp ${d}.ring.gz ../${d}.ring.new
|
||||
chown swift: ../${d}.ring.new
|
||||
mv ../${d}.ring.new ../${d}.ring.gz
|
||||
|
||||
if [ -e /etc/swift/${d}-server.conf ]; then
|
||||
service <%= @service_prefix %>swift-${d}-replicator restart
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
24
templates/default/rsyncd.conf.erb
Normal file
24
templates/default/rsyncd.conf.erb
Normal file
@@ -0,0 +1,24 @@
|
||||
uid = swift
|
||||
gid = swift
|
||||
|
||||
log file = /var/log/rsyncd.log
|
||||
pid file = /var/run/rsyncd.pid
|
||||
address = 0.0.0.0
|
||||
|
||||
[account]
|
||||
max connections = 10
|
||||
path = /srv/node/
|
||||
read only = false
|
||||
lock file = /var/lock/account.lock
|
||||
|
||||
[container]
|
||||
max connections = 10
|
||||
path = /srv/node/
|
||||
read only = false
|
||||
lock file = /var/lock/container.lock
|
||||
|
||||
[object]
|
||||
max connections = 10
|
||||
path = /srv/node/
|
||||
read only = false
|
||||
lock file = /var/lock/object.lock
|
77
templates/default/simple-redhat-init-config.erb
Normal file
77
templates/default/simple-redhat-init-config.erb
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: <%= @exec %>
|
||||
# Required-Start: $remote_fs
|
||||
# Required-Stop: $remote_fs
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: <%= @description %>
|
||||
### END INIT INFO
|
||||
|
||||
# chkconfig: - 98 02
|
||||
|
||||
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
name="<%= @exec =%>"
|
||||
|
||||
[ -e "/etc/sysconfig/openstack-swift-$name" ] && . "/etc/sysconfig/openstack-swift-$name"
|
||||
|
||||
lockfile="/var/lock/subsys/openstack-swift-$name"
|
||||
|
||||
start() {
|
||||
swift-init "$name" start
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
stop() {
|
||||
swift-init "$name" stop
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
rh_status() {
|
||||
swift-init "$name" status
|
||||
retval=$?
|
||||
return $retval
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status &> /dev/null
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
rh_status_q && exit 0
|
||||
$1
|
||||
;;
|
||||
stop)
|
||||
rh_status_q || exit 0
|
||||
$1
|
||||
;;
|
||||
restart)
|
||||
$1
|
||||
;;
|
||||
reload)
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
rh_status_q || exit 0
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}"
|
||||
exit 2
|
||||
esac
|
||||
exit $?
|
11
templates/default/simple-systemd-config.erb
Normal file
11
templates/default/simple-systemd-config.erb
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=<%= @description %>
|
||||
After=syslog.target network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=<%= @user %>
|
||||
ExecStart=<%= @exec %>
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Reference in New Issue
Block a user