├── Berksfile ├── templates └── default │ ├── singleregion-address.yaml.erb │ ├── multiregion-address.yaml.erb │ ├── opscenter_nginx_site.erb │ └── opscenterd.conf.erb ├── Gemfile ├── .gitignore ├── Thorfile ├── metadata.rb ├── LICENSE ├── recipes ├── default.rb ├── opscenter-server-shutdown.rb ├── install.rb ├── opscenter-agent.rb └── opscenter-server.rb ├── .kitchen.yml ├── attributes └── default.rb ├── Vagrantfile └── README.md /Berksfile: -------------------------------------------------------------------------------- 1 | site :opscode 2 | -------------------------------------------------------------------------------- /templates/default/singleregion-address.yaml.erb: -------------------------------------------------------------------------------- 1 | stomp_interface: "<%= @LEADEREC2PUBLICHOSTNAME %>" 2 | use_ssl: 1 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'berkshelf' 4 | gem 'test-kitchen', :group => :integration 5 | gem 'kitchen-vagrant', :group => :integration 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | Berksfile.lock 3 | *~ 4 | *# 5 | .#* 6 | \#*# 7 | .*.sw[a-z] 8 | *.un~ 9 | /cookbooks 10 | 11 | # Bundler 12 | Gemfile.lock 13 | bin/* 14 | .bundle/* 15 | 16 | .kitchen/ 17 | .kitchen.local.yml 18 | -------------------------------------------------------------------------------- /templates/default/multiregion-address.yaml.erb: -------------------------------------------------------------------------------- 1 | stomp_interface: "<%= @LEADEREC2PUBLICHOSTNAME %>" 2 | local_interface: "<%= node[:cloud][:public_ipv4] %>" 3 | agent_rpc_interface: "<%= node[:ipaddress] %>" 4 | agent_rpc_broadcast_address: "<%= node[:cloud][:public_ipv4] %>" 5 | use_ssl: 1 6 | -------------------------------------------------------------------------------- /Thorfile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'bundler' 4 | require 'bundler/setup' 5 | require 'berkshelf/thor' 6 | 7 | begin 8 | require 'kitchen/thor_tasks' 9 | Kitchen::ThorTasks.new 10 | rescue LoadError 11 | puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] 12 | end 13 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'cassandra-opscenter' 2 | maintainer "Medidata Solutions, Inc." 3 | maintainer_email "cookbooks@mdsol.com" 4 | license "Apache 2.0" 5 | description "Installs Opscenter for monitoring Cassandra" 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 7 | version "0.0.5" 8 | 9 | %w{ ubuntu debian redhat fedora centos scientific amazon }.each do |os| 10 | supports os 11 | end 12 | 13 | depends "python" 14 | depends "java" 15 | depends "nginx" 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Medidata Solutions Worldwide 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 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cassandra-opscenter 3 | # Recipe:: default 4 | # 5 | # Copyright 2013 Medidata Solutions Worldwide 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 | include_recipe "cassandra-opscenter::install" 21 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver_plugin: vagrant 3 | driver_config: 4 | require_chef_omnibus: true 5 | 6 | platforms: 7 | - name: ubuntu-12.04 8 | driver_config: 9 | box: opscode-ubuntu-12.04 10 | box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box 11 | - name: ubuntu-10.04 12 | driver_config: 13 | box: opscode-ubuntu-10.04 14 | box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_ubuntu-10.04_provisionerless.box 15 | - name: centos-6.4 16 | driver_config: 17 | box: opscode-centos-6.4 18 | box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_centos-6.4_provisionerless.box 19 | - name: centos-5.9 20 | driver_config: 21 | box: opscode-centos-5.9 22 | box_url: https://opscode-vm-bento.s3.amazonaws.com/vagrant/opscode_centos-5.9_provisionerless.box 23 | 24 | suites: 25 | - name: default 26 | run_list: [] 27 | attributes: {} 28 | -------------------------------------------------------------------------------- /templates/default/opscenter_nginx_site.erb: -------------------------------------------------------------------------------- 1 | # nginx site for opscenter - Managed by Chef - do not edit directly! 2 | 3 | # the size of the public hostname can be too large for the default size of 32; 4 | server_names_hash_bucket_size <%= node[:nginx][:server_names_hash_bucket_size] %>; 5 | 6 | server { 7 | listen 80 default; 8 | server_name <%= node[:ec2][:public_hostname] %>; 9 | access_log /var/log/nginx/opscenter.access.log; 10 | error_log /var/log/nginx/opscenter.error.log warn; 11 | 12 | # Allow access to the agent in the opscenter directory 13 | location /agent.tar.gz { root <%= node[:cassandra][:opscenter][:home] %>-<%= node[:cassandra][:opscenter][:version] %> ; } 14 | 15 | # Redirect all requests to http://<%= node[:ipaddress] %>:<%= node[:cassandra][:opscenter][:server_port] %>; 16 | location / { 17 | rewrite ^ http://<%= node[:ec2][:public_hostname] %>:<%= node[:cassandra][:opscenter][:server_port] %>$request_uri? permanent; 18 | } 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /templates/default/opscenterd.conf.erb: -------------------------------------------------------------------------------- 1 | # opscenterd.conf - Managed by Chef - do not edit directly! 2 | 3 | [webserver] 4 | port = <%= node[:cassandra][:opscenter][:server_port] %> 5 | interface = <%= node[:ipaddress] %> 6 | # The following settings can be used to enable ssl support for the opscenter 7 | # web application. Change these values to point to the ssl certificate and key 8 | # that you wish to use for your OpsCenter install, as well as the port you would like 9 | # to serve ssl traffic from. 10 | #ssl_keyfile = /var/lib/opscenter/ssl/opscenter.key 11 | #ssl_certfile = /var/lib/opscenter/ssl/opscenter.pem 12 | #ssl_port = 8443 13 | 14 | [logging] 15 | # level may be TRACE, DEBUG, INFO, WARN, or ERROR 16 | #level = INFO 17 | 18 | [authentication] 19 | # if this file does not exist, there will be no password protection. Use the 20 | # set_passwd.py tool (included with OpsCenter) to set passwords. This property will 21 | # default to /etc/opscenter/.passwd in packaged installations and ./passwds in 22 | # tarball installations. 23 | #passwd_file = 24 | -------------------------------------------------------------------------------- /recipes/opscenter-server-shutdown.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cassandra-opscenter 3 | # Recipe:: opscenter-server-shutdown 4 | # 5 | # Copyright 2013 Medidata Solutions Worldwide 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 | # We may lose the election one day. In which case we will stop running the Opscenter Server. 21 | # Metrics are kept in Cassandra itself so this is strangely safe. 22 | 23 | # Stop the server 24 | bash "Opscenter Server Shutdown" do 25 | code <<-EOH 26 | pkill -f start_opscenter.py 27 | EOH 28 | only_if "pgrep -f start_opscenter.py" 29 | end 30 | 31 | # Delete the link 32 | link node[:cassandra][:opscenter][:home] do 33 | action :delete 34 | end 35 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # External variables 3 | 4 | # The default is too small for a typical ec2 hostname - this needs to be set above 64 5 | override[:nginx][:server_names_hash_bucket_size] = 512 6 | 7 | ### 8 | # Cassandra variables 9 | 10 | # Multi region switch variable: in this cookbook the agent config is different depending on this variable. 11 | # We use the variable from the cassandra-priam cookbook, which this cookbook was written alongside. 12 | default[:cassandra][:priam_multiregion_enable] = nil 13 | 14 | ### 15 | # Opscenter variables 16 | 17 | # We will create this user on the leader-elected server. 18 | default[:cassandra][:opscenter][:user] = "opscenter" 19 | default[:cassandra][:opscenter][:group] = "opscenter" 20 | 21 | # A top level directory attribute is provided should you wish to install elsewhere. 22 | default[:cassandra][:opscenter][:parentdir] = "/opt" 23 | default[:cassandra][:opscenter][:home] = "#{node[:cassandra][:opscenter][:parentdir]}/opscenter" 24 | 25 | # What version to install, where to get it and a checksum to guarantee it is valid. 26 | default[:cassandra][:opscenter][:version] = "3.2.2" 27 | default[:cassandra][:opscenter][:src_url] = "http://downloads.datastax.com/community/opscenter-#{node['cassandra']['opscenter']['version']}-free.tar.gz" 28 | default[:cassandra][:opscenter][:checksum] = "568b9e8767a0ed1bc7f101f39cf400f63fbba4f7dceefafab19c608aaf386950" 29 | 30 | # We create fill in this attribute dynamically mid-chef-run on the host that installs the server and generates the package. 31 | default[:cassandra][:opscenter][:agent][:checksum] = nil 32 | 33 | # For agent distribution and proxying/redirect to the opscenter interface on the default http port 34 | default[:cassandra][:opscenter][:server_port] = "8888" 35 | -------------------------------------------------------------------------------- /recipes/install.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cassandra-opscenter 3 | # Recipe:: install 4 | # 5 | # Copyright 2013 Medidata Solutions Worldwide 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 | ## Simplistic leader election 21 | node.save 22 | peers = search(:node, "roles:#{node[:roles].first}" ) 23 | leader = peers.sort{|a,b| a.name <=> b.name}.first || node # the "or" covers the case where node is the first db 24 | 25 | # Some reporting on the election 26 | Chef::Log.info("cassandra-opscenter LeaderElection: #{node[:roles].first} Leader is : #{leader.name} #{leader.ec2.public_hostname} #{leader.ipaddress}") 27 | 28 | # Set some global vars to be used in the agent recipe 29 | $LEADERNAME = leader.name 30 | $LEADERIPADDRESS = leader.ipaddress 31 | $LEADEREC2PUBLICHOSTNAME = leader.ec2.public_hostname 32 | $LEADERAGENTCHECKSUM = leader.cassandra.opscenter.agent.checksum 33 | 34 | if (node.name == leader.name) 35 | # Leader installs the server - it is the Master 36 | include_recipe "cassandra-opscenter::opscenter-server" 37 | # Leader installs the agent too 38 | include_recipe "cassandra-opscenter::opscenter-agent" 39 | else 40 | # Followers install the agent 41 | include_recipe "cassandra-opscenter::opscenter-agent" 42 | # And shutdown previous instances of the server - saving memory, etc 43 | include_recipe "cassandra-opscenter::opscenter-server-shutdown" 44 | end 45 | 46 | -------------------------------------------------------------------------------- /recipes/opscenter-agent.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cassandra-opscenter 3 | # Recipe:: opscenter-agent 4 | # 5 | # Copyright 2013 Medidata Solutions Worldwide 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 | Chef::Log.info("Installing Opscenter Agent") 21 | 22 | # Required for IO reporting 23 | package "sysstat" 24 | 25 | # Required for opscenter agent connectivity 26 | package "libssl0.9.8" 27 | 28 | # Install java 29 | include_recipe "java" 30 | 31 | # Pick a package suffix based on the platform. 32 | case node[:platform] 33 | when "debian", "ubuntu" 34 | PACKAGESUFFIX = "deb" 35 | when "redhat", "centos", "fedora", "scientific", "amazon" 36 | PACKAGESUFFIX = "rpm" 37 | end 38 | 39 | # Download Agent from Leader - the leader may take a while to generate the agent.tar.gz at install time and make it available so we give it some retries to do it. 40 | Chef::Log.info("Downloading Agent from http://#{$LEADEREC2PUBLICHOSTNAME}/agent.tar.gz") 41 | remote_file "#{Chef::Config[:file_cache_path]}/#{$LEADEREC2PUBLICHOSTNAME}-opscenter-#{node[:cassandra][:opscenter][:version]}-agent.tar.gz" do 42 | source "http://#{$LEADEREC2PUBLICHOSTNAME}/agent.tar.gz" 43 | mode "0644" 44 | retries 10 45 | checksum $LEADERAGENTCHECKSUM 46 | notifies :run, "bash[Opscenter Agent Installation]", :immediately 47 | end 48 | 49 | # Install the Agent according to the Documentation - which we hope has been fixed. 50 | bash "Opscenter Agent Installation" do 51 | code <<-EOH 52 | cd /tmp/ && tar zxvf #{Chef::Config[:file_cache_path]}/#{$LEADEREC2PUBLICHOSTNAME}-opscenter-#{node[:cassandra][:opscenter][:version]}-agent.tar.gz && cd agent && ./bin/install_agent.sh opscenter-agent.#{PACKAGESUFFIX} #{$LEADEREC2PUBLICHOSTNAME} 53 | EOH 54 | not_if "dpkg -l opscenter-agent | grep #{node[:cassandra][:opscenter][:version]} && grep #{$LEADEREC2PUBLICHOSTNAME} /var/lib/opscenter-agent/conf/address.yaml" 55 | notifies :create, "template[/var/lib/opscenter-agent/conf/address.yaml]", :immediately 56 | notifies :restart, "service[opscenter-agent]", :immediately 57 | end 58 | 59 | # Opscenter Agent configuration - differs between single and multi region setups 60 | case node[:cassandra][:priam_multiregion_enable] 61 | when "true" 62 | template "/var/lib/opscenter-agent/conf/address.yaml" do 63 | variables :LEADEREC2PUBLICHOSTNAME => $LEADEREC2PUBLICHOSTNAME 64 | source "multiregion-address.yaml.erb" 65 | mode "0644" 66 | notifies :restart, "service[opscenter-agent]", :immediately 67 | end 68 | else 69 | template "/var/lib/opscenter-agent/conf/address.yaml" do 70 | variables :LEADEREC2PUBLICHOSTNAME => $LEADEREC2PUBLICHOSTNAME 71 | source "singleregion-address.yaml.erb" 72 | mode "0644" 73 | notifies :restart, "service[opscenter-agent]", :immediately 74 | end 75 | end 76 | 77 | # We call the opscenter-agent service resource so it must be specified somewhere. 78 | service "opscenter-agent" do 79 | action :start 80 | end 81 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | # All Vagrant configuration is done here. The most common configuration 6 | # options are documented and commented below. For a complete reference, 7 | # please see the online documentation at vagrantup.com. 8 | 9 | config.vm.hostname = "cassandra-opscenter-cookbook-berkshelf" 10 | 11 | # Every Vagrant virtual environment requires a box to build off of. 12 | config.vm.box = "Berkshelf-CentOS-6.3-x86_64-minimal" 13 | 14 | # The url from where the 'config.vm.box' box will be fetched if it 15 | # doesn't already exist on the user's system. 16 | config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box" 17 | 18 | # Assign this VM to a host-only network IP, allowing you to access it 19 | # via the IP. Host-only networks can talk to the host machine as well as 20 | # any other machines on the same network, but cannot be accessed (through this 21 | # network interface) by any external networks. 22 | config.vm.network :private_network, ip: "33.33.33.10" 23 | 24 | # Create a public network, which generally matched to bridged network. 25 | # Bridged networks make the machine appear as another physical device on 26 | # your network. 27 | 28 | # config.vm.network :public_network 29 | 30 | # Create a forwarded port mapping which allows access to a specific port 31 | # within the machine from a port on the host machine. In the example below, 32 | # accessing "localhost:8080" will access port 80 on the guest machine. 33 | 34 | # Share an additional folder to the guest VM. The first argument is 35 | # the path on the host to the actual folder. The second argument is 36 | # the path on the guest to mount the folder. And the optional third 37 | # argument is a set of non-required options. 38 | # config.vm.synced_folder "../data", "/vagrant_data" 39 | 40 | # Provider-specific configuration so you can fine-tune various 41 | # backing providers for Vagrant. These expose provider-specific options. 42 | # Example for VirtualBox: 43 | # 44 | # config.vm.provider :virtualbox do |vb| 45 | # # Don't boot with headless mode 46 | # vb.gui = true 47 | # 48 | # # Use VBoxManage to customize the VM. For example to change memory: 49 | # vb.customize ["modifyvm", :id, "--memory", "1024"] 50 | # end 51 | # 52 | # View the documentation for the provider you're using for more 53 | # information on available options. 54 | 55 | config.ssh.max_tries = 40 56 | config.ssh.timeout = 120 57 | 58 | # The path to the Berksfile to use with Vagrant Berkshelf 59 | # config.berkshelf.berksfile_path = "./Berksfile" 60 | 61 | # Enabling the Berkshelf plugin. To enable this globally, add this configuration 62 | # option to your ~/.vagrant.d/Vagrantfile file 63 | config.berkshelf.enabled = true 64 | 65 | # An array of symbols representing groups of cookbook described in the Vagrantfile 66 | # to exclusively install and copy to Vagrant's shelf. 67 | # config.berkshelf.only = [] 68 | 69 | # An array of symbols representing groups of cookbook described in the Vagrantfile 70 | # to skip installing and copying to Vagrant's shelf. 71 | # config.berkshelf.except = [] 72 | 73 | config.vm.provision :chef_solo do |chef| 74 | chef.json = { 75 | :mysql => { 76 | :server_root_password => 'rootpass', 77 | :server_debian_password => 'debpass', 78 | :server_repl_password => 'replpass' 79 | } 80 | } 81 | 82 | chef.run_list = [ 83 | "recipe[cassandra_opscenter_cookbook::default]" 84 | ] 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Description 2 | =========== 3 | 4 | This cookbook exists to make a deployment of a [Datastax Opscenter][1] cluster on a Cassandra cluster in Amazon EC2. 5 | 6 | [Datastax Opscenter][1] is a Monitoring and Management platform for Apache Cassandra - vital for visualising Cassandra's Status. 7 | 8 | [Datastax Opscenter][1] is deployed in a traditional many-clients just-one-server model, which conflicts slightly with Cassandra's masterless deployment model. 9 | 10 | To get around needing to know this/manage in an automated manner a leadership election takes place between nodes in the cluster, a leader is automatically assigned based on having the 'lowest' alphanumeric hostname, and that leader generates an agent package which is then distributed by http and verified by checksum. 11 | 12 | The good news is that Opscenter stores its data within Cassandra itself in its own Keyspace (2 replicas) so if a leader is terminated and a new leader arises from the ashes, no data should be lost. 13 | 14 | This cookbook supports two modes of deployment - multiregion OR non-multiregion, set through attributes. We default to non-multiregion aka singleregion. The way multiregion is expressed is in a difference in the agent's address configuration. Check the attributes for how to set this. 15 | 16 | This cookbook deploys the tarball version of opscenter because the packages provided tend to install as root, whereas this cookbook installs/runs opscenter as a unique system user. 17 | 18 | This cookbook holds certain assumptions to be true in order to easily manage its deployment: 19 | 20 | ##### A) You are deploying this on EC2 21 | ###### Reason: This cookbook was developed on/designed for EC2 deployment. If you want to support non-EC2 deployment please submit patches. 22 | 23 | ##### B) All members of the cluster share the same UNIQUE chef role and this is the first role in the list of roles. i.e. cassandra-cluster-one or product-production-casdb. 24 | ###### Reason: The unique role is used to search for other cluster members for shared information. If you want to extend/improve this please submit patches. 25 | 26 | ##### C) Connectivity between cluster members is suffiently open to allow for agent distribution and agent connectivity. Typically you should have a security group that allows relatively open access from that security group on port 80 for agent distrubtion. 27 | ###### Reason: Nothing will work without connectivity anyway. No node is an island. 28 | 29 | [1]: http://www.datastax.com/what-we-offer/products-services/datastax-opscenter 30 | 31 | Requirements 32 | ============ 33 | * Chef 10.16.4+ 34 | * Cassandra on each node. 35 | * Python cookbook to run the server. 36 | * Java cookbook to run the agent (on each node including the elected server). 37 | * Nginx for agent distribution on the elected server. 38 | 39 | ## Platform 40 | 41 | * Ubuntu 12.04+ [tested heavily] 42 | * Very Probably Debian 43 | * Probably RPM-based distros. [we do attempt to differentiate where necessary] 44 | 45 | Attributes 46 | ========== 47 | 48 | See the contents of attributes/default.rb where there are accurate comments and self-explanatory attribute names. 49 | 50 | Recipes 51 | ======= 52 | 53 | * `default.rb` : A dummy recipe pointing to install.rb 54 | * `install.rb` : Installs everything by calling the rest of the recipes in the right order. Includes a leadership election section for nominating the server. 55 | * `opscenter-server.rb` : Installs the server 56 | * `opscenter-agent.rb` : Installs the agent 57 | * `opscenter-server-shutdown.rb` : Shuts down the server when a new leader takes over - we wouldn't want to waste ram, right ? 58 | 59 | Usage 60 | ===== 61 | 62 | Include cassandra-opscenter in your runlist. 63 | 64 | Ensure you have enough connectivity between cluster members so that the agent can be distributed. (over the http port) 65 | 66 | Once this cookbook is deployed and the nodes converged, login to the cluster member with the lowest alphanumeric node.name on port 8888 67 | 68 | Click 'Use Existing Cluster' in the dialogue box. 69 | 70 | In the next dialogue box add the hostname you have connected to the cluster list and click 'Save Cluster'. 71 | 72 | #### multiregion requires the following attribute be set - this is from the cassandra-priam cookbook, but would work for non-priam deployments of opscenter and cassandra: 73 | 74 | ```JSON 75 | { 76 | "cassandra": { 77 | "priam_multiregion_enable": "true" 78 | } 79 | } 80 | ``` 81 | 82 | Development 83 | =========== 84 | 85 | See the [Github page][2] 86 | 87 | [2]: https://github.com/mdsol/cassandra_opscenter_cookbook 88 | 89 | Authors 90 | ======= 91 | 92 | * Author: Alex Trull 93 | * Author: Benton Roberts 94 | 95 | Copyright: 2013–2013 Medidata Solutions, Inc. 96 | -------------------------------------------------------------------------------- /recipes/opscenter-server.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cassandra-opscenter 3 | # Recipe:: opscenter-server 4 | # 5 | # Copyright 2013 Medidata Solutions Worldwide 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 | Chef::Log.info("Installing Opscenter Server") 21 | 22 | # Install python 23 | include_recipe "python" 24 | 25 | # Required for opscenter server connectivity 26 | package "libssl0.9.8" 27 | 28 | # Create a group for our opscenter user 29 | group "#{node[:cassandra][:opscenter][:group]}" 30 | 31 | # Create a user.. for our opscenter 32 | user "#{node[:cassandra][:opscenter][:user]}" do 33 | system true 34 | home node[:cassandra][:opscenter][:home] 35 | gid node[:cassandra][:opscenter][:group] 36 | shell "/bin/sh" 37 | end 38 | 39 | # download source 40 | src_url = node[:cassandra][:opscenter][:src_url] 41 | local_archive = "#{Chef::Config[:file_cache_path]}/#{::File.basename src_url}" 42 | remote_file local_archive do 43 | source src_url 44 | mode 0644 45 | not_if { File.exists? local_archive } 46 | checksum node[:cassandra][:opscenter][:checksum] 47 | end 48 | 49 | VERSION_DIR = "#{node[:cassandra][:opscenter][:home]}-#{node[:cassandra][:opscenter][:version]}" 50 | 51 | # create the target directory 52 | directory VERSION_DIR do 53 | owner "#{node[:cassandra][:opscenter][:user]}" 54 | group "#{node[:cassandra][:opscenter][:group]}" 55 | mode 0775 56 | recursive true 57 | end 58 | 59 | # unpack 60 | execute "unpack #{local_archive}" do 61 | command "tar --strip-components 1 --no-same-owner -xzf #{local_archive}" 62 | creates "#{VERSION_DIR}/bin/opscenter" 63 | user "#{node[:cassandra][:opscenter][:user]}" 64 | group "#{node[:cassandra][:opscenter][:group]}" 65 | cwd VERSION_DIR 66 | end 67 | 68 | # link the opscenter home to the version directory 69 | link node[:cassandra][:opscenter][:home] do 70 | to VERSION_DIR 71 | owner "#{node[:cassandra][:opscenter][:user]}" 72 | group "#{node[:cassandra][:opscenter][:group]}" 73 | end 74 | 75 | # opscenter server configuration 76 | template "#{node[:cassandra][:opscenter][:home]}/conf/opscenterd.conf" do 77 | source "opscenterd.conf.erb" 78 | owner "#{node[:cassandra][:opscenter][:user]}" 79 | group "#{node[:cassandra][:opscenter][:group]}" 80 | mode "0640" 81 | end 82 | 83 | # Start it up 84 | execute "Start Datastax OpsCenter" do 85 | command "#{node[:cassandra][:opscenter][:home]}/bin/opscenter" 86 | user "#{node[:cassandra][:opscenter][:user]}" 87 | group "#{node[:cassandra][:opscenter][:group]}" 88 | cwd node[:cassandra][:opscenter][:home] 89 | not_if "pgrep -f start_opscenter.py" 90 | notifies :run, "bash[Short Delay for Opscenter Server Startup]", :immediately 91 | end 92 | 93 | # We cause a delay after startup so that the agent.tar.gz can be created and permissions set afterwards 94 | bash "Short Delay for Opscenter Server Startup" do 95 | code <<-EOH 96 | sleep 15 97 | EOH 98 | action :nothing 99 | not_if { ::File.exists?("#{node[:cassandra][:opscenter][:home]}/agent.tar.gz") } 100 | end 101 | 102 | # Set everyone-readable permissions on agent.tar.gz so nginx can read it and other nodes can get it. 103 | file "#{node[:cassandra][:opscenter][:home]}/agent.tar.gz" do 104 | owner "#{node[:cassandra][:opscenter][:user]}" 105 | group "#{node[:cassandra][:opscenter][:group]}" 106 | mode 0644 107 | only_if { ::File.exists?("#{node[:cassandra][:opscenter][:home]}/agent.tar.gz") } 108 | notifies :create, "ruby_block[Save Opscenter Agent Checksum]", :immediately 109 | end 110 | 111 | # We create a hash in our node data and save the node data - the agent installation recipe will use this hash to verify the download. 112 | ruby_block "Save Opscenter Agent Checksum" do 113 | block do 114 | node.set[:cassandra][:opscenter][:agent][:checksum] = Digest::SHA256.file("#{node[:cassandra][:opscenter][:home]}/agent.tar.gz").hexdigest 115 | node.save 116 | end 117 | end 118 | 119 | # Install nginx - the cookbook would be better. 120 | package "nginx" do 121 | notifies :enable, "service[nginx]", :immediately 122 | end 123 | 124 | # Start nginx. 125 | service "nginx" do 126 | supports :restart => true, :reload => true 127 | action :enable 128 | end 129 | 130 | # Provide access to the agent.tar.gz on the leader via an nginx site. 131 | template "/etc/nginx/sites-available/opscenter" do 132 | source "opscenter_nginx_site.erb" 133 | mode 0644 134 | notifies :create, "link[/etc/nginx/sites-enabled/opscenter]", :immediately 135 | notifies :restart, "service[nginx]", :immediately 136 | end 137 | 138 | # Link the site to enabled access 139 | link "/etc/nginx/sites-enabled/opscenter" do 140 | to "/etc/nginx/sites-available/opscenter" 141 | end 142 | 143 | --------------------------------------------------------------------------------