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
|
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
|
https://wiki.openstack.org/wiki/Swift
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
============
|
============
|
||||||
|
|
||||||
|
Clients
|
||||||
|
--------
|
||||||
|
|
||||||
|
* CentOS >= 6.3
|
||||||
|
* Ubuntu >= 12.04
|
||||||
|
|
||||||
|
Chef
|
||||||
|
---------
|
||||||
|
|
||||||
|
* 11.4.4
|
||||||
|
|
||||||
Cookbooks
|
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
|
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
|
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.
|
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
|
$ ./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
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with 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.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and⋅
|
See the License for the specific language governing permissions and⋅
|
||||||
limitations under the License.
|
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