├── cookbooks ├── memcached │ ├── README.rdoc │ ├── attributes │ │ └── default.rb │ ├── definitions │ │ └── memcached_instance.rb │ ├── metadata.json │ ├── metadata.rb │ ├── recipes │ │ └── default.rb │ └── templates │ │ └── default │ │ ├── memcached.conf.erb │ │ ├── memcached.default.erb │ │ ├── sv-memcached-log-run.erb │ │ └── sv-memcached-run.erb └── swift │ ├── README.rdoc │ ├── attributes │ └── default.rb │ ├── files │ └── default │ │ └── default-rsync │ ├── libraries │ └── eval.rb │ ├── metadata.json │ ├── metadata.rb │ ├── providers │ ├── disk.rb │ └── ringfile.rb │ ├── recipes │ ├── auth.rb │ ├── default.rb │ ├── disks.rb │ ├── monitor.rb │ ├── proxy.rb │ ├── ring-compute.rb │ ├── rsync.rb │ └── storage.rb │ ├── resources │ ├── disk.rb │ └── ringfile.rb │ └── templates │ └── default │ ├── account-server-conf.erb │ ├── auth-server.conf.erb │ ├── container-server-conf.erb │ ├── object-server-conf.erb │ ├── proxy-server.conf.erb │ ├── rsyncd.conf.erb │ ├── swift.conf.erb │ └── swift_nrpe.cfg.erb ├── data_bags └── crowbar │ ├── bc-default-swift.json │ └── bc-default-swift.schema ├── readme.txt └── roles ├── swift-proxy-acct.rb ├── swift-proxy.rb ├── swift-ring-compute.rb └── swift-storage.rb /cookbooks/memcached/README.rdoc: -------------------------------------------------------------------------------- 1 | = DESCRIPTION: 2 | 3 | Installs memcached and provides a define to set up an instance of memcache via runit. 4 | 5 | = REQUIREMENTS: 6 | 7 | == Platform: 8 | 9 | Tested on Ubuntu 8.10-9.10. Uses the memcached init script by default. A runit service can be set up for instances using the included define. 10 | 11 | == Cookbooks: 12 | 13 | Opscode cookbooks, http://github.com/opscode/cookbooks/tree/master: 14 | 15 | * runit 16 | 17 | = ATTRIBUTES: 18 | 19 | The following are node attributes passed to the template for the runit service. 20 | 21 | * memcached[:memory] - maximum memory for memcached instances. 22 | * memcached[:user] - user to run memcached as. 23 | * memcached[:port] - port for memcached to listen on. 24 | * memcached[:listen] - IP address for memcached to listen on. 25 | 26 | = USAGE: 27 | 28 | Simply set the attributes and it will configure the /etc/memcached.conf file. If you want to use multiple memcached instances, you'll need to modify the recipe to disable the startup script and the template in the default recipe. 29 | 30 | Use the define, memcached_instance, to set up a runit service for the named memcached instance. 31 | 32 | memcached_instance "myproj" 33 | 34 | = LICENSE and AUTHOR: 35 | 36 | Author:: Joshua Timberman () 37 | Author:: Joshua Sierles () 38 | 39 | Copyright:: 2009, Opscode, Inc 40 | Copyright:: 2009, 37signals 41 | 42 | Licensed under the Apache License, Version 2.0 (the "License"); 43 | you may not use this file except in compliance with the License. 44 | You may obtain a copy of the License at 45 | 46 | http://www.apache.org/licenses/LICENSE-2.0 47 | 48 | Unless required by applicable law or agreed to in writing, software 49 | distributed under the License is distributed on an "AS IS" BASIS, 50 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 51 | See the License for the specific language governing permissions and 52 | limitations under the License. 53 | -------------------------------------------------------------------------------- /cookbooks/memcached/attributes/default.rb: -------------------------------------------------------------------------------- 1 | default[:memcached][:memory] = 64 2 | default[:memcached][:port] = 11211 3 | default[:memcached][:user] = "nobody" 4 | default[:memcached][:listen] = "0.0.0.0" 5 | -------------------------------------------------------------------------------- /cookbooks/memcached/definitions/memcached_instance.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: memcached 3 | # Definition:: memcached_instance 4 | # 5 | # Copyright 2009, Opscode, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | define :memcached_instance do 21 | include_recipe "memcached" 22 | 23 | runit_service "memcached-#{params[:name]}" do 24 | template_name "memcached" 25 | cookbook "memcached" 26 | options({ 27 | :memory => node[:memcached][:memory], 28 | :port => node[:memcached][:port], 29 | :user => node[:memcached][:user]}.merge(params) 30 | ) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /cookbooks/memcached/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": { 3 | "debian": [ 4 | 5 | ], 6 | "ubuntu": [ 7 | 8 | ] 9 | }, 10 | "suggestions": { 11 | 12 | }, 13 | "license": "Apache 2.0", 14 | "conflicting": { 15 | 16 | }, 17 | "long_description": "= DESCRIPTION:\n\nInstalls memcached and provides a define to set up an instance of memcache via runit.\n\n= REQUIREMENTS:\n\n== Platform:\n\nTested on Ubuntu 8.10-9.10. Uses the memcached init script by default. A runit service can be set up for instances using the included define.\n\n== Cookbooks:\n\nOpscode cookbooks, http://github.com/opscode/cookbooks/tree/master:\n\n* runit\n\n= ATTRIBUTES: \n\nThe following are node attributes passed to the template for the runit service.\n\n* memcached[:memory] - maximum memory for memcached instances.\n* memcached[:user] - user to run memcached as.\n* memcached[:port] - port for memcached to listen on.\n* memcached[:listen] - IP address for memcached to listen on.\n\n= USAGE:\n\nSimply set the attributes and it will configure the /etc/memcached.conf file. If you want to use multiple memcached instances, you'll need to modify the recipe to disable the startup script and the template in the default recipe.\n\nUse the define, memcached_instance, to set up a runit service for the named memcached instance.\n\n memcached_instance \"myproj\" \n\n= LICENSE and AUTHOR:\n\nAuthor:: Joshua Timberman ()\nAuthor:: Joshua Sierles ()\n\nCopyright:: 2009, Opscode, Inc\nCopyright:: 2009, 37signals\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", 18 | "providing": { 19 | 20 | }, 21 | "description": "Installs memcached and provides a define to set up an instance of memcache via runit", 22 | "version": "0.10.4", 23 | "maintainer": "Opscode, Inc.", 24 | "replacing": { 25 | 26 | }, 27 | "attributes": { 28 | "memcached/listen": { 29 | "required": "optional", 30 | "calculated": false, 31 | "choice": [ 32 | 33 | ], 34 | "default": "0.0.0.0", 35 | "type": "string", 36 | "recipes": [ 37 | 38 | ], 39 | "display_name": "Memcached IP Address", 40 | "description": "IP address to use for memcached instance" 41 | }, 42 | "memcached/memory": { 43 | "required": "optional", 44 | "calculated": false, 45 | "choice": [ 46 | 47 | ], 48 | "default": "64", 49 | "type": "string", 50 | "recipes": [ 51 | 52 | ], 53 | "display_name": "Memcached Memory", 54 | "description": "Memory allocated for memcached instance" 55 | }, 56 | "memcached/user": { 57 | "required": "optional", 58 | "calculated": false, 59 | "choice": [ 60 | 61 | ], 62 | "default": "nobody", 63 | "type": "string", 64 | "recipes": [ 65 | 66 | ], 67 | "display_name": "Memcached User", 68 | "description": "User to run memcached instance as" 69 | }, 70 | "memcached/port": { 71 | "required": "optional", 72 | "calculated": false, 73 | "choice": [ 74 | 75 | ], 76 | "default": "11211", 77 | "type": "string", 78 | "recipes": [ 79 | 80 | ], 81 | "display_name": "Memcached Port", 82 | "description": "Port to use for memcached instance" 83 | } 84 | }, 85 | "maintainer_email": "cookbooks@opscode.com", 86 | "name": "memcached", 87 | "recipes": { 88 | "memcached": "Installs and configures memcached" 89 | }, 90 | "groupings": { 91 | 92 | }, 93 | "dependencies": { 94 | "runit": [ 95 | 96 | ] 97 | }, 98 | "recommendations": { 99 | 100 | } 101 | } -------------------------------------------------------------------------------- /cookbooks/memcached/metadata.rb: -------------------------------------------------------------------------------- 1 | maintainer "Opscode, Inc." 2 | maintainer_email "cookbooks@opscode.com" 3 | license "Apache 2.0" 4 | description "Installs memcached and provides a define to set up an instance of memcache via runit" 5 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc')) 6 | version "0.10.4" 7 | depends "runit" 8 | 9 | recipe "memcached", "Installs and configures memcached" 10 | 11 | %w{ ubuntu debian }.each do |os| 12 | supports os 13 | end 14 | 15 | attribute "memcached/memory", 16 | :display_name => "Memcached Memory", 17 | :description => "Memory allocated for memcached instance", 18 | :default => "64" 19 | 20 | attribute "memcached/port", 21 | :display_name => "Memcached Port", 22 | :description => "Port to use for memcached instance", 23 | :default => "11211" 24 | 25 | attribute "memcached/user", 26 | :display_name => "Memcached User", 27 | :description => "User to run memcached instance as", 28 | :default => "nobody" 29 | 30 | attribute "memcached/listen", 31 | :display_name => "Memcached IP Address", 32 | :description => "IP address to use for memcached instance", 33 | :default => "0.0.0.0" 34 | -------------------------------------------------------------------------------- /cookbooks/memcached/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: memcached 3 | # Recipe:: default 4 | # 5 | # Copyright 2009, Opscode, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | package "memcached" do 21 | action :upgrade 22 | end 23 | 24 | package "libmemcache-dev" do 25 | action :upgrade 26 | end 27 | 28 | service "memcached" do 29 | action :nothing 30 | supports :status => true, :start => true, :stop => true, :restart => true 31 | end 32 | 33 | template "/etc/memcached.conf" do 34 | source "memcached.conf.erb" 35 | owner "root" 36 | group "root" 37 | mode "0644" 38 | variables( 39 | :listen => node[:memcached][:listen], 40 | :user => node[:memcached][:user], 41 | :port => node[:memcached][:port], 42 | :memory => node[:memcached][:memory] 43 | ) 44 | notifies :restart, resources(:service => "memcached"), :immediately 45 | end 46 | 47 | case node[:lsb][:codename] 48 | when "karmic" 49 | template "/etc/default/memcached" do 50 | source "memcached.default.erb" 51 | owner "root" 52 | group "root" 53 | mode "0644" 54 | notifies :restart, resources(:service => "memcached"), :immediately 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /cookbooks/memcached/templates/default/memcached.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Configured by Chef. Logcal changes will be lost. 3 | # 4 | # memcached default config file 5 | # 2003 - Jay Bonci 6 | # This configuration file is read by the start-memcached script provided as 7 | # part of the Debian GNU/Linux distribution. 8 | 9 | # Run memcached as a daemon. This command is implied, and is not needed for the 10 | # daemon to run. See the README.Debian that comes with this package for more 11 | # information. 12 | -d 13 | 14 | # Log memcached's output to /var/log/memcached 15 | logfile /var/log/memcached.log 16 | 17 | # Be verbose 18 | -v 19 | 20 | # Be even more verbose (print client commands as well) 21 | # -vv 22 | 23 | # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default 24 | # Note that the daemon will grow to this size, but does not start out holding this much 25 | # memory 26 | -m <%= @memory %> 27 | 28 | # Default connection port is 11211 29 | -p <%= @port %> 30 | 31 | # Run the daemon as root. The start-memcached will default to running as root if no 32 | # -u command is present in this config file 33 | -u <%= @user %> 34 | 35 | # Specify which IP address to listen on. The default is to listen on all IP addresses 36 | # This parameter is one of the only security measures that memcached has, so make sure 37 | # it's listening on a firewalled interface. 38 | -l <%= @listen %> 39 | 40 | # Limit the number of simultaneous incoming connections. The daemon default is 1024 41 | # -c 1024 42 | 43 | # Lock down all paged memory. Consult with the README and homepage before you do this 44 | # -k 45 | 46 | # Return error when memory is exhausted (rather than removing items) 47 | # -M 48 | 49 | # Maximize core file limit 50 | # -r 51 | -------------------------------------------------------------------------------- /cookbooks/memcached/templates/default/memcached.default.erb: -------------------------------------------------------------------------------- 1 | # Set this to yes to enable memcached. 2 | ENABLE_MEMCACHED=yes 3 | -------------------------------------------------------------------------------- /cookbooks/memcached/templates/default/sv-memcached-log-run.erb: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec svlogd -tt ./main 3 | -------------------------------------------------------------------------------- /cookbooks/memcached/templates/default/sv-memcached-run.erb: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec 2>&1 3 | exec chpst -u <%= @options[:user] %> /usr/bin/memcached -v -m <%= @options[:memory] %> -p <%= @options[:port] %> 4 | -------------------------------------------------------------------------------- /cookbooks/swift/README.rdoc: -------------------------------------------------------------------------------- 1 | = DESCRIPTION: 2 | 3 | = REQUIREMENTS: 4 | 5 | = ATTRIBUTES: 6 | 7 | = USAGE: 8 | 9 | -------------------------------------------------------------------------------- /cookbooks/swift/attributes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | ### The cluster hash is shared among all nodes in a swift cluster. 19 | ### can be generated using od -t x8 -N 8 -A n = # of replicas) 26 | default[:swift][:zones]= 2 27 | ## minimum amount of time a partition should stay put, in hours 28 | default[:swift][:min_part_hours]= 1 29 | ## number of bits to represent the partitions count 30 | default[:swift][:partitions]= 18 31 | 32 | ### the uid/gid to be used for swift processes 33 | default[:swift][:user]= "swift" 34 | default[:swift][:group]= "swift" 35 | 36 | 37 | default[:swift][:config] = {} 38 | default[:swift][:config][:environment] = "default" 39 | 40 | ### where to find IP for admin use 41 | default[:swift][:admin_ip_expr] = "node[:ipaddress]" 42 | ### where to find IP for admin use 43 | default[:swift][:storage_ip_expr] = "node[:ipaddress]" 44 | 45 | # expression to find a hash of possible disks to be used. 46 | default[:swift][:disk_enum_expr]= 'node[:block_device]' 47 | # expression accepting a k,v pair for evaluation. if expression returns true, then the disk will be used. 48 | # by default, use any sdX or hdX that is not the first one (which will hold the OS). 49 | default[:swift][:disk_test_expr]= 'k =~/sd[^a]/ or k=~/hd[^a]/' 50 | 51 | # An expression to classify disks into zone's and assign them a weight. 52 | # return 53 | # - nil: the disk is not included in the ring 54 | # - otherwise an array of [zone, weight]. Zone is an integer representing the zone # for the disk is expected, weight is the weight of the disk 55 | # the default expression below just assigns disks in a round robin fashion. 56 | # 57 | # The expression is evaluated with the following context: 58 | # - node - the Chef node hash 59 | # - params - a hash with the following keys: 60 | # :ring=> one of "object", "account" or "container" 61 | # :disk=> disk partition information as created in disks.rb,contains: :name (e.g sdb) :size either :remaining (= all the disk) or an actual byte count. 62 | default[:swift][:disk_zone_assign_expr] = '$DISK_CNT||=0; $DISK_CNT= $DISK_CNT+1 ;[ $DISK_CNT % node[:swift][:zones] , 99]' 63 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/default-rsync: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | # 14 | # 15 | # defaults file for rsync daemon mode 16 | 17 | # start rsync in daemon mode from init.d script? 18 | # only allowed values are "true", "false", and "inetd" 19 | # Use "inetd" if you want to start the rsyncd from inetd, 20 | # all this does is prevent the init.d script from printing a message 21 | # about not starting rsyncd (you still need to modify inetd's config yourself). 22 | RSYNC_ENABLE=true 23 | 24 | # which file should be used as the configuration file for rsync. 25 | # This file is used instead of the default /etc/rsyncd.conf 26 | # Warning: This option has no effect if the daemon is accessed 27 | # using a remote shell. When using a different file for 28 | # rsync you might want to symlink /etc/rsyncd.conf to 29 | # that file. 30 | # RSYNC_CONFIG_FILE= 31 | 32 | # what extra options to give rsync --daemon? 33 | # that excludes the --daemon; that's always done in the init.d script 34 | # Possibilities are: 35 | # --address=123.45.67.89 (bind to a specific IP address) 36 | # --port=8730 (bind to specified port; default 873) 37 | RSYNC_OPTS='' 38 | 39 | # run rsyncd at a nice level? 40 | # the rsync daemon can impact performance due to much I/O and CPU usage, 41 | # so you may want to run it at a nicer priority than the default priority. 42 | # Allowed values are 0 - 19 inclusive; 10 is a reasonable value. 43 | RSYNC_NICE='' 44 | 45 | # run rsyncd with ionice? 46 | # "ionice" does for IO load what "nice" does for CPU load. 47 | # As rsync is often used for backups which aren't all that time-critical, 48 | # reducing the rsync IO priority will benefit the rest of the system. 49 | # See the manpage for ionice for allowed options. 50 | # -c3 is recommended, this will run rsync IO at "idle" priority. Uncomment 51 | # the next line to activate this. 52 | # RSYNC_IONICE='-c3' 53 | 54 | # Don't forget to create an appropriate config file, 55 | # else the daemon will not start. 56 | 57 | -------------------------------------------------------------------------------- /cookbooks/swift/libraries/eval.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | require 'chef' 20 | 21 | class Swift 22 | class Evaluator 23 | 24 | def initialize(node) 25 | @b = binding 26 | end 27 | 28 | def eval_with_context(str) 29 | eval(str,@b) 30 | end 31 | 32 | def self.eval_with_params(str,node,params) 33 | b = binding 34 | b.eval(str) 35 | end 36 | 37 | def log_eval_vars() 38 | eval("Chef::Log.info('locals:'+local_variables.join(':') + '\nglobals:'+global_variables.join(':'))") 39 | end 40 | 41 | 42 | def self.get_ip_by_type(node, type) 43 | ip_location = node[:swift][type] 44 | e = Evaluator.new(node) 45 | ip = e.eval_with_context(ip_location) 46 | Chef::Log.info("Looking at #{ip_location} for #{type} IP addr. Got: #{ip}") 47 | ip 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /cookbooks/swift/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": { 3 | 4 | }, 5 | "suggestions": { 6 | 7 | }, 8 | "license": "Apache 2.0", 9 | "conflicting": { 10 | 11 | }, 12 | "long_description": "= DESCRIPTION:\n\n= REQUIREMENTS:\n\n= ATTRIBUTES: \n\n= USAGE:\n\n", 13 | "providing": { 14 | 15 | }, 16 | "description": "Installs/Configures cloudfiles", 17 | "version": "0.1.0", 18 | "maintainer": "Opscode, Inc.", 19 | "replacing": { 20 | 21 | }, 22 | "attributes": { 23 | 24 | }, 25 | "maintainer_email": "oss@opscode.com", 26 | "name": "swift", 27 | "recipes": { 28 | 29 | }, 30 | "groupings": { 31 | 32 | }, 33 | "dependencies": { 34 | "memcached": [ 35 | 36 | ] 37 | }, 38 | "recommendations": { 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /cookbooks/swift/metadata.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | maintainer "Opscode, Inc." 19 | maintainer_email "oss@opscode.com" 20 | license "Apache 2.0" 21 | description "Installs/Configures cloudfiles" 22 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc')) 23 | version "0.1" 24 | depends "memcached" -------------------------------------------------------------------------------- /cookbooks/swift/providers/disk.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | require 'chef/mixin/shell_out' 20 | include Chef::Mixin::ShellOut 21 | 22 | 23 | def load_current_resource 24 | dev_name = @new_resource.name 25 | @current = Chef::Resource::SwiftDisk.new(dev_name) 26 | 27 | parted_partition_parse dev_name 28 | geo = @current.geo() 29 | if geo.nil? or geo[:cyl_size].nil? 30 | ### if the device has no good partition table, parted returns nothing useful 31 | ### use sfdisk to get the info 32 | Chef::Log.info("parted didn't geo, running sfdisk") 33 | sfdisk_get_geo dev_name 34 | geo = @current.geo() 35 | end 36 | 37 | parts = @current.part() 38 | 39 | s = < cyl.to_f, 60 | :head => head.to_f, 61 | :sector => sector.to_f, 62 | :cyl_size => cyl_size.to_f 63 | }) 64 | @current.geo[:cyl_size_computed] = @current.geo[:head].to_f * @current.geo[:sector].to_f * 512 65 | end 66 | 67 | =begin 68 | sample output 69 | # sfdisk /dev/sdb -g 70 | /dev/sdb: 261 cylinders, 255 heads, 63 sectors/track 71 | =end 72 | def sfdisk_get_geo(dev_name) 73 | out = %x{sfdisk #{dev_name} -g} 74 | Chef::Log.info("updating geo using sfdisk: #{out}") 75 | 76 | out =~ /^(.*):[ ]*([0-9]+).*,[ ]*([0-9]+).*,[ ]*([0-9]+).*$/ 77 | set_geo($2,$3,$4) 78 | end 79 | 80 | 81 | def parted_partition_parse(dev_name) 82 | Chef::Log.debug("reading partition table for #{dev_name}") 83 | =begin 84 | Run parted to get basic info about the disk 85 | sample output: 86 | ~# parted -m -s /dev/sda unit cyl print 87 | CYL; 88 | /dev/sda:1044cyl:scsi:512:512:msdos:VMware Virtual disk; 89 | 1044:255:63:8225kB; 90 | 1:0cyl:31cyl:30cyl:ext2::boot; 91 | 2:31cyl:1044cyl:1012cyl:::; 92 | 5:31cyl:1044cyl:1012cyl:::lvm; 93 | =end 94 | pipe= IO.popen("parted -m -s #{dev_name} unit cyl print") # this can return 1, but it's ok (if no partition table present, we'll create it) 95 | result = pipe.readlines 96 | parted_parse_results result 97 | end 98 | 99 | def parted_parse_results(input) 100 | Chef::Log.debug("read:" + input.inspect) 101 | input = input.to_a 102 | part_tab = [] 103 | catch (:parse_error) do 104 | line = input.shift 105 | throw :parse_error if line =~ /^Error:/ 106 | line = input.shift # CYL; 107 | throw :parse_error unless line =~ /\/dev\/([^\/]+):([0-9]+)cyl:(.*):.*$/ 108 | 109 | line = input.shift # 1044:255:63:8225kB; 110 | throw :parse_error unless line =~ /([0-9]+):([0-9]+):([0-9]+):(([0-9]+)([a-zA-Z]*));$/ 111 | set_geo(Regexp.last_match(1), Regexp.last_match(2), Regexp.last_match(3), size_to_bytes(Regexp.last_match(4))) 112 | 113 | input.each { |line| 114 | # 1:0cyl:31cyl:30cyl:ext2::boot; 115 | throw :parse_error unless line =~ /([0-9]):([0-9]+)cyl:([0-9]+)cyl:([0-9]+)cyl:(.*):(.*);$/ 116 | part_num = Regexp.last_match(1).to_i 117 | part_info = { 118 | :num => part_num, 119 | :start => Regexp.last_match(2), 120 | :end => Regexp.last_match(3), 121 | :size => size_to_bytes(Regexp.last_match(4)), 122 | :type => Regexp.last_match(5), 123 | :system => Regexp.last_match(6), 124 | :flags => Regexp.last_match(7) } 125 | part_tab << part_info 126 | } 127 | end 128 | 129 | @current.part(part_tab) 130 | part_tab 131 | end 132 | 133 | 134 | def size_to_bytes(s) 135 | case s 136 | when /^([0-9]+)$/ 137 | return $1.to_f 138 | 139 | when /^([0-9]+)[Kk][Bb]$/ 140 | return $1.to_f * 1024 141 | 142 | when /^([0-9]+)[Mm][Bb]$/ 143 | return $1.to_f * 1024 * 1024 144 | 145 | when /^([0-9]+)[Gg][Bb]$/ 146 | return $1.to_f * 1024 * 1024 * 1024 147 | 148 | when /^([0-9]+)[Tt][Bb]$/ 149 | return $1.to_f * 1024 * 1024 * 1024 * 1024 150 | 151 | end 152 | -1 153 | end 154 | 155 | action :list do 156 | Chef::Log.info("at some point there'll be a list") 157 | end 158 | 159 | #### 160 | # compare the requested partition table parameters to what exists 161 | # if differences found - remove all current partitions, and create new ones. 162 | # An existing partition is considered a match if: 163 | # - it has the same serial # (1,2,3) 164 | # - it has the same size 165 | 166 | action :ensure_exists do 167 | req = @new_resource.part 168 | cur = @current.part 169 | dev_name = @new_resource.name 170 | 171 | recreate, delete_existing = false 172 | cyl_size = @current.geo[:cyl_size_computed] 173 | 174 | if (cur.nil?) 175 | recreate = true; 176 | else 177 | cur_cyl = 0 178 | idx = 0 179 | req.each { |params| 180 | if (cur[idx].nil?) 181 | recreate = true 182 | Chef::Log.info("no current #{idx}") 183 | next 184 | end 185 | req_size = params[:size] 186 | if (req_size == :remaining) 187 | req_size = (@current.geo[:cyl] - cur_cyl -1) * cyl_size 188 | end 189 | cur_size = cur[idx][:size] * cyl_size 190 | cur_min, cur_max = req_size*0.9, req_size*1.1 191 | if !(cur_size > cur_min and cur_size < cur_max) 192 | recreate = true 193 | end 194 | cur_cyl += cur[idx][:size] 195 | idx+=1 196 | Chef::Log.info("partition #{idx} #{(recreate ? 'differs' : 'is same')}: #{cur_size}/ #{req_size}") 197 | } 198 | end 199 | 200 | if !recreate 201 | Chef::Log.info("partition table matches - not recreating") 202 | @current.updated_by_last_action(false) 203 | else 204 | @current.updated_by_last_action(true) 205 | 206 | ### make sure to ensure that there are no mounted 207 | ### filesystems on the device 208 | re = /^(#{Regexp.escape(dev_name)}[0-9]+)/ 209 | mounted = [] 210 | shell_out!("mount").stdout.each_line { |line| 211 | md = re.match(line) 212 | next unless md 213 | mounted << md[1] 214 | } 215 | mounted.each { |m| 216 | Chef::Log.info("unmounting #{m}") 217 | shell_out!("umount #{m}") 218 | } 219 | 220 | # Nuke current partition table. 221 | execute "create new partition table" do 222 | command "parted -s -m #{dev_name} mktable bsd" 223 | end 224 | 225 | # create new partitions 226 | cur_cyl = 0 227 | idx = 0 228 | req.each { | params | 229 | if (params[:size] == :remaining) 230 | cyls = (@current.geo[:cyl] - cur_cyl - 1) 231 | else 232 | cyls = (params[:size].to_f / cyl_size.to_f).floor.to_i 233 | end 234 | s = "parted -m -s #{dev_name} unit cyl " 235 | s << "mkpart #{cur_cyl.to_i} #{(cur_cyl += cyls).to_i} " # #{params[:type]} 236 | Chef::Log.info("creating new partition #{idx+1} with:" + s) 237 | execute "creating partition #{idx}" do 238 | command s 239 | end 240 | idx+=1 241 | } 242 | end 243 | end 244 | 245 | -------------------------------------------------------------------------------- /cookbooks/swift/providers/ringfile.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | ## 20 | # This LWRP will read the current state of a current ring, by executing 21 | # swift-ring-builder and parsing its output. It would then compare the 22 | # desired set of disks to the disks present. 23 | # It currently does not change parameters (zone assignment or weight). 24 | # to achieve that, you'd have to remove and readd the disk. 25 | 26 | ## 27 | # some internal data structs to hold ring info read from existing files 28 | class RingInfo 29 | attr_accessor :partitions, :replicas, :zones, :device_num, :devices, :min_part_hours 30 | 31 | class RingDeviceInfo 32 | attr_accessor :id, :zone, :ip, :port, :name, :weight, :partitions 33 | 34 | def initialize 35 | Chef::Log.debug "new device" 36 | self 37 | end 38 | def to_s 39 | s = "" 40 | s <<"@" << @id <<":" << @zone << "[" << @ip <<":" << @port <<"]/" << @name 41 | end 42 | end 43 | 44 | def initialize 45 | @devices = {} 46 | self 47 | end 48 | 49 | def self.dev_key ip,port,name 50 | "" << ip << ":" << port.to_s << "-" << name 51 | end 52 | 53 | def add_device d 54 | Chef::Log.debug "added device @ip #{d.ip}:#{d.port}" 55 | key = RingInfo.dev_key d.ip,d.port ,d.name 56 | @devices[key] = d 57 | end 58 | 59 | def to_s 60 | s="" 61 | #s <<"r:" << @replicas <<"z:" << @zones 62 | devices.each { |d| 63 | s << "\n " << d.to_s 64 | } 65 | end 66 | end 67 | 68 | 69 | 70 | def load_current_resource 71 | name = @new_resource.name 72 | name = "/etc/swift/#{name}" 73 | @current_resource = Chef::Resource::SwiftRingfile.new(name) 74 | @ring_test = nil 75 | Chef::Log.info("parsing ring-file for #{name}") 76 | IO.popen("swift-ring-builder #{name}") { |pipe| 77 | ring_txt=pipe.readlines 78 | Chef::Log.debug("raw ring info:#{ring_txt}") 79 | @ring_test = scan_ring_desc ring_txt 80 | Chef::Log.debug("at end of load, current ring is: #{@ring_test.to_s}") 81 | } 82 | compute_deltas 83 | end 84 | 85 | 86 | def scan_ring_desc(input) 87 | 88 | r = RingInfo.new 89 | state = :init 90 | next_state ='' # if the current state is ignore, this is the next state 91 | ignore_count = 0 # the number of lines to ignore 92 | input.each { |line| 93 | 94 | case state 95 | when :init 96 | state=:gen_info 97 | next 98 | 99 | when :ignore 100 | Chef::Log.debug("ignoring line:" + line ) 101 | ignore_count -= 1 102 | if (ignore_count ==0) 103 | state = next_state 104 | end 105 | next 106 | 107 | when :gen_info 108 | line =~/^(\d+).+,(\d+).+,(\d+).+,(\d+).*,([0-9.]+).+$/ 109 | r.partitions=$1 110 | r.replicas=$2 111 | r.zones=$3 112 | r.device_num=$4 113 | state = :ignore 114 | next_state = :dev_info 115 | ignore_count =2 116 | next 117 | 118 | when :dev_info # 0 1 192.168.124.131 6002 sdb1 100.00 0 -100.00 119 | Chef::Log.debug "reading dev info:" + line 120 | line =~ /^\s+(\d+)\s+(\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+)\s+(\S+)\s+([0-9.]+)\s+(\d+)\s+([-0-9.]+)\s*$/ 121 | if $~.nil? 122 | raise "failed to parse: #{line}" 123 | else 124 | Chef::Log.debug "matched: #{$~[0]}" 125 | end 126 | dev = RingInfo::RingDeviceInfo.new 127 | dev.id = $1 128 | dev.zone = $2 129 | dev.ip = $3 130 | dev.port = $4 131 | dev.name = $5 132 | dev.weight = $6 133 | dev.partitions = $7 134 | r.add_device dev 135 | end 136 | } 137 | r 138 | end 139 | 140 | 141 | ### 142 | # compute disks to be added or removed (and update the dirty flag) 143 | def compute_deltas 144 | req_disks = @new_resource.disks 145 | keyed_req = {} # for easy lookup, make a map of the requested disks 146 | cur = @ring_test 147 | name = @new_resource.name 148 | @to_add = [] 149 | @to_rem = [] 150 | 151 | 152 | ## figure out which disks need adding 153 | req_disks.each {|disk| 154 | key = RingInfo.dev_key disk[:ip],disk[:port],disk[:dev_name] 155 | @to_add << disk unless cur and cur.devices[key] # add unless present 156 | keyed_req[key] = disk 157 | } 158 | 159 | ### figure out which disks need removing 160 | cur.devices.each {|key, d| 161 | @to_rem << d unless keyed_req[key] # remove unless still requested 162 | } if cur 163 | 164 | Chef::Log.info("disks, to add #{@to_add.length} , to remove: #{@to_rem.length}" ) 165 | Chef::Log.debug("disks, to add #{@to_add.join(";")} , to remove: #{@to_rem.join(";")}" ) 166 | 167 | end 168 | 169 | action :apply do 170 | name = @new_resource.name 171 | cur=@ring_test 172 | Chef::Log.info("current content of: #{name} #{(cur.nil? ? "-not there" : cur.to_s)}") 173 | 174 | ## make sure file exists 175 | create_ring 176 | 177 | # if we're changing the ring, make sure that file timestamps differ somewhat 178 | if @to_add.length > 0 or @to_rem.length > 0 179 | sleep 0.1 180 | end 181 | 182 | @to_add.each { |d| 183 | execute "add disk #{d[:ip]}:#{d[:port]}/#{d[:dev_name]} to #{name}" do 184 | command "swift-ring-builder #{name} add z#{d[:zone]}-#{d[:ip]}:#{d[:port]}/#{d[:dev_name]} #{d[:weight]}" 185 | cwd "/etc/swift" 186 | returns 1 187 | end 188 | } 189 | 190 | @to_rem.each {|d| 191 | execute "remove disk #{d.id} from #{name}" do 192 | command "swift-ring-builder #{name} remove d#{d.id} " 193 | cwd "/etc/swift" 194 | returns 1 195 | end 196 | } 197 | end 198 | 199 | 200 | action :rebalance do 201 | name = @current_resource.name 202 | dirty = false 203 | 204 | ring_data_mtime= ::File.new(name).mtime if ::File.exist?(name) 205 | ring_data_mtime ||= File.new(name).mtime if ::File.exist?(name) 206 | ring_data_mtime ||= 0 207 | ring_name = name.sub(/^(.*)\..*$/, '\1.ring.gz') 208 | ring_file_mtime = (::File.exist?(ring_name) ? ::File.mtime(ring_name) : -1) 209 | dirty = true if (ring_data_mtime.to_i > ring_file_mtime.to_i) 210 | 211 | Chef::Log.info("current status for: #{name} is #{dirty ? "dirty" : "not-dirty"} #{ring_name} #{ring_data_mtime.to_i}/#{ring_file_mtime.to_i}") 212 | 213 | execute "rebalance ring for #{name}" do 214 | command "swift-ring-builder #{name} rebalance" 215 | cwd "/etc/swift" 216 | returns [0,1] # returns 1 if it didn't do anything, 2 on 217 | end if dirty 218 | 219 | # if no rebalance was needed, but the the ring file is not there, make sure to make it. 220 | if !::File.exist?(ring_name) then 221 | dirty = true 222 | execute "writeout ring for #{name}" do 223 | command "swift-ring-builder #{name} write_ring" 224 | cwd "/etc/swift" 225 | returns [0,1] ## returns 1 if it didn't do anything, 2 on error. 226 | end 227 | end 228 | 229 | @new_resource.updated_by_last_action(dirty) 230 | end 231 | 232 | 233 | 234 | def create_ring 235 | name = @new_resource.name 236 | mh = @new_resource.min_part_hours ? @new_resource.min_part_hours : 1 237 | parts = @new_resource.partitions ? @new_resource.partitions : 18 238 | replicas = @new_resource.replicas ? @new_resource.replicas : 3 239 | 240 | execute "create #{name} ring" do 241 | command "swift-ring-builder #{name} create #{parts} #{replicas} #{mh}" 242 | creates "/etc/swift/#{name}" 243 | cwd "/etc/swift" 244 | end 245 | end 246 | 247 | 248 | if __FILE__ == $0 249 | # produced by: 250 | # root@d00-0c-29-14-30-92:/etc/swift# swift-ring-builder account.builder 251 | 252 | test_str=< node[:swift][:cluster_hash] 37 | }) 38 | end 39 | 40 | directory "/var/lock/swift" do 41 | owner "swift" 42 | group "swift" 43 | mode "0755" 44 | end 45 | 46 | 47 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/disks.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | package "xfsprogs" 20 | 21 | log("locating disks using #{node[:swift][:disk_enum_expr]} test: #{node[:swift][:disk_test_expr]}") {level :debug} 22 | to_use_disks = {} 23 | all_disks = eval(node[:swift][:disk_enum_expr]) 24 | all_disks.each { |k,v| 25 | b = binding() 26 | to_use_disks[k]=v if eval(node[:swift][:disk_test_expr]) 27 | } 28 | 29 | log("will use these disks: #{to_use_disks.keys.join(':')}") {level :debug} 30 | 31 | node[:swift][:devs] = [] 32 | to_use_disks.each { |k,v| 33 | 34 | target_suffix= k + "1" # by default, will use format first partition. 35 | target_dev = "/dev/#{k}" 36 | target_dev_part = "/dev/#{target_suffix}" 37 | 38 | # protect against OS's that confuse ohai. if the device isnt there.. don't 'try to use it. 39 | if File.exists?(target_dev) == false 40 | log ("device: #{target_dev} doesn't seem to exist. ignoring") {level :warn } 41 | next 42 | end 43 | 44 | swift_disk "/dev/#{k}" do 45 | part [{ :type => "xfs", :size => :remaining} ] 46 | action :ensure_exists 47 | end 48 | 49 | 50 | execute "make xfs filesystem on #{k}" do 51 | command "mkfs.xfs -f -i size=1024 #{target_dev}" 52 | ## test if the FS is already an XFS file system. 53 | not_if "xfs_admin -l #{target_dev}" 54 | end 55 | 56 | directory "/srv/node/#{target_suffix}" do 57 | group "swift" 58 | owner "swift" 59 | recursive true 60 | action :create 61 | end 62 | 63 | mount "/srv/node/#{target_suffix}" do 64 | device target_dev 65 | options "noatime,nodiratime,nobarrier,logbufs=8" 66 | dump 0 67 | fstype "xfs" 68 | action [:mount, :enable] 69 | end 70 | #### 71 | # publish the disks 72 | node[:swift][:devs] << {:name=>target_suffix, :size=> :remaining } 73 | } 74 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/monitor.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | #### 20 | # if monitored by nagios, install the nrpe commands 21 | 22 | swift_svcs = node[:swift][:monitor][:svcs] 23 | swift_ports = node[:swift][:monitor][:ports] 24 | log ("will monitor swift svcs: #{swift_svcs.join(',')} and ports #{swift_ports.values.join(',')}") 25 | 26 | template "/etc/nagios/nrpe.d/swift_nrpe.cfg" do 27 | source "swift_nrpe.cfg.erb" 28 | mode "0644" 29 | group node[:nagios][:group] 30 | owner node[:nagios][:user] 31 | variables( { 32 | :svcs => swift_svcs , 33 | :swift_ports => swift_ports 34 | }) 35 | notifies :restart, resources(:service => "nagios-nrpe-server") 36 | end if node.role?("nagios-client") 37 | 38 | service "nagios-nrpe-server" do 39 | action :nothing 40 | end 41 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/proxy.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | include_recipe 'apt' 20 | include_recipe 'utils' 21 | include_recipe 'swift::auth' 22 | 23 | %w{curl python-software-properties memcached swift-proxy}.each do |pkg| 24 | package pkg 25 | end 26 | 27 | ## note that trying to use the resource fails in odd ways... 28 | execute "create auth cert" do 29 | cwd "/etc/swift" 30 | creates "/etc/swift/cert.crt" 31 | group node[:swift][:group] 32 | user node[:swift][:user] 33 | command <<-EOH 34 | /usr/bin/openssl req -new -x509 -nodes -out cert.crt -keyout cert.key -batch &>/dev/null 0 0) 45 | memcached_servers = result.map {|x| 46 | s = Swift::Evaluator.get_ip_by_type(x, :admin_ip_expr) 47 | s += ":11211 " 48 | } 49 | log("memcached servers" + memcached_servers.join(":")) {level :debug} 50 | servers = memcached_servers.join(":") 51 | else 52 | log("found no swift-proxy nodes") {level :warn} 53 | end 54 | 55 | local_ip = Swift::Evaluator.get_ip_by_type(node, :admin_ip_expr) 56 | ## Create the proxy server configuraiton file 57 | template "/etc/swift/proxy-server.conf" do 58 | source "proxy-server.conf.erb" 59 | mode "0644" 60 | group node[:swift][:group] 61 | owner node[:swift][:user] 62 | variables( { 63 | :admin_key => node[:swift][:cluster_admin_pw], 64 | :memcached_ips => servers, 65 | :localip => local_ip , 66 | :user =>node[:swift][:user], 67 | :debug => node[:swift][:debug], 68 | :account_management => node[:swift]["account_management"] 69 | }) 70 | end 71 | 72 | ## install a default memcached instsance. 73 | ## default configuration is take from: node[:memcached] / [:memory], [:port] and [:user] 74 | node[:memcached][:listen] = local_ip 75 | node[:memcached][:name] = "swift-proxy" 76 | memcached_instance do 77 | end 78 | 79 | 80 | service "swift-proxy" do 81 | action [:enable, :start] 82 | end 83 | 84 | ### 85 | # let the monitoring tools know what services should be running on this node. 86 | node[:swift][:monitor] = {} 87 | node[:swift][:monitor][:svcs] = ["swift-proxy", "memcached" ] 88 | node[:swift][:monitor][:ports] = {:proxy =>8080} 89 | node.save -------------------------------------------------------------------------------- /cookbooks/swift/recipes/ring-compute.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2011, Dell 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # Author: andi abes 16 | # 17 | 18 | include_recipe 'swift::rsync' 19 | 20 | ## 21 | # Assumptions: 22 | # - The partitions to be used on each node are in node[:swift][:devs] 23 | # - only nodes which have the swift-storage role assigned are used. 24 | 25 | 26 | env_filter = " AND swift_config_environment:#{node[:swift][:config][:environment]}" 27 | nodes = search(:node, "roles:swift-storage#{env_filter}") 28 | 29 | =begin 30 | http://swift.openstack.org/howto_installmultinode.html 31 | 32 | swift-ring-builder account.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6002/$DEVICE $WEIGHT 33 | swift-ring-builder container.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6001/$DEVICE $WEIGHT 34 | swift-ring-builder object.builder add z$ZONE-$STORAGE_LOCAL_NET_IP:6000/$DEVICE $WEIGHT 35 | 36 | command "swift-ring-builder object.builder add z#{zone}-#{storage_ip_addr}:6000/#{disk[:name]} #{weight}" 37 | =end 38 | 39 | 40 | #### 41 | # collect the current contents of the ring files. 42 | disks_a= [] 43 | disks_c= [] 44 | disks_o= [] 45 | ## collect the nodes that need to be notified when ring files are updated 46 | target_nodes=[] 47 | zone_round_robin =1 48 | replicas = node[:swift][:replicas] 49 | zones = node[:swift][:zones] 50 | disk_assign_expr = node[:swift][:disk_zone_assign_expr] 51 | hash = node[:swift][:cluster_hash] 52 | 53 | log ("cluster config: replicas:#{replicas} zones:#{zones} hash:#{hash}") 54 | nodes.each { |node| 55 | storage_ip = Swift::Evaluator.get_ip_by_type(node, :storage_ip_expr) 56 | target_nodes << storage_ip 57 | log ("Looking at node: #{storage_ip}") {level :debug} 58 | disks=node[:swift][:devs] 59 | next if disks.nil? 60 | disks.each {|disk| 61 | z_o, w_o = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), :ring=> "object", :disk=>disk) 62 | z_c,w_c = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), :ring=> "container", :disk=>disk) 63 | z_a,w_a = Swift::Evaluator.eval_with_params(disk_assign_expr, node(), :ring=> "account", :disk=>disk) 64 | 65 | log("obj: #{z_o}/#{w_o} container: #{z_c}/#{w_c} account: #{z_a}/#{w_a}. count: #{$DISK_CNT}") {level :debug} 66 | d = {:ip => storage_ip, :dev_name=>disk[:name], :port => 6000} 67 | if z_o 68 | d[:port] = 6000; d[:zone]=z_o ; d[:weight]=w_o 69 | disks_o << d 70 | end 71 | d = d.dup 72 | if z_c 73 | d[:port] = 6001; d[:zone]=z_c ; d[:weight]=w_c 74 | disks_c << d 75 | end 76 | d = d.dup 77 | if z_a 78 | d[:port] = 6002; d[:zone]=z_a ; d[:weight]=w_a 79 | disks_a << d 80 | end 81 | 82 | 83 | } 84 | } 85 | 86 | replicas = node[:swift][:replicas] 87 | min_move = node[:swift][:min_part_hours] 88 | parts = node[:swift][:partitions] 89 | 90 | swift_ringfile "account.builder" do 91 | disks disks_a 92 | replicas replicas 93 | min_part_hours min_move 94 | partitions parts 95 | action [:apply, :rebalance] 96 | end 97 | swift_ringfile "container.builder" do 98 | disks disks_c 99 | replicas replicas 100 | min_part_hours min_move 101 | partitions parts 102 | action [:apply, :rebalance] 103 | end 104 | swift_ringfile "object.builder" do 105 | disks disks_o 106 | replicas replicas 107 | min_part_hours min_move 108 | partitions parts 109 | action [:apply, :rebalance] 110 | end 111 | 112 | 113 | log ("nodes to notify: #{target_nodes.join ' '}") {level :debug} 114 | target_nodes.each {|t| 115 | execute "push account ring-to #{t}" do 116 | command "rsync account.ring.gz #{node[:swift][:user]}@#{t}::ring" 117 | cwd "/etc/swift" 118 | action :nothing 119 | subscribes :run, resources(:swift_ringfile =>"account.builder") 120 | end 121 | execute "push container ring-to #{t}" do 122 | command "rsync container.ring.gz #{node[:swift][:user]}@#{t}::ring" 123 | cwd "/etc/swift" 124 | action :nothing 125 | subscribes :run, resources(:swift_ringfile =>"container.builder") 126 | end 127 | execute "push object ring-to #{t}" do 128 | command "rsync object.ring.gz #{node[:swift][:user]}@#{t}::ring" 129 | cwd "/etc/swift" 130 | action :nothing 131 | subscribes :run, resources(:swift_ringfile =>"object.builder") 132 | end 133 | } 134 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/rsync.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | storage_ip = Swift::Evaluator.get_ip_by_type(node,:storage_ip_expr) 20 | template "/etc/rsyncd.conf" do 21 | source "rsyncd.conf.erb" 22 | variables({ 23 | :uid => node[:swift][:user], 24 | :gid => node[:swift][:group], 25 | :storage_net_ip => storage_ip 26 | }) 27 | end 28 | 29 | cookbook_file "/etc/default/rsync" do 30 | source "default-rsync" 31 | end 32 | 33 | service "rsync" do 34 | action :start 35 | end 36 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/storage.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | include_recipe 'apt' 20 | include_recipe 'swift::disks' 21 | include_recipe 'swift::auth' 22 | include_recipe 'swift::rsync' 23 | 24 | %w{swift-container swift-object sqlite }.each do |pkg| 25 | package pkg 26 | end 27 | 28 | storage_ip = Swift::Evaluator.get_ip_by_type(node,:storage_ip_expr) 29 | 30 | %w{account-server object-server container-server}.each do |service| 31 | template "/etc/swift/#{service}.conf" do 32 | source "#{service}-conf.erb" 33 | owner "swift" 34 | group "swift" 35 | variables({ 36 | :uid => node[:swift][:user], 37 | :gid => node[:swift][:group], 38 | :storage_net_ip => storage_ip, 39 | :server_num => 1, ## could allow multiple servers on the same machine 40 | :admin_key => node[:swift][:cluster_admin_pw], 41 | :debug => node[:swift][:debug] 42 | }) 43 | end 44 | end 45 | 46 | 47 | svcs = %w{swift-object swift-object-auditor swift-object-replicator swift-object-updater} 48 | svcs = svcs + %w{swift-container swift-container-auditor swift-container-replicator swift-container-updater} 49 | svcs = svcs + %w{swift-account swift-account-reaper swift-account-auditor swift-account-replicator} 50 | 51 | ## make sure to fetch ring files from the ring compute node 52 | env_filter = " AND swift_config_environment:#{node[:swift][:config][:environment]}" 53 | compute_nodes = search(:node, "roles:swift-ring-compute#{env_filter}") 54 | if (!compute_nodes.nil? and compute_nodes.length > 0 ) 55 | compute_node_addr = Swift::Evaluator.get_ip_by_type(compute_nodes[0],:storage_ip_expr) 56 | log("ring compute found on: #{compute_nodes[0][:fqdn]} using: #{compute_node_addr}") {level :debug} 57 | %w{container account object}.each { |ring| 58 | execute "pull #{ring} ring" do 59 | command "rsync #{node[:swift][:user]}@#{compute_node_addr}::ring/#{ring}.ring.gz ." 60 | cwd "/etc/swift" 61 | end 62 | } 63 | 64 | svcs.each { |x| 65 | service x do 66 | action [:enable, :start] 67 | end 68 | } 69 | end 70 | 71 | 72 | ### 73 | # let the monitoring tools know what services should be running on this node. 74 | node[:swift][:monitor] = {} 75 | node[:swift][:monitor][:svcs] = svcs 76 | node[:swift][:monitor][:ports] = {:object =>6000, :container =>6001, :account =>6002} 77 | node.save 78 | -------------------------------------------------------------------------------- /cookbooks/swift/resources/disk.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | =begin 20 | Ensure that a disk's partition table matches expectations. 21 | Sample use: 22 | 23 | swift_disk "/dev/sdb" do 24 | part( 25 | {[:type => "xfs", :size =>swift_disk::ONE_GIG*4 ], 26 | [:type => "xfs", :size =>swift_disk::remaining}) 27 | action :ensure_exists 28 | end 29 | 30 | =end 31 | 32 | actions :ensure_exists 33 | 34 | attribute :name, :kind_of => String 35 | attribute :cylinders, :kind_of => Integer 36 | attribute :size, :kind_of => Integer 37 | attribute :device, :kind_of => String 38 | attribute :geo, :kind_of => Hash 39 | attribute :part, :kind_of => Array 40 | attribute :status, :kind_of => Symbol 41 | 42 | 43 | -------------------------------------------------------------------------------- /cookbooks/swift/resources/ringfile.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | 20 | =begin 21 | A ring file describes the disks in a swift cluster. 22 | the utility used to manipulate it requires only changes to by applied 23 | 24 | Each disk needs to be described with the following: 25 | :ip - the IP address of the machine 26 | :port - the port the server on that machine is listening on 27 | :dev_name - the device's name 28 | :weight - a relative (to other disks) weight. determines how heavily used this disk will be 29 | :zone - the zone the disk is in 30 | 31 | When 'applied' this resource compares the current disk information in the ring file to that provided 32 | to it, and adds the missing disks 33 | 34 | Sample usage below. Note that disks_c is an array of hashes. 35 | 36 | swift_ringfile "container.builder" do 37 | disks disks_c 38 | action [:apply, :rebalance] 39 | end 40 | 41 | 42 | 43 | =end 44 | 45 | actions :apply, :rebalance 46 | attribute :disks 47 | attribute :partitions, :kind_of => Integer 48 | attribute :replicas, :kind_of => Integer 49 | attribute :min_part_hours, :kind_of => Integer 50 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/account-server-conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | [Default] 20 | #bind_ip = <%= @storage_net_ip %> 21 | bind_port = 6002 22 | 23 | log_facility = LOG_LOCAL0 24 | log_level = DEBUG 25 | log_name = swift-a 26 | log_requests = true 27 | setup_console_handler = true 28 | 29 | 30 | [pipeline:main] 31 | pipeline = account-server 32 | 33 | [app:account-server] 34 | use = egg:swift#account 35 | set log_level = DEBUG 36 | set log_requests = true 37 | 38 | 39 | [account-replicator] 40 | 41 | [account-auditor] 42 | 43 | [account-reaper] 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/auth-server.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | [auth-server] 20 | default_cluster_url = https://127.0.0.1:8080/v1 21 | user = swift 22 | cert_file = /etc/swift/cert.crt 23 | key_file = /etc/swift/cert.key 24 | super_admin_key = <%= @admin_key %> 25 | 26 | 27 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/container-server-conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | [DEFAULT] 20 | #bind_ip = <%= @storage_net_ip %> 21 | bind_port = 6001 22 | workers = 2 23 | 24 | log_facility = LOG_LOCAL0 25 | log_level = DEBUG 26 | log_name = swift-c 27 | log_requests = true 28 | setup_console_handler = true 29 | 30 | [pipeline:main] 31 | pipeline = container-server 32 | 33 | [app:container-server] 34 | use = egg:swift#container 35 | log_level = DEBUG 36 | 37 | [container-replicator] 38 | 39 | [container-updater] 40 | 41 | [container-auditor] 42 | 43 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/object-server-conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | [DEFAULT] 19 | #bind_ip = <%= @storage_net_ip %> 20 | bind_port = 6000 21 | workers = 2 22 | 23 | log_facility = LOG_LOCAL0 24 | log_level = DEBUG 25 | log_name = swift-o 26 | log_requests = true 27 | setup_console_handler = true 28 | 29 | 30 | [pipeline:main] 31 | pipeline = object-server 32 | 33 | [app:object-server] 34 | use = egg:swift#object 35 | set log_level = DEBUG 36 | set log_requests = true 37 | 38 | [object-replicator] 39 | 40 | [object-updater] 41 | 42 | [object-auditor] 43 | 44 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/proxy-server.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | [DEFAULT] 19 | cert_file = /etc/swift/cert.crt 20 | key_file = /etc/swift/cert.key 21 | bind_port = 8080 22 | workers = 1 23 | user = <%= @user %> 24 | 25 | log_facility = LOG_LOCAL0 26 | log_level = DEBUG 27 | log_name = swift-p 28 | log_requests = true 29 | setup_console_handler = true 30 | 31 | [pipeline:main] 32 | pipeline = healthcheck cache swauth proxy-server 33 | 34 | [app:proxy-server] 35 | use = egg:swift#proxy 36 | <% if @account_management == "true" %> 37 | allow_account_management = true 38 | <% end %> 39 | 40 | set log_name = proxy-server 41 | set log_facility = LOG_LOCAL0 42 | set log_level = DEBUG 43 | set access_log_name = proxy-server 44 | set access_log_facility = LOG_LOCAL0 45 | set access_log_level = INFO 46 | set log_requests = true 47 | 48 | [filter:swauth] 49 | use = egg:swift#swauth 50 | set default_swift_cluster = local#https://<%= @localip %>:8080/v1 51 | super_admin_key = <%= @admin_key %> 52 | log_level = DEBUG 53 | 54 | [filter:healthcheck] 55 | use = egg:swift#healthcheck 56 | 57 | [filter:cache] 58 | use = egg:swift#memcache 59 | memcache_servers = <%= @memcached_ips %> 60 | 61 | 62 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/rsyncd.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | uid = <%= @uid %> 19 | gid = <%= @group %> 20 | log file = /var/log/rsyncd.log 21 | pid file = /var/run/rsyncd.pid 22 | 23 | uid = swift 24 | gid = swift 25 | log file = /var/log/rsyncd.log 26 | pid file = /var/run/rsyncd.pid 27 | address = <%= @storage_net_ip %> 28 | 29 | [account] 30 | max connections = 2 31 | path = /srv/node/ 32 | read only = false 33 | lock file = /var/lock/swift/account.lock 34 | 35 | [container] 36 | max connections = 2 37 | path = /srv/node/ 38 | read only = false 39 | lock file = /var/lock/swift/container.lock 40 | 41 | [object] 42 | max connections = 2 43 | path = /srv/node/ 44 | read only = false 45 | lock file = /var/lock/swift/object.lock 46 | 47 | [ring] 48 | max connections =2 49 | path = /etc/swift 50 | read only = false 51 | lock file = /var/lock/swift/ring.lock 52 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/swift.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | [swift-hash] 20 | swift_hash_path_suffix = <%= @swift_cluster_hash %> 21 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/swift_nrpe.cfg.erb: -------------------------------------------------------------------------------- 1 | 2 | <% @svcs.each do |s| %> 3 | command[check_<%= s%>]=/usr/lib/nagios/plugins/check_procs -w 2:10 -c 1:100 -a "<%=s %>" 4 | <% end unless @svcs.nil? %> 5 | 6 | 7 | <% @swift_ports.each do |name,port| %> 8 | command[check_port_swift-<%= name %>]=/usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p <%= port %> 9 | <% end unless @swift_ports.nil? %> 10 | -------------------------------------------------------------------------------- /data_bags/crowbar/bc-default-swift.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "id": "bc-default-swift", 4 | "description": "The default proposal for swift", 5 | "attributes": { 6 | "swift": { 7 | "cluster_hash": "fa8bea159b55bd7e", 8 | "cluster_admin_pw": "swauth", 9 | "replicas": 1, 10 | "partitions": 18, 11 | "zones": 2, 12 | "min_part_hours": 1, 13 | "user": "swift", 14 | "group": "swift", 15 | "debug": true, 16 | "admin_ip_expr": "Chef::Recipe::Barclamp::Inventory.get_network_by_type(node, \"admin\").address", 17 | "storage_ip_expr": "Chef::Recipe::Barclamp::Inventory.get_network_by_type(node, \"storage\").address", 18 | "disk_enum_expr": "node[\"crowbar\"][\"disks\"]", 19 | "disk_test_expr": "v[\"usage\"] == 'Storage'", 20 | "disk_zone_assign_expr": "$SWIFT_DISK_CNT||=0; $SWIFT_DISK_CNT= $SWIFT_DISK_CNT+1 ;[ $SWIFT_DISK_CNT % node[:swift][:zones] , 99]" 21 | } 22 | }, 23 | "deployment": { 24 | "swift": { 25 | "crowbar-revision": 0, 26 | "elements": {}, 27 | "element_order": [ 28 | [ "swift-storage", "swift-ring-compute", "swift-proxy-acct", "swift-proxy" ] 29 | ], 30 | "config": { 31 | "environment": "swift-config-base", 32 | "mode": "full", 33 | "transitions": false, 34 | "transition_list": [] 35 | } 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /data_bags/crowbar/bc-default-swift.schema: -------------------------------------------------------------------------------- 1 | { 2 | "type": "map", 3 | "required": true, 4 | "mapping": { 5 | "id": { "type": "str", "required": true, "pattern": "/^bc-swift-|^bc-default-swift$/" }, 6 | "description": { "type": "str", "required": true }, 7 | "attributes": { 8 | "type": "map", 9 | "required": true, 10 | "mapping": { 11 | "swift": { 12 | "type": "map", 13 | "required": true, 14 | "mapping": { 15 | "cluster_hash": { "type": "str", "required": true }, 16 | "cluster_admin_pw": { "type": "str", "required": true }, 17 | "replicas": { "type": "int", "required": true }, 18 | "zones": { "type": "int", "required": true }, 19 | "min_part_hours": { "type": "int", "required": true }, 20 | "partitions": { "type": "int", "required": true }, 21 | "user": { "type": "str", "required": true }, 22 | "group": { "type": "str", "required": true }, 23 | "debug": { "type": "bool", "required": false}, 24 | "admin_ip_expr": { "type": "str", "required": true}, 25 | "storage_ip_expr": { "type": "str", "required": true}, 26 | "disk_enum_expr": { "type": "str", "required": true}, 27 | "disk_test_expr": { "type": "str", "required": true}, 28 | "disk_zone_assign_expr": { "type": "str", "required": false} 29 | } 30 | } 31 | } 32 | }, 33 | "deployment": { 34 | "type": "map", 35 | "required": true, 36 | "mapping": { 37 | "swift": { 38 | "type": "map", 39 | "required": true, 40 | "mapping": { 41 | "crowbar-revision": { "type": "int", "required": true }, 42 | "elements": { 43 | "type": "map", 44 | "required": true, 45 | "mapping": { 46 | = : { 47 | "type": "seq", 48 | "required": true, 49 | "sequence": [ { "type": "str" } ] 50 | } 51 | } 52 | }, 53 | "element_order": { 54 | "type": "seq", 55 | "required": true, 56 | "sequence": [ { 57 | "type": "seq", 58 | "sequence": [ { "type": "str" } ] 59 | } ] 60 | }, 61 | "config": { 62 | "type": "map", 63 | "required": true, 64 | "mapping": { 65 | "environment": { "type": "str", "required": true }, 66 | "mode": { "type": "str", "required": true }, 67 | "transitions": { "type": "bool", "required": true }, 68 | "transition_list": { 69 | "type": "seq", 70 | "required": true, 71 | "sequence": [ { "type": "str" } ] 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | * Overview 2 | 3 | Swift is part of Openstack, and provides a distributed blob storage. This barclamp installs swift. 4 | Swift includes the following components: 5 | - Proxy node- provides the API to the cluster, including authentication. 6 | - Storage nodes - provide storage for clsuter. 7 | 8 | * Roles 9 | The following node roles are definied in this cookbook: 10 | - Storage node - configures a node to be used as a storage node 11 | - Proxy node - configures a node to be a proxy. each proxy node will have a memcached server installed. all proxy nodes are updated with all the memcached severs' addresses (listening on the internal IP addresses) 12 | - Proxy node with account management - same as proxy node, but allows account_management. 13 | - ring-compute-node - computes and update the ring file (contains information about what partitions are stored where). The ring file distributed to other cluster members via rsync (rsyncd configured on this node, other nodes configured to sync periodically) 14 | 15 | 16 | * General comments 17 | 18 | The cookbook is designed to be useful in many different environments without requiring changes to the recpies themselvs. This is achieved by using attributes which provide expressions evaluated at recpie execution time. For example: 19 | 20 | default[:swift][:admin_ip_expr] = "node[:ipaddress]" 21 | default[:swift][:storage_ip_expr] = "node[:ipaddress]" 22 | 23 | 24 | Instructs the recipes to look at the ipaddress attribute set on the node for use for both the admin and storage networks. In environments where more copmlex address allocation is present, these expressions can be modified (even to function calls). 25 | 26 | 27 | as a more complex example: 28 | 29 | # expression to find a hash of possible disks to be used. 30 | default[:swift][:disk_enum_expr]= 'node[:block_device]' 31 | # expression accepting a k,v pair for evaluation. if expression returns true, then the disk will be used. 32 | # by default, use any sdX or hdX that is not the first one (which will hold the OS). 33 | default[:swift][:disk_test_expr]= 'k =~/sd[^a]/ or k=~/hd[^a]/' 34 | 35 | The first attribute provides a source for a list of possible disks to use. In this case, it's the ohai disk list. The second attribute is a test against the found disk - if the expression is true, the disk is ''claimed'' by swift (partitioned and formatted). The comment describes the sample expression. 36 | 37 | 38 | Look in the attributes\default.rb for the full set of expressions provided. 39 | Look in data_bags/crowbar/bc-default-swift.json for some additional examples 40 | 41 | -------------------------------------------------------------------------------- /roles/swift-proxy-acct.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | name "swift-proxy-acct" 20 | 21 | description < { "account_management" => "true" } 33 | 34 | -------------------------------------------------------------------------------- /roles/swift-proxy.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | name "swift-proxy" 20 | description "provides the proxy and authentication components to swift" 21 | run_list( 22 | "recipe[swift::default]", 23 | "recipe[swift::proxy]", 24 | "recipe[swift::monitor]" 25 | ) 26 | 27 | override_attributes "swift" => { "account_management" => "false" } 28 | 29 | -------------------------------------------------------------------------------- /roles/swift-ring-compute.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | name "swift-ring-compute" 20 | 21 | run_list( 22 | "recipe[swift::default]", 23 | "recipe[swift::ring-compute]" 24 | ) 25 | 26 | description "A swift role to compute the ring files for the cluster. Should be installed on a single node" 27 | -------------------------------------------------------------------------------- /roles/swift-storage.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2011, Dell 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # Author: andi abes 17 | # 18 | 19 | name "swift-storage" 20 | description "configures a swift storage node, including partitioning disks, formatting them as XFS" 21 | 22 | run_list( 23 | "recipe[swift::default]", 24 | "recipe[swift::storage]", 25 | "recipe[swift::monitor]" 26 | ) 27 | --------------------------------------------------------------------------------