From a547a5e4b273591ea5a12cc3f0092c71fccabc48 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 12:53:59 -0500 Subject: [PATCH 01/30] Add license badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 209b8c6..87b6d1e 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build Status](https://circleci.com/gh/cloudops/cookbook_cloudstack.svg?style=svg)](https://circleci.com/gh/cloudops/cookbook_cloudstack) [![Cookbook Version](https://img.shields.io/cookbook/v/cloudstack.svg)](https://supermarket.chef.io/cookbooks/cloudstack) +[![license](https://img.shields.io/github/license/cloudops/cookbook_cloudstack.svg)](https://github.com/cloudops/cookbook_cloudstack/blob/master/LICENSE) Install and configure [Apache Cloudstack](http://cloudstack.apache.org) using [Chef](http://www.chef.io/). A wrapper cookbook is prefered in order to Install Apache CloudStack properly, refer to [cloudstack_wrapper cookbook](https://github.com/cloudops/cookbook_cloudstack_wrapper) for example. From 6c1b63cfb1777f48b975907e0b7029b0200df58f Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 12:54:16 -0500 Subject: [PATCH 02/30] fix cookstyle --- metadata.rb | 6 +++--- recipes/management_server.rb | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/metadata.rb b/metadata.rb index 0623cfc..aeba1cb 100644 --- a/metadata.rb +++ b/metadata.rb @@ -9,10 +9,10 @@ source_url 'https://github.com/cloudops/cookbook_cloudstack' issues_url 'https://github.com/cloudops/cookbook_cloudstack/issues' -depends 'yum' , '> 3.0' -depends 'apt' , '> 2.0' +depends 'yum', '> 3.0' +depends 'apt', '> 2.0' depends 'mysql', '~> 8.0' -depends 'sudo' , '>= 2.6.0' +depends 'sudo', '>= 2.6.0' supports 'centos' supports 'redhat' diff --git a/recipes/management_server.rb b/recipes/management_server.rb index 5f1dfef..2a23875 100644 --- a/recipes/management_server.rb +++ b/recipes/management_server.rb @@ -36,4 +36,3 @@ end include_recipe 'cloudstack::vhd-util' - From 8f1a868e62f4627d09972eb75649f63afb995c1b Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 12:58:25 -0500 Subject: [PATCH 03/30] Fix markdown lint and formatting --- CHANGELOG.md | 143 +++++++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a4705d..ad375af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,134 +1,133 @@ -cloudstack CHANGELOG -==================== +# cloudstack CHANGELOG -This file is used to list changes made in each version of the co-cloudstack cookbook. +This file is used to list changes made in each version of the cloudstack cookbook. + +## 6.0.1 -6.0.1 ------ - khos2ow - Add missing SystemVM URLs for CloudStack 4.10 -6.0.0 ------ +## 6.0.0 + - pdion891 - Fix Chef14 issues on CentOS 7 for cloudstack_setup_database ressource. - - Added circle-ci recipe for automated CI. - - Remove management of sudoers file, pkgs are taking care of it. +- pdion891 - Added circle-ci recipe for automated CI. +- pdion891 - Remove management of sudoers file, pkgs are taking care of it. + +## 5.0.0 -5.0.0 ------ - pdion891 - update default version to 4.11. - khos2ow - fixed cookstyle and foodcritic issues. -4.1.2 ------ +## 4.1.2 + - khos2ow - add default metadata expire to cloudstack repo -4.1.1 ------ +## 4.1.1 + - khos2ow - add server-id for mysql -4.1.0 ------ +## 4.1.0 + - khos2ow - add support for enabling/disabling cloudstack repo -4.0.8 ------ -- put mysql password in single-quotes, otherwise some hardened passwords are not interpreted correctly and logins fail. +## 4.0.8 + +- pdion891 - put mysql password in single-quotes, otherwise some hardened passwords are not interpreted correctly and logins fail. + +## 4.0.7 -4.0.7 ------ - pdion891 - add support for CentOS 7 for ACS 4.10 with JDK8 -4.0.5 ------ +## 4.0.5 + - pdion891 - add repo for mysql-connector-python -4.0.4 ------ +## 4.0.4 + - pdion891 - update apt repo issue for missing pkg signature. - - fix warning for chef 13. +- pdion891 - fix warning for chef 13. + +## 4.0.1 -4.0.1 ------ - pdion891 - update release to 4.8 by default -4.0.0 ------ +## 4.0.0 + - pdion891 - integration to berkshelf and vagrant. - - update for new acs 4.6 release. +- pdion891 - update for new acs 4.6 release. + +## 3.1.1 -3.1.1 ------ - pdion891 - POST for login authentication use to generate admin api_keys - - update systemvm url for acs 4.5 +- pdion891 - update systemvm url for acs 4.5 + +## 3.1.0 -3.1.0 ------ - pdion891 - support cookbook mysql6 -3.0.10 ------- +## 3.0.10 + - pdion891 - fix port_open: localhost-> 127.0.0.1 -3.0.9 ------ +## 3.0.9 + - pdion891 - fix sudoers. -3.0.8 ------ +## 3.0.8 + - pdion891 - update date in header. - - readme typos +- pdion891 - readme typos + +## 3.0.7 -3.0.7 ------ - pdion891 - rename ``hypervisor_tpl`` by ``systemvm`` -3.0.6 ------ +## 3.0.6 + - pdion891 - update 4.4.1 systemplate urls -3.0.5 ------ +## 3.0.5 + - pdion891 - fix systemvmtemplate url selection -3.0.4 ------ +## 3.0.4 + - pdion891 - api_key: major rewrite part1. -3.0.3 ------ +## 3.0.3 + - pdion891 - api_key: add existing keys validation to fix admin password change. -3.0.2 ------ +## 3.0.2 + - pdion891 - Add eventlog to rabbitmq config template -3.0.0 ------ +## 3.0.0 + - pdion891 - Complete rewrite of co-cloudstack as cloudstack using Chef LWRP - pdion891 - Rename cookbook from co-cloudstack to cloudstack. -2.0.3 ------ +## 2.0.3 + - pdion891 - Add mysql-conf to configure mysql-server tunings required by CloudStack. -2.0.2 ------ +## 2.0.2 + - pdion891 - change way of generating APIkeys by querying CloudStack API instead of enabling integration api port. -2.0.0 ------ +## 2.0.0 + - pdion891 - add support for CS 4.3 -1.0.0 ------ +## 1.0.0 + - pdion891 - add vhd-util recipe -- Update license headers -- Update dependencies for opscode cookbooks +- pdion891 - Update license headers +- pdion891 - Update dependencies for opscode cookbooks + +## 0.1.2 -0.1.2 ------ - pdion891 - remove use of databag and use attributes instead. -0.1.0 ------ +## 0.1.0 + - pdion891 - Initial release of co-cloudstack From 3c2d9fd6f0e5f771dfb97034f0ca3bf554966e24 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 13:57:28 -0500 Subject: [PATCH 04/30] Convert global_settings to new custom resource format --- libraries/global_setting.rb | 44 ----------------------- providers/global_setting.rb | 72 ------------------------------------- resources/global_setting.rb | 61 +++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 123 deletions(-) delete mode 100644 libraries/global_setting.rb delete mode 100644 providers/global_setting.rb diff --git a/libraries/global_setting.rb b/libraries/global_setting.rb deleted file mode 100644 index 596f0aa..0000000 --- a/libraries/global_setting.rb +++ /dev/null @@ -1,44 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Library:: global_setting -# Author:: Pierre-Luc Dion -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -module Cloudstack - module GlobalSetting - # Support whyrun - def whyrun_supported? - false - end - - def load_current_value(name) - require 'cloudstack_ruby_client' - # get CloudStack current value of the Global Setting - client = CloudstackRubyClient::Client.new('http://localhost:8080/client/api/', @current_resource.admin_apikey, @current_resource.admin_secretkey, false) - client.list_configurations(name: name)['configuration'].first['value'] - end - - def update_setting(name, value) - require 'cloudstack_ruby_client' - client = CloudstackRubyClient::Client.new('http://localhost:8080/client/api/', @current_resource.admin_apikey, @current_resource.admin_secretkey, false) - client.update_configuration( - name: name, - value: value - ) - end - end -end diff --git a/providers/global_setting.rb b/providers/global_setting.rb deleted file mode 100644 index 78f1e64..0000000 --- a/providers/global_setting.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Provider:: global_setting -# Author:: Pierre-Luc Dion () -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Configure Global Settings -############################################################################### - -# require 'cloudstack_ruby_client' -require 'json' -include Cloudstack::Helper -include Cloudstack::GlobalSetting - -use_inline_resources if defined?(:use_inline_resources) # ~FC113 - -######### -# ACTIONS -######### -action :update do - unless @current_resource.admin_apikey.nil? - unless @current_resource.exists - converge_by("Update Global Setting: #{@current_resource.name} to #{@current_resource.value}") do - # test_connection?(@current_resource.admin_apikey, @current_resource.admin_secretkey) - update_setting(@current_resource.name, @current_resource.value) - end - end - end -end - -def load_current_resource - require 'cloudstack_ruby_client' - @current_resource = Chef::Resource::CloudstackGlobalSetting.new(@new_resource.name) - @current_resource.name(@new_resource.name) - if $admin_apikey.nil? - @current_resource.admin_apikey(@new_resource.admin_apikey) - @current_resource.admin_secretkey(@new_resource.admin_secretkey) - else # if it's the first run on the server $admin_apikey will not be empty - @current_resource.admin_apikey($admin_apikey) - @current_resource.admin_secretkey($admin_secretkey) - end - @current_resource.value(@new_resource.value) - - if cloudstack_is_running? - if @current_resource.admin_apikey.nil? - Chef::Log.error 'admin_apikey empty, cannot update Global Settings' - else - current_value = load_current_value(@current_resource.name) - if current_value.nil? - Chef::Log.error "Global Setting: #{@current_resource.name} not found" - elsif @current_resource.value == current_value - @current_resource.exists = true - else - @current_resource.exists = false - end - end - else - Chef::Log.error 'CloudStack not running, cannot update Global Settings.' - end -end diff --git a/resources/global_setting.rb b/resources/global_setting.rb index 9d3780c..25171b5 100644 --- a/resources/global_setting.rb +++ b/resources/global_setting.rb @@ -19,13 +19,60 @@ # Configure Global Settings ############################################################################### -actions :update - default_action :update -attribute :name, name_attribute: true, kind_of: String -attribute :value, kind_of: String -attribute :admin_apikey, kind_of: String -attribute :admin_secretkey, kind_of: String +property :name, String, name_property: true +property :value, String +property :admin_apikey, String +property :admin_secretkey, String + +actions :update do + unless new_resource.admin_apikey.nil? + unless current_value_exists? + converge_by("Update Global Setting: #{new_resource.name} to #{new_resource.value}") do + # test_connection?(new_resource.admin_apikey, new_resource.admin_secretkey) + update_setting(new_resource.name, new_resource.value) + end + end + end +end + +action_class do + require 'json' + require 'cloudstack_ruby_client' + include Cloudstack::Helper + include Cloudstack::Database + + def load_current_value(name) + # get CloudStack current value of the Global Setting + client = CloudstackRubyClient::Client.new('http://localhost:8080/client/api/', new_resource.admin_apikey, new_resource.admin_secretkey, false) + client.list_configurations(name: name)['configuration'].first['value'] + end + + def update_setting(name, value) + client = CloudstackRubyClient::Client.new('http://localhost:8080/client/api/', new_resource.admin_apikey, new_resource.admin_secretkey, false) + client.update_configuration( + name: name, + value: value + ) + end -attr_accessor :exists + def current_value_exists + if cloudstack_is_running? + if new_resource.admin_apikey.nil? || new_resource.admin_secretkey.nil? + Chef::Log.error 'admin_apikey empty, cannot update Global Settings' + else + current_value = load_current_value(new_resource.name) + if current_value.nil? + Chef::Log.error "Global Setting: #{new_resource.name} not found" + elsif new_resource.value == current_value + true + else + false + end + end + else + Chef::Log.error 'CloudStack not running, cannot update Global Settings.' + end + end +end From 6aaca713be7c712cf4755ec5bee0b7e5d5c44b7c Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 14:05:24 -0500 Subject: [PATCH 05/30] fix cookstyle --- resources/global_setting.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/global_setting.rb b/resources/global_setting.rb index 25171b5..e3014fc 100644 --- a/resources/global_setting.rb +++ b/resources/global_setting.rb @@ -65,10 +65,8 @@ def current_value_exists current_value = load_current_value(new_resource.name) if current_value.nil? Chef::Log.error "Global Setting: #{new_resource.name} not found" - elsif new_resource.value == current_value - true else - false + new_resource.value == current_value end end else From 9d0a4c22fe0aa93793d1fbd303653a19002097d0 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 14:20:16 -0500 Subject: [PATCH 06/30] Convert api_keys to new custom resource format --- libraries/api_keys.rb | 180 ------------------------------------ providers/api_keys.rb | 81 ---------------- resources/api_keys.rb | 208 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 199 insertions(+), 270 deletions(-) delete mode 100644 libraries/api_keys.rb delete mode 100644 providers/api_keys.rb diff --git a/libraries/api_keys.rb b/libraries/api_keys.rb deleted file mode 100644 index 40d6575..0000000 --- a/libraries/api_keys.rb +++ /dev/null @@ -1,180 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Library:: keys -# Author:: Pierre-Luc Dion -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -# -# methods related to CloudStack API keys. -# -# -module Cloudstack - module ApiKeys - def create_admin_apikeys - # 1. make sure cloudstack is running - # 2. get admin apikeys - # 2.1 does admin keys defines in attributes? - # 2.2 does admin keys found in Chef environment? - # 2.3 does admin keys are already generated in cloudstack? - # 3. if none of the above generate new admin api keys - ################################################################## - if cloudstack_api_is_running? - # bypass the section if CloudStack is not running. - if @current_resource.admin_apikey || @current_resource.admin_secretkey - # if keys attributes are empty search in Chef environment for other node having API-KEYS. - if Chef::Config[:solo] - Chef::Log.warn('This recipe uses search. Chef Solo does not support search.') - other_nodes = [] - else - other_nodes = search(:node, "chef_environment:#{node.chef_environment} AND cloudstack_admin_api_key:* NOT name:#{node.name}") - end - if other_nodes.empty? - admin_apikeys_from_cloudstack - else - @current_resource.admin_apikey(other_nodes.first['cloudstack']['admin']['api_key']) - @current_resource.admin_secretkey(other_nodes.first['cloudstack']['admin']['secret_key']) - if keys_valid? - # API-KEYS from other nodes are valids, so updating current node attributes. - # @current_resource.exists = true - Chef::Log.info "api keys: found valid keys from #{other_nodes.first.name} in the Chef environment: #{node.chef_environment}." - Chef::Log.info 'api keys: updating node attributes' - end - end - elsif keys_valid? - # test API-KEYS on cloudstack, if they work, skip the section. - @current_resource.exists = true - Chef::Log.info 'api keys: are valid, nothing to do.' - else - admin_apikeys_from_cloudstack - end - else - Chef::Log.error 'CloudStack not running, cannot generate API keys.' - end - end - - def admin_apikeys_from_cloudstack - # look if apikeys already exist - # otherwise generate them - if @current_resource.username == 'admin' - admin_keys = retrieve_admin_keys(@current_resource.url, @current_resource.password) - if admin_keys[:api_key].nil? - converge_by('Creating api keys for admin') do - admin_keys = generate_admin_keys(@current_resource.url, @current_resource.password) - Chef::Log.info 'admin api keys: Generate new' - end - else - Chef::Log.info 'admin api keys: use existing in CloudStack' - end - # puts admin_keys - node.normal['cloudstack']['admin']['api_key'] = admin_keys[:api_key] - node.normal['cloudstack']['admin']['secret_key'] = admin_keys[:secret_key] - node.save unless Chef::Config[:solo] - $admin_apikey = admin_keys[:api_key] - $admin_secretkey = admin_keys[:secret_key] - Chef::Log.info "$admin_apikey = #{$admin_apikey}" - else - Chef::Log.error 'Account not admin' - end - end - - def generate_admin_keys(url = 'http://localhost:8080/client/api', password = 'password') - login_params = { command: 'login', username: 'admin', password: password, response: 'json' } - # create sessionkey and cookie of the api session initiated with username and password - uri = URI(url) - uri.query = URI.encode_www_form(login_params) - http = Net::HTTP.new(uri.hostname, uri.port) - res = http.post(uri.request_uri, '') # POST enforced since ACS 4.6 - get_keys_params = { - sessionkey: JSON.parse(res.body)['loginresponse']['sessionkey'], - command: 'registerUserKeys', - response: 'json', - id: '2', - } - - # use sessionkey + cookie to generate admin API and SECRET keys. - uri2 = URI(url) - uri2.query = URI.encode_www_form(get_keys_params) - sleep(2) # add some delay to have the session working - http_cookie = res.response['set-cookie'].split('; ')[0] - http_headers = { 'Cookie': http_cookie } - query_for_keys = http.get(uri2.request_uri, http_headers) - - if query_for_keys.code == '200' - keys = { - api_key: JSON.parse(query_for_keys.body)['registeruserkeysresponse']['userkeys']['apikey'], - secret_key: JSON.parse(query_for_keys.body)['registeruserkeysresponse']['userkeys']['secretkey'], - } - else - Chef::Log.info "Error creating keys errorcode: #{query_for_keys.code}" - end - keys - end - - def keys_valid? - # Test if current defined keys from Chef are valid - # - if @current_resource.admin_apikey || @current_resource.admin_secretkey - # return false if one key is empty - require 'cloudstack_ruby_client' - begin - client = CloudstackRubyClient::Client.new(@current_resource.url, @current_resource.admin_apikey, @current_resource.admin_secretkey, @current_resource.ssl) - list_apis = client.list_apis - rescue - false - end - if list_apis.nil? - false - else - true - end - else - false - end - end - - def retrieve_admin_keys(url = 'http://localhost:8080/client/api', password = 'password') - login_params = { command: 'login', username: 'admin', password: password, response: 'json' } - # create sessionkey and cookie of the api session initiated with username and password - uri = URI(url) - uri.query = URI.encode_www_form(login_params) - http = Net::HTTP.new(uri.hostname, uri.port) - res = http.post(uri.request_uri, '') # POST enforced since ACS 4.6 - get_keys_params = { - sessionkey: JSON.parse(res.body)['loginresponse']['sessionkey'], - command: 'listUsers', - response: 'json', - id: '2', - } - # use sessionkey + cookie to generate admin API and SECRET keys. - uri2 = URI(url) - uri2.query = URI.encode_www_form(get_keys_params) - sleep(2) # add some delay to have the session working - http_cookie = res.response['set-cookie'].split('; ')[0] - http_headers = { 'Cookie': http_cookie } - users = http.get(uri2.request_uri, http_headers) - if users.code == '200' - keys = { - api_key: JSON.parse(users.body)['listusersresponse']['user'].first['apikey'], - secret_key: JSON.parse(users.body)['listusersresponse']['user'].first['secretkey'], - } - else - Chef::Log.info "Error creating keys errorcode: #{users.code}" - end - keys - end - end -end diff --git a/providers/api_keys.rb b/providers/api_keys.rb deleted file mode 100644 index 5ff8e80..0000000 --- a/providers/api_keys.rb +++ /dev/null @@ -1,81 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Provider:: api_keys -# Author:: Pierre-Luc Dion () -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -# Generate api keys for specified CloudStack user. -# currently work for admin account. - -require 'uri' -require 'net/http' -require 'json' - -include Cloudstack::Helper -include Cloudstack::ApiKeys - -# Support whyrun -def whyrun_supported? - true -end - -use_inline_resources if defined?(:use_inline_resources) # ~FC113 - -######### -# ACTIONS -######### - -action :create do - wait_count = 0 - until cloudstack_api_is_running? || wait_count == 5 - cloudstack_api_is_running? - sleep(5) - wait_count += 1 - Chef::Log.info 'Waiting CloudStack to start' if wait_count == 1 - end - - create_admin_apikeys -end - -action :reset do - # force generate new API keys - # load_current_resource - if cloudstack_is_running? - if @current_resource.username == 'admin' - converge_by('Reseting admin api keys') do - admin_keys = generate_admin_keys(@current_resource.url, @current_resource.password) - Chef::Log.info 'admin api keys: Generate new' - node.normal['cloudstack']['admin']['api_key'] = admin_keys[:api_key] - node.normal['cloudstack']['admin']['secret_key'] = admin_keys[:secret_key] - node.save unless Chef::Config[:solo] - $admin_apikey = admin_keys[:api_key] - $admin_secretkey = admin_keys[:secret_key] - end - end - else - Chef::Log.error 'CloudStack not running, cannot generate API keys.' - end -end - -def load_current_resource - @current_resource = Chef::Resource::CloudstackApiKeys.new(@new_resource.name) - @current_resource.username(@new_resource.name) - @current_resource.password(@new_resource.password) - @current_resource.url(@new_resource.url) - @current_resource.admin_apikey(@new_resource.admin_apikey) - @current_resource.admin_secretkey(@new_resource.admin_secretkey) - @current_resource.ssl(@new_resource.ssl) -end diff --git a/resources/api_keys.rb b/resources/api_keys.rb index 188d00e..b0ef546 100644 --- a/resources/api_keys.rb +++ b/resources/api_keys.rb @@ -17,15 +17,205 @@ # limitations under the License. # -actions :create, :reset - default_action :create -attribute :username, name_attribute: true, kind_of: String -attribute :url, kind_of: String, default: 'http://localhost:8080/client/api' -attribute :password, kind_of: String, default: 'password' -attribute :admin_apikey, kind_of: String -attribute :admin_secretkey, kind_of: String -attribute :ssl, equal_to: [true, false, 'true', 'false'], default: false +property :username, String, name_property: true +property :url, String, default: 'http://localhost:8080/client/api' +property :password, String, default: 'password' +property :admin_apikey, String +property :admin_secretkey, String +property :ssl, equal_to: [true, false, 'true', 'false'], default: false + +actions :create do + wait_count = 0 + until cloudstack_api_is_running? || wait_count == 5 + cloudstack_api_is_running? + sleep(5) + wait_count += 1 + Chef::Log.info 'Waiting CloudStack to start' if wait_count == 1 + end + + if cloudstack_api_is_running? + create_admin_apikeys + else + Chef::Log.error 'CloudStack not running, cannot generate API keys.' + end +end + +actions :reset do + # force generate new API keys + # load_current_resource + if cloudstack_is_running? + if new_resource.username == 'admin' + converge_by('Reseting admin api keys') do + admin_keys = generate_admin_keys(new_resource.url, new_resource.password) + Chef::Log.info 'admin api keys: Generate new' + node.normal['cloudstack']['admin']['api_key'] = admin_keys[:api_key] + node.normal['cloudstack']['admin']['secret_key'] = admin_keys[:secret_key] + node.save unless Chef::Config[:solo] + new_resource.admin_apikey = admin_keys[:api_key] + new_resource.admin_secretkey = admin_keys[:secret_key] + end + end + else + Chef::Log.error 'CloudStack not running, cannot generate API keys.' + end +end + +action_class do + require 'uri' + require 'net/http' + require 'json' + + include Cloudstack::Helper + include Cloudstack::ApiKeys + + def create_admin_apikeys + # 1. make sure cloudstack is running + # 2. get admin apikeys + # 2.1 does admin keys defines in attributes? + # 2.2 does admin keys found in Chef environment? + # 2.3 does admin keys are already generated in cloudstack? + # 3. if none of the above generate new admin api keys + ################################################################## + # bypass the section if CloudStack is not running. + if new_resource.admin_apikey || new_resource.admin_secretkey + # if keys attributes are empty search in Chef environment for other node having API-KEYS. + if Chef::Config[:solo] + Chef::Log.warn('This recipe uses search. Chef Solo does not support search.') + other_nodes = [] + else + other_nodes = search(:node, "chef_environment:#{node.chef_environment} AND cloudstack_admin_api_key:* NOT name:#{node.name}") + end + if other_nodes.empty? + admin_apikeys_from_cloudstack + else + new_resource.admin_apikey(other_nodes.first['cloudstack']['admin']['api_key']) + new_resource.admin_secretkey(other_nodes.first['cloudstack']['admin']['secret_key']) + if keys_valid? + # API-KEYS from other nodes are valids, so updating current node attributes. + # new_resource.exists = true + Chef::Log.info "api keys: found valid keys from #{other_nodes.first.name} in the Chef environment: #{node.chef_environment}." + Chef::Log.info 'api keys: updating node attributes' + end + end + elsif keys_valid? + # test API-KEYS on cloudstack, if they work, skip the section. + new_resource.exists = true + Chef::Log.info 'api keys: are valid, nothing to do.' + else + admin_apikeys_from_cloudstack + end + end + + def admin_apikeys_from_cloudstack + # look if apikeys already exist + # otherwise generate them + if new_resource.username == 'admin' + admin_keys = retrieve_admin_keys(new_resource.url, new_resource.password) + if admin_keys[:api_key].nil? + converge_by('Creating api keys for admin') do + admin_keys = generate_admin_keys(new_resource.url, new_resource.password) + Chef::Log.info 'admin api keys: Generate new' + end + else + Chef::Log.info 'admin api keys: use existing in CloudStack' + end + # puts admin_keys + node.normal['cloudstack']['admin']['api_key'] = admin_keys[:api_key] + node.normal['cloudstack']['admin']['secret_key'] = admin_keys[:secret_key] + node.save unless Chef::Config[:solo] + new_resource.admin_apikey = admin_keys[:api_key] + new_resource.admin_secretkey = admin_keys[:secret_key] + Chef::Log.info "$admin_apikey = #{new_resource.admin_apikey}" + else + Chef::Log.error 'Account not admin' + end + end + + def generate_admin_keys(url = 'http://localhost:8080/client/api', password = 'password') + login_params = { command: 'login', username: 'admin', password: password, response: 'json' } + # create sessionkey and cookie of the api session initiated with username and password + uri = URI(url) + uri.query = URI.encode_www_form(login_params) + http = Net::HTTP.new(uri.hostname, uri.port) + res = http.post(uri.request_uri, '') # POST enforced since ACS 4.6 + get_keys_params = { + sessionkey: JSON.parse(res.body)['loginresponse']['sessionkey'], + command: 'registerUserKeys', + response: 'json', + id: '2', + } + + # use sessionkey + cookie to generate admin API and SECRET keys. + uri2 = URI(url) + uri2.query = URI.encode_www_form(get_keys_params) + sleep(2) # add some delay to have the session working + http_cookie = res.response['set-cookie'].split('; ')[0] + http_headers = { 'Cookie': http_cookie } + query_for_keys = http.get(uri2.request_uri, http_headers) + + if query_for_keys.code == '200' + keys = { + api_key: JSON.parse(query_for_keys.body)['registeruserkeysresponse']['userkeys']['apikey'], + secret_key: JSON.parse(query_for_keys.body)['registeruserkeysresponse']['userkeys']['secretkey'], + } + else + Chef::Log.info "Error creating keys errorcode: #{query_for_keys.code}" + end + keys + end + + def keys_valid? + # Test if current defined keys from Chef are valid + # + if new_resource.admin_apikey || new_resource.admin_secretkey + # return false if one key is empty + require 'cloudstack_ruby_client' + begin + client = CloudstackRubyClient::Client.new(new_resource.url, new_resource.admin_apikey, new_resource.admin_secretkey, new_resource.ssl) + list_apis = client.list_apis + rescue + false + end + if list_apis.nil? + false + else + true + end + else + false + end + end -attr_accessor :exists + def retrieve_admin_keys(url = 'http://localhost:8080/client/api', password = 'password') + login_params = { command: 'login', username: 'admin', password: password, response: 'json' } + # create sessionkey and cookie of the api session initiated with username and password + uri = URI(url) + uri.query = URI.encode_www_form(login_params) + http = Net::HTTP.new(uri.hostname, uri.port) + res = http.post(uri.request_uri, '') # POST enforced since ACS 4.6 + get_keys_params = { + sessionkey: JSON.parse(res.body)['loginresponse']['sessionkey'], + command: 'listUsers', + response: 'json', + id: '2', + } + # use sessionkey + cookie to generate admin API and SECRET keys. + uri2 = URI(url) + uri2.query = URI.encode_www_form(get_keys_params) + sleep(2) # add some delay to have the session working + http_cookie = res.response['set-cookie'].split('; ')[0] + http_headers = { 'Cookie': http_cookie } + users = http.get(uri2.request_uri, http_headers) + if users.code == '200' + keys = { + api_key: JSON.parse(users.body)['listusersresponse']['user'].first['apikey'], + secret_key: JSON.parse(users.body)['listusersresponse']['user'].first['secretkey'], + } + else + Chef::Log.info "Error creating keys errorcode: #{users.code}" + end + keys + end +end From df5b9cff28b2ccb660f3112b392ce1e80cdd301e Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 14:39:53 -0500 Subject: [PATCH 07/30] Fix server spec test --- resources/api_keys.rb | 1 - resources/global_setting.rb | 2 -- spec/recipes/default_spec.rb | 25 ++++--------------------- spec/spec_helper.rb | 24 +----------------------- 4 files changed, 5 insertions(+), 47 deletions(-) diff --git a/resources/api_keys.rb b/resources/api_keys.rb index b0ef546..c68dc08 100644 --- a/resources/api_keys.rb +++ b/resources/api_keys.rb @@ -68,7 +68,6 @@ require 'json' include Cloudstack::Helper - include Cloudstack::ApiKeys def create_admin_apikeys # 1. make sure cloudstack is running diff --git a/resources/global_setting.rb b/resources/global_setting.rb index e3014fc..0113387 100644 --- a/resources/global_setting.rb +++ b/resources/global_setting.rb @@ -39,9 +39,7 @@ action_class do require 'json' - require 'cloudstack_ruby_client' include Cloudstack::Helper - include Cloudstack::Database def load_current_value(name) # get CloudStack current value of the Global Setting diff --git a/spec/recipes/default_spec.rb b/spec/recipes/default_spec.rb index e2bcf30..1ffa217 100644 --- a/spec/recipes/default_spec.rb +++ b/spec/recipes/default_spec.rb @@ -1,27 +1,10 @@ -require_relative '../spec_helper' +require 'spec_helper' -describe 'cloudstack::default' do - subject { ChefSpec::Runner.new.converge(described_recipe) } - - # Write quick specs using `it` blocks with implied subjects - it { should do_something('...') } - - # Write full examples using the `expect` syntax - it 'does something' do - expect(subject).to do_something('...') +describe 'cloudstack::management_server' do + let(:chef_run) do + ChefSpec::ServerRunner.new.converge(described_recipe) end - # Use an explicit subject - let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } - - it 'does something' do - expect(chef_run).to do_something('...') - end -end - -describe 'cloudstack::cloudstack_management' do - let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) } - it 'installs cloudstack-management' do expect(chef_run).to install_package('cloudstack-management') end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1995e2b..c9a3f38 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,25 +1,3 @@ # Added by ChefSpec require 'chefspec' - -# Uncomment to use ChefSpec's Berkshelf extension -# require 'chefspec/berkshelf' - -RSpec.configure do |config| - # Specify the path for Chef Solo to find cookbooks - # config.cookbook_path = '/var/cookbooks' - - # Specify the path for Chef Solo to find roles - # config.role_path = '/var/roles' - - # Specify the Chef log_level (default: :warn) - # config.log_level = :debug - - # Specify the path to a local JSON file with Ohai data - # config.path = 'ohai.json' - - # Specify the operating platform to mock Ohai data from - # config.platform = 'ubuntu' - - # Specify the operating version to mock Ohai data from - # config.version = '12.04' -end +require 'chefspec/berkshelf' From 7e994b57d785592b1c41b2c54b615b6454cef804 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 14:46:36 -0500 Subject: [PATCH 08/30] Ignore FC075 from Foodcritic --- .foodcritic | 1 + 1 file changed, 1 insertion(+) create mode 100644 .foodcritic diff --git a/.foodcritic b/.foodcritic new file mode 100644 index 0000000..c6a3266 --- /dev/null +++ b/.foodcritic @@ -0,0 +1 @@ +~FC075 \ No newline at end of file From 4450e27acc3cd76473287535a1d2e718e6b8af50 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 15:06:28 -0500 Subject: [PATCH 09/30] Suppress chefspec warning message --- spec/recipes/default_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/recipes/default_spec.rb b/spec/recipes/default_spec.rb index 1ffa217..332033c 100644 --- a/spec/recipes/default_spec.rb +++ b/spec/recipes/default_spec.rb @@ -2,7 +2,7 @@ describe 'cloudstack::management_server' do let(:chef_run) do - ChefSpec::ServerRunner.new.converge(described_recipe) + ChefSpec::ServerRunner.new(platform: 'centos', version: '7.4.1708').converge(described_recipe) end it 'installs cloudstack-management' do From e45094713ad5f8581c6e7cc1d04b0343730af0a4 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 15:09:22 -0500 Subject: [PATCH 10/30] Enhance CircleCI config --- .circleci/config.yml | 49 ++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af6dee9..1dd4737 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,30 +19,42 @@ jobs: steps: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - - run: chef --version - - run: chef exec cookstyle . + - run: + name: "Chef version" + command: chef --version + - run: + name: "Check Cookstyle" + command: chef exec cookstyle . foodcritic: <<: *defaults steps: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - - run: chef --version - - run: chef exec foodcritic . + - run: + name: "Chef version" + command: chef --version + - run: + name: "Check Foodcritic" + command: chef exec foodcritic . chefspec: <<: *defaults steps: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - - run: chef --version - - run: chef exec rspec spec + - run: + name: "Chef version" + command: chef --version + - run: + name: "Check Serverspec" + command: chef exec rspec spec kitchen: - machine: - services: - - docker - working_directory: ~/cookbook/cookbook_cloudstack + machine: true + services: + - docker + working_directory: $CIRCLE_WORKING_DIRECTORY steps: - checkout - run: | @@ -50,11 +62,18 @@ jobs: wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb sudo dpkg -i chefdk_3.5.13-1_amd64.deb fi - - run: chef --version - - run: bundle install - - run: berks install - - run: berks update - - run: KITCHEN_LOCAL_YAML=.kitchen.docker.yml kitchen test --destroy always + - run: + name: "Chef version" + command: chef --version + - run: + name: "Install dependencies" + command: | + bundle install + berks install + berks update + - run: + name: "Run Kitchen test" + command: KITCHEN_LOCAL_YAML=.kitchen.docker.yml kitchen test --destroy always workflows: version: 2 From d1d22ee85231c469ec22c2617205fa825300af31 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 15:17:51 -0500 Subject: [PATCH 11/30] Fix kitchen on ci pipeline --- .circleci/config.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dd4737..9fd3108 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,26 +54,28 @@ jobs: machine: true services: - docker - working_directory: $CIRCLE_WORKING_DIRECTORY steps: - checkout - - run: | - if ! chef -v; then + - run: + name: "Install Chef and Vagrant" + command: | wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb sudo dpkg -i chefdk_3.5.13-1_amd64.deb - fi + + wget https://releases.hashicorp.com/vagrant/2.2.2/vagrant_2.2.2_x86_64.deb + sudo dpkg -i vagrant_2.2.2_x86_64.deb - run: name: "Chef version" command: chef --version - run: - name: "Install dependencies" + name: "Install Gem, Cookbooks dependencies" command: | bundle install berks install berks update - run: name: "Run Kitchen test" - command: KITCHEN_LOCAL_YAML=.kitchen.docker.yml kitchen test --destroy always + command: kitchen test --destroy always workflows: version: 2 From 9f032d2a85f54e9b9f728abff072abe04b452c37 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 15:50:44 -0500 Subject: [PATCH 12/30] Use docker driver for kitchen test --- .circleci/config.yml | 2 +- .kitchen.docker.yml | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .kitchen.docker.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 9fd3108..84196e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,7 +75,7 @@ jobs: berks update - run: name: "Run Kitchen test" - command: kitchen test --destroy always + command: KITCHEN_LOCAL_YAML=.kitchen.docker.yml kitchen test --destroy always workflows: version: 2 diff --git a/.kitchen.docker.yml b/.kitchen.docker.yml new file mode 100644 index 0000000..e13083f --- /dev/null +++ b/.kitchen.docker.yml @@ -0,0 +1,18 @@ +--- +driver: + name: docker + +provisioner: + name: chef_solo + +platforms: + # - name: ubuntu-14.04 + # - name: ubuntu-16.04 + # - name: centos-6 + - name: centos-7 + +suites: + - name: default + run_list: + - recipe[cloudstack::circle-ci] + attributes: From 8eb52a0838bf685e5d7832821a7b08f179b4130b Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 15:55:25 -0500 Subject: [PATCH 13/30] Add kitchen-docker gem --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index 6eaae69..6e74a9c 100644 --- a/Gemfile +++ b/Gemfile @@ -16,3 +16,4 @@ gem 'berkshelf' gem 'test-kitchen' gem 'kitchen-vagrant' +gem 'kitchen-docker' From 1d3bbdd6869785ac31c0a28af4aeba3bd23393a7 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 17:41:37 -0500 Subject: [PATCH 14/30] Cosmetic formatting --- recipes/repo_rhel.rb | 20 ++++++++++---------- recipes/repo_ubuntu.rb | 6 +++--- recipes/vhd-util.rb | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/recipes/repo_rhel.rb b/recipes/repo_rhel.rb index a7308af..c3fc265 100644 --- a/recipes/repo_rhel.rb +++ b/recipes/repo_rhel.rb @@ -20,19 +20,19 @@ include_recipe 'yum' yum_repository 'cloudstack' do - description 'Apache Cloudstack' - baseurl node['cloudstack']['repo_url'] - enabled node['cloudstack']['repo_enabled'] + description 'Apache Cloudstack' + baseurl node['cloudstack']['repo_url'] + enabled node['cloudstack']['repo_enabled'] metadata_expire node['cloudstack']['repo_metadata_expire'] - gpgkey node['cloudstack']['repo_sign'] - gpgcheck node['cloudstack']['repo_sign'].empty? ? false : true - action :create + gpgkey node['cloudstack']['repo_sign'] + gpgcheck node['cloudstack']['repo_sign'].empty? ? false : true + action :create end yum_repository 'mysql-connector' do description 'MySQL Community connectors' - baseurl 'http://repo.mysql.com/yum/mysql-connectors-community/el/$releasever/$basearch/' - gpgkey 'http://repo.mysql.com/RPM-GPG-KEY-mysql' - gpgcheck true - action :create + baseurl 'http://repo.mysql.com/yum/mysql-connectors-community/el/$releasever/$basearch/' + gpgkey 'http://repo.mysql.com/RPM-GPG-KEY-mysql' + gpgcheck true + action :create end diff --git a/recipes/repo_ubuntu.rb b/recipes/repo_ubuntu.rb index fbb01a2..df906a2 100644 --- a/recipes/repo_ubuntu.rb +++ b/recipes/repo_ubuntu.rb @@ -21,10 +21,10 @@ # add Apache CloudStack .deb repo apt_repository 'cloudstack' do - uri node['cloudstack']['repo_url'] - components [ node['cloudstack']['release_major'] ] + uri node['cloudstack']['repo_url'] + components [ node['cloudstack']['release_major'] ] distribution 'trusty' - trusted node['cloudstack']['repo_trust'] + trusted node['cloudstack']['repo_trust'] unless node['cloudstack']['repo_sign'].empty? key node['cloudstack']['repo_sign'] end diff --git a/recipes/vhd-util.rb b/recipes/vhd-util.rb index 89f31c5..0170ac3 100644 --- a/recipes/vhd-util.rb +++ b/recipes/vhd-util.rb @@ -21,7 +21,7 @@ remote_file "#{node['cloudstack']['vhd-util_path']}/vhd-util" do source node['cloudstack']['vhd-util_url'] - mode 0755 + mode 0755 action :create_if_missing only_if { node['recipes'].include?('cloudstack::management_server') } end From 640fcabf8d3e7b5ad1a0d76d98ff502cfea0f145 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 14 Dec 2018 17:42:10 -0500 Subject: [PATCH 15/30] Remove Vagrant installation --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 84196e1..96c447f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -61,9 +61,6 @@ jobs: command: | wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb sudo dpkg -i chefdk_3.5.13-1_amd64.deb - - wget https://releases.hashicorp.com/vagrant/2.2.2/vagrant_2.2.2_x86_64.deb - sudo dpkg -i vagrant_2.2.2_x86_64.deb - run: name: "Chef version" command: chef --version From 7bef2dfe55ae473cf08d1a6830aa511179a795bf Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 13:30:33 -0500 Subject: [PATCH 16/30] Fix for services inside docker container --- .kitchen.docker.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.kitchen.docker.yml b/.kitchen.docker.yml index e13083f..eca7cd0 100644 --- a/.kitchen.docker.yml +++ b/.kitchen.docker.yml @@ -8,8 +8,17 @@ provisioner: platforms: # - name: ubuntu-14.04 # - name: ubuntu-16.04 + # - name: ubuntu-18.04 # - name: centos-6 - name: centos-7 + driver_config: + run_command: /usr/sbin/init + privileged: true + provision_command: + - systemctl enable sshd.service + # - name: debian-7 + # - name: debian-8 + # - name: debian-9 suites: - name: default From 77e5111c842fb7d5fdc28c2a41b2d0d509a81d0e Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 13:48:59 -0500 Subject: [PATCH 17/30] Add cloudstack version to usage recipe --- recipes/usage.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/recipes/usage.rb b/recipes/usage.rb index fc9139e..fca4809 100644 --- a/recipes/usage.rb +++ b/recipes/usage.rb @@ -22,7 +22,9 @@ package 'cloudstack-usage' do action :install - # only_if { node.recipes.include?('cloudstack::management_server') } + unless node['cloudstack']['version'].empty? + version node['cloudstack']['version'] + end end service 'cloudstack-usage' do From eb6d632a3d5d412ba13bb5bcdbed3a47b6e558f4 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 13:49:22 -0500 Subject: [PATCH 18/30] Add more platforms to kitchen test --- .kitchen.docker.yml | 25 ++++++++++++++++++------- .kitchen.yml | 5 ++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.kitchen.docker.yml b/.kitchen.docker.yml index eca7cd0..c4d885a 100644 --- a/.kitchen.docker.yml +++ b/.kitchen.docker.yml @@ -6,19 +6,30 @@ provisioner: name: chef_solo platforms: - # - name: ubuntu-14.04 - # - name: ubuntu-16.04 - # - name: ubuntu-18.04 - # - name: centos-6 + - name: ubuntu-14.04 + driver_config: + run_command: /bin/systemd + privileged: true + - name: ubuntu-16.04 + driver_config: + run_command: /bin/systemd + privileged: true + - name: ubuntu-18.04 + driver_config: + run_command: /bin/systemd + privileged: true + - name: centos-6 + driver_config: + run_command: /usr/sbin/init + privileged: true + provision_command: + - systemctl enable sshd.service - name: centos-7 driver_config: run_command: /usr/sbin/init privileged: true provision_command: - systemctl enable sshd.service - # - name: debian-7 - # - name: debian-8 - # - name: debian-9 suites: - name: default diff --git a/.kitchen.yml b/.kitchen.yml index 211d4e5..60f7944 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -6,7 +6,10 @@ provisioner: name: chef_solo platforms: -# - name: ubuntu-16.04 + - name: ubuntu-14.04 + - name: ubuntu-16.04 + - name: ubuntu-18.04 + - name: centos-6 - name: centos-7 suites: From b6def9717f5ebda03e0e6b79a0f5c02f85f0ad66 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 18:15:14 -0500 Subject: [PATCH 19/30] Move test recipes to its standalone folder --- .kitchen.docker.yml | 2 +- .kitchen.yml | 2 +- Berksfile | 4 ++++ test/cookbooks/test/metadata.rb | 4 ++++ .../cookbooks/test/recipes/all-in-one.rb | 20 ++++++++++--------- 5 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 test/cookbooks/test/metadata.rb rename recipes/circle-ci.rb => test/cookbooks/test/recipes/all-in-one.rb (78%) diff --git a/.kitchen.docker.yml b/.kitchen.docker.yml index c4d885a..75966e2 100644 --- a/.kitchen.docker.yml +++ b/.kitchen.docker.yml @@ -34,5 +34,5 @@ platforms: suites: - name: default run_list: - - recipe[cloudstack::circle-ci] + - recipe[test::all-in-one] attributes: diff --git a/.kitchen.yml b/.kitchen.yml index 60f7944..df7248d 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -15,5 +15,5 @@ platforms: suites: - name: default run_list: - - recipe[cloudstack::circle-ci] + - recipe[test::all-in-one] attributes: diff --git a/Berksfile b/Berksfile index 34fea21..5a7274b 100644 --- a/Berksfile +++ b/Berksfile @@ -1,3 +1,7 @@ source 'https://supermarket.chef.io' metadata + +group :integration do + cookbook 'test', path: 'test/cookbooks/test' +end diff --git a/test/cookbooks/test/metadata.rb b/test/cookbooks/test/metadata.rb new file mode 100644 index 0000000..f0926a1 --- /dev/null +++ b/test/cookbooks/test/metadata.rb @@ -0,0 +1,4 @@ +name 'test' +version '0.0.1' + +depends 'cloudstack' diff --git a/recipes/circle-ci.rb b/test/cookbooks/test/recipes/all-in-one.rb similarity index 78% rename from recipes/circle-ci.rb rename to test/cookbooks/test/recipes/all-in-one.rb index f1f9fd7..d8e57e8 100644 --- a/recipes/circle-ci.rb +++ b/test/cookbooks/test/recipes/all-in-one.rb @@ -1,6 +1,6 @@ # -# Cookbook Name:: cloudstack -# Recipe:: default +# Cookbook Name:: test +# Recipe:: all # Author:: Pierre-Luc Dion () # Copyright 2018, CloudOps, Inc. # @@ -11,24 +11,26 @@ # install mysql-server package 'mariadb-server' - -execute 'set mysql root password' do - command 'mysqladmin -h 127.0.0.1 -u root password password' - action :nothing -end +# include_recipe 'mariadb::server' if platform?(%w(redhat centos fedora oracle)) service 'mariadb' do action :start - notifies :run, 'execute[set mysql root password]', :immediately + # notifies :run, 'execute[set mysql root password]', :immediately end elsif platform?(%w(ubuntu debian)) service 'mysql' do action :start - notifies :run, 'execute[set mysql root password]', :immediately + # notifies :run, 'execute[set mysql root password]', :immediately end end +execute 'set mysql root password' do + command 'mysqladmin -h 127.0.0.1 -u root password password' + # action :nothing + action :run +end + # init database and connection configuration cloudstack_setup_database '127.0.0.1' do root_user 'root' From 61002ac49669ee96b025822d2591a622cc5484bc Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 18:51:52 -0500 Subject: [PATCH 20/30] Update config for centos7 for now --- .circleci/config.yml | 2 +- .kitchen.docker.yml | 18 ------------------ .kitchen.yml | 4 ---- test/cookbooks/test/recipes/all-in-one.rb | 16 +++++++--------- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 96c447f..20fede6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -57,7 +57,7 @@ jobs: steps: - checkout - run: - name: "Install Chef and Vagrant" + name: "Install Chef" command: | wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb sudo dpkg -i chefdk_3.5.13-1_amd64.deb diff --git a/.kitchen.docker.yml b/.kitchen.docker.yml index 75966e2..8f22ca4 100644 --- a/.kitchen.docker.yml +++ b/.kitchen.docker.yml @@ -6,24 +6,6 @@ provisioner: name: chef_solo platforms: - - name: ubuntu-14.04 - driver_config: - run_command: /bin/systemd - privileged: true - - name: ubuntu-16.04 - driver_config: - run_command: /bin/systemd - privileged: true - - name: ubuntu-18.04 - driver_config: - run_command: /bin/systemd - privileged: true - - name: centos-6 - driver_config: - run_command: /usr/sbin/init - privileged: true - provision_command: - - systemctl enable sshd.service - name: centos-7 driver_config: run_command: /usr/sbin/init diff --git a/.kitchen.yml b/.kitchen.yml index df7248d..8f24435 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -6,10 +6,6 @@ provisioner: name: chef_solo platforms: - - name: ubuntu-14.04 - - name: ubuntu-16.04 - - name: ubuntu-18.04 - - name: centos-6 - name: centos-7 suites: diff --git a/test/cookbooks/test/recipes/all-in-one.rb b/test/cookbooks/test/recipes/all-in-one.rb index d8e57e8..2bbb896 100644 --- a/test/cookbooks/test/recipes/all-in-one.rb +++ b/test/cookbooks/test/recipes/all-in-one.rb @@ -9,28 +9,26 @@ include_recipe 'cloudstack::management_server' include_recipe 'cloudstack::usage' +execute 'set mysql root password' do + command 'mysqladmin -h 127.0.0.1 -u root password password' + action :nothing +end + # install mysql-server package 'mariadb-server' -# include_recipe 'mariadb::server' if platform?(%w(redhat centos fedora oracle)) service 'mariadb' do action :start - # notifies :run, 'execute[set mysql root password]', :immediately + notifies :run, 'execute[set mysql root password]', :immediately end elsif platform?(%w(ubuntu debian)) service 'mysql' do action :start - # notifies :run, 'execute[set mysql root password]', :immediately + notifies :run, 'execute[set mysql root password]', :immediately end end -execute 'set mysql root password' do - command 'mysqladmin -h 127.0.0.1 -u root password password' - # action :nothing - action :run -end - # init database and connection configuration cloudstack_setup_database '127.0.0.1' do root_user 'root' From 419a5933ad695f9f9b15c15cc227fde513ca6d35 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 19:04:10 -0500 Subject: [PATCH 21/30] Show ruby version --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20fede6..8a2f4b4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -62,8 +62,10 @@ jobs: wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb sudo dpkg -i chefdk_3.5.13-1_amd64.deb - run: - name: "Chef version" - command: chef --version + name: "Chef and Ruby version" + command: | + chef --version + ruby --version - run: name: "Install Gem, Cookbooks dependencies" command: | From 11c66e46683e9fb4d7ecc7e9103cce64cb53a738 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Mon, 17 Dec 2018 19:10:49 -0500 Subject: [PATCH 22/30] Install ruby --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8a2f4b4..a30ed88 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,6 +56,9 @@ jobs: - docker steps: - checkout + - run: + name: "Set Ruby Version" + command: echo "ruby-2.5.1" > ~/.ruby-version - run: name: "Install Chef" command: | From fb331e442d77e3c77e0c0346629830f3d3395c00 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Wed, 2 Jan 2019 18:24:15 -0500 Subject: [PATCH 23/30] Add systemvm upload to test --- test/cookbooks/test/recipes/all-in-one.rb | 11 +++++++++ .../default/serverspec/systemvm_spec.rb | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 test/integration/default/serverspec/systemvm_spec.rb diff --git a/test/cookbooks/test/recipes/all-in-one.rb b/test/cookbooks/test/recipes/all-in-one.rb index 2bbb896..87adb65 100644 --- a/test/cookbooks/test/recipes/all-in-one.rb +++ b/test/cookbooks/test/recipes/all-in-one.rb @@ -38,6 +38,17 @@ action :create end +# download initial systemvm template +cloudstack_system_template 'xenserver' do + nfs_path node['cloudstack']['secondary']['path'] + nfs_server node['cloudstack']['secondary']['host'] + url node['cloudstack']['systemvm']['xenserver'] + db_user node['cloudstack']['db']['user'] + db_password node['cloudstack']['db']['password'] + db_host node['cloudstack']['db']['host'] + action :create +end + cloudstack_setup_management node.name do tomcat7 true end diff --git a/test/integration/default/serverspec/systemvm_spec.rb b/test/integration/default/serverspec/systemvm_spec.rb new file mode 100644 index 0000000..3af2ab3 --- /dev/null +++ b/test/integration/default/serverspec/systemvm_spec.rb @@ -0,0 +1,24 @@ +require 'serverspec' +set :backend, :exec + +describe file('/data/secondary/template/tmpl/1/1') do + it { should be_directory } +end + +describe file('/data/secondary/template/tmpl/1/1/template.properties') do + it { should be_file } + it { should exist } +end + +describe file('/data/secondary') do + it { should be_directory } +end + +describe file('/data/primary') do + it { should be_directory } +end + +describe service('nfs-server') do + it { should be_enabled } + it { should be_running } +end From a150d48ed39954cb389188965c01e2c2d2051c68 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Thu, 3 Jan 2019 11:38:13 -0500 Subject: [PATCH 24/30] Convert system_template to new custom resource format --- libraries/system_template.rb | 58 -------------- providers/system_template.rb | 72 ------------------ resources/system_template.rb | 92 ++++++++++++++++++++--- test/cookbooks/test/recipes/all-in-one.rb | 11 +-- 4 files changed, 86 insertions(+), 147 deletions(-) delete mode 100644 libraries/system_template.rb delete mode 100644 providers/system_template.rb diff --git a/libraries/system_template.rb b/libraries/system_template.rb deleted file mode 100644 index 7005e24..0000000 --- a/libraries/system_template.rb +++ /dev/null @@ -1,58 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Library:: system_template -# Author:: Pierre-Luc Dion -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -module Cloudstack - module SystemTemplate - # retrieve template ID from database - def db_template_id - # get template ID from database to check path - Chef::Log.debug 'Retrieve template ID from database' - template_cmd = "mysql -h #{@current_resource.db_host} --user=#{@current_resource.db_user} --password=#{@current_resource.db_password} --skip-column-names -U cloud -e 'select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{@current_resource.hypervisor}\" and removed is null'" - template_id = Mixlib::ShellOut.new(template_cmd) - template_id.run_command - Chef::Log.debug "template id = #{template_id.stdout.chomp}" - template_id.stdout.chomp - end - - # Create or mount secondary storage path - def secondary_storage - unless ::File.exist?(@current_resource.nfs_path) - # Use condition enclosing instead of 'not_if' guard because resource nfs_path is not defined in case of resource merging - directory @current_resource.nfs_path do - owner 'root' - group 'root' - action :create - recursive true - end - end - end - - def download_systemvm_template - # Create database configuration for cloudstack management server that will use and existing database. - # puts "Downloading system template from: #{@current_resource.url}" - Chef::Log.info "Downloading system template for #{@current_resource.hypervisor}, this will take some time..." - download_cmd = "/usr/share/cloudstack-common/scripts/storage/secondary/cloud-install-sys-tmplt -m #{@current_resource.nfs_path} -u #{@current_resource.url} -h #{@current_resource.hypervisor} -F" - download_template = Mixlib::ShellOut.new(download_cmd) - download_template.run_command - if download_template.exitstatus == 0 - end - end - end -end diff --git a/providers/system_template.rb b/providers/system_template.rb deleted file mode 100644 index 153dec8..0000000 --- a/providers/system_template.rb +++ /dev/null @@ -1,72 +0,0 @@ -# -# Cookbook Name:: cloudstack -# Provider:: system_template -# Author:: Pierre-Luc Dion () -# Copyright 2018, CloudOps, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Download system template for initial deployment of CloudStack - -include Chef::Mixin::ShellOut -include Cloudstack::Helper -include Cloudstack::SystemTemplate - -use_inline_resources if defined?(:use_inline_resources) # ~FC113 - -action :create do - load_current_resource - - # Chef::Log.info 'creating cloudstack database' - unless @current_resource.exists - converge_by("Downloading system template from: #{@current_resource.url}") do - # test_connection?(@current_resource.admin_apikey, @current_resource.admin_secretkey) - secondary_storage - download_systemvm_template - end - end -end - -def load_current_resource - @current_resource = Chef::Resource::CloudstackSystemTemplate.new(@new_resource.name) - @current_resource.name(@new_resource.name) - @current_resource.url(@new_resource.url) - @current_resource.hypervisor(@new_resource.hypervisor) - @current_resource.nfs_path(@new_resource.nfs_path) - @current_resource.nfs_server(@new_resource.nfs_server) - @current_resource.db_user(@new_resource.db_user) - @current_resource.db_password(@new_resource.db_password) - @current_resource.db_host(@new_resource.db_host) - - # if CloudStack management-server is running, it mean a systemvm template as been downloaded. - if cloudstack_is_running? - @current_resource.exists = true - elsif db_exist?(@current_resource.db_host, @current_resource.db_user, @current_resource.db_password) - if @current_resource.url.nil? - cmd = Mixlib::ShellOut.new("mysql -h #{@current_resource.db_host} --user=#{@current_resource.db_user} --password='#{@current_resource.db_password}' --skip-column-names -U cloud -e 'select max(url) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{@current_resource.hypervisor}\" and removed is null'") - cmd.run_command - cmd.error! - @current_resource.url(cmd.stdout.chomp) - end - template_id = db_template_id - Chef::Log.debug "looking for template in #{@current_resource.nfs_path}/template/tmpl/1/#{template_id}" - if ::File.exist?("#{@current_resource.nfs_path}/template/tmpl/1/#{template_id}/template.properties") - Chef::Log.debug "template exists in #{@current_resource.nfs_path}/template/tmpl/1/#{template_id}" - @current_resource.exists = true - else - @current_resource.exists = false - end - else - Chef::Log.error 'Database not configured. Cannot retrieve Template URL' - end -end diff --git a/resources/system_template.rb b/resources/system_template.rb index b49998c..0f46e4c 100644 --- a/resources/system_template.rb +++ b/resources/system_template.rb @@ -16,18 +16,90 @@ # See the License for the specific language governing permissions and # limitations under the License. -actions :create - default_action :create -attribute :hypervisor, name_attribute: true, kind_of: String -attribute :nfs_path, kind_of: String, default: '/mnt/secondary' -attribute :nfs_server, kind_of: String, default: 'localhost' +property :hypervisor, String, name_property: true +property :nfs_path, String, default: '/mnt/secondary' +property :nfs_server, String, default: 'localhost' # If URL net specify, can retreive template URL from database. -attribute :url, kind_of: String -attribute :db_user, kind_of: String, default: 'cloud' # node['cloudstack']['db']['user'] -attribute :db_password, kind_of: String, default: 'password' # node['cloudstack']['db']['password'] -attribute :db_host, kind_of: String, default: 'localhost' # node['cloudstack']['db']['host'] +property :url, String +property :db_user, String, default: 'cloud' # node['cloudstack']['db']['user'] +property :db_password, String, default: 'password' # node['cloudstack']['db']['password'] +property :db_host, String, default: 'localhost' # node['cloudstack']['db']['host'] + +action :create do + load_current_resource + + # Chef::Log.info 'creating cloudstack database' + unless current_value_exists? + converge_by("Downloading system template from: #{new_resource.url}") do + # test_connection?(new_resource.admin_apikey, new_resource.admin_secretkey) + secondary_storage + download_systemvm_template + end + end +end + +action_class do + include Cloudstack::Helper + + def current_value_exists? + # if CloudStack management-server is running, it mean a systemvm template as been downloaded. + if cloudstack_is_running? + true + elsif db_exist?(new_resource.db_host, new_resource.db_user, new_resource.db_password) + if new_resource.url.nil? + cmd = Mixlib::ShellOut.new("mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password='#{new_resource.db_password}' --skip-column-names -U cloud -e 'select max(url) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'") + cmd.run_command + cmd.error! + new_resource.url(cmd.stdout.chomp) + end + template_id = db_template_id + Chef::Log.debug "looking for template in #{new_resource.nfs_path}/template/tmpl/1/#{template_id}" + if ::File.exist?("#{new_resource.nfs_path}/template/tmpl/1/#{template_id}/template.properties") + Chef::Log.debug "template exists in #{new_resource.nfs_path}/template/tmpl/1/#{template_id}" + true + else + false + end + else + Chef::Log.error 'Database not configured. Cannot retrieve Template URL' + end + end + + # retrieve template ID from database + def db_template_id + # get template ID from database to check path + Chef::Log.debug 'Retrieve template ID from database' + template_cmd = "mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password=#{new_resource.db_password} --skip-column-names -U cloud -e 'select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'" + template_id = Mixlib::ShellOut.new(template_cmd) + template_id.run_command + Chef::Log.debug "template id = #{template_id.stdout.chomp}" + template_id.stdout.chomp + end + + # Create or mount secondary storage path + def secondary_storage + unless ::File.exist?(new_resource.nfs_path) + # Use condition enclosing instead of 'not_if' guard because resource nfs_path is not defined in case of resource merging + directory new_resource.nfs_path do + owner 'root' + group 'root' + action :create + recursive true + end + end + end -attr_accessor :exists + def download_systemvm_template + # Create database configuration for cloudstack management server that will use and existing database. + # puts "Downloading system template from: #{new_resource.url}" + Chef::Log.info "Downloading system template for #{new_resource.hypervisor}, this will take some time..." + download_cmd = "/usr/share/cloudstack-common/scripts/storage/secondary/cloud-install-sys-tmplt -m #{new_resource.nfs_path} -u #{new_resource.url} -h #{new_resource.hypervisor} -F" + download_template = Mixlib::ShellOut.new(download_cmd) + download_template.run_command + if download_template.exitstatus == 0 + end + end +end diff --git a/test/cookbooks/test/recipes/all-in-one.rb b/test/cookbooks/test/recipes/all-in-one.rb index 87adb65..15f3b54 100644 --- a/test/cookbooks/test/recipes/all-in-one.rb +++ b/test/cookbooks/test/recipes/all-in-one.rb @@ -40,13 +40,10 @@ # download initial systemvm template cloudstack_system_template 'xenserver' do - nfs_path node['cloudstack']['secondary']['path'] - nfs_server node['cloudstack']['secondary']['host'] - url node['cloudstack']['systemvm']['xenserver'] - db_user node['cloudstack']['db']['user'] - db_password node['cloudstack']['db']['password'] - db_host node['cloudstack']['db']['host'] - action :create + nfs_path node['cloudstack']['secondary']['path'] + nfs_server node['cloudstack']['secondary']['host'] + url node['cloudstack']['systemvm']['xenserver'] + action :create end cloudstack_setup_management node.name do From d0361914ef3eac09b7c384dab8032bb521adce13 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Thu, 3 Jan 2019 11:38:44 -0500 Subject: [PATCH 25/30] Fix function definition typo --- resources/global_setting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/global_setting.rb b/resources/global_setting.rb index 0113387..ddd6c60 100644 --- a/resources/global_setting.rb +++ b/resources/global_setting.rb @@ -55,7 +55,7 @@ def update_setting(name, value) ) end - def current_value_exists + def current_value_exists? if cloudstack_is_running? if new_resource.admin_apikey.nil? || new_resource.admin_secretkey.nil? Chef::Log.error 'admin_apikey empty, cannot update Global Settings' From 3210111374f1b94f50bb1ae1c5104b24d53e5699 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Thu, 3 Jan 2019 18:00:58 -0500 Subject: [PATCH 26/30] Update CI config --- .circleci/config.yml | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a30ed88..8734263 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,6 @@ defaults: &defaults docker: - - image: chef/chefdk + - image: chef/chefdk:3.6.57 working_directory: ~/cookbook/cookbook_cloudstack version: 2 @@ -20,8 +20,10 @@ jobs: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - run: - name: "Chef version" - command: chef --version + name: "Chef and Ruby version" + command: | + chef --version + ruby --version - run: name: "Check Cookstyle" command: chef exec cookstyle . @@ -32,8 +34,10 @@ jobs: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - run: - name: "Chef version" - command: chef --version + name: "Chef and Ruby version" + command: | + chef --version + ruby --version - run: name: "Check Foodcritic" command: chef exec foodcritic . @@ -44,8 +48,10 @@ jobs: - restore_cache: key: repo-{{ .Environment.CIRCLE_SHA1 }} - run: - name: "Chef version" - command: chef --version + name: "Chef and Ruby version" + command: | + chef --version + ruby --version - run: name: "Check Serverspec" command: chef exec rspec spec @@ -56,14 +62,14 @@ jobs: - docker steps: - checkout - - run: - name: "Set Ruby Version" - command: echo "ruby-2.5.1" > ~/.ruby-version + # - run: + # name: "Set Ruby Version" + # command: echo "ruby-2.5.1" > ~/.ruby-version - run: name: "Install Chef" command: | - wget https://packages.chef.io/files/stable/chefdk/3.5.13/ubuntu/18.04/chefdk_3.5.13-1_amd64.deb - sudo dpkg -i chefdk_3.5.13-1_amd64.deb + wget https://packages.chef.io/files/stable/chefdk/3.6.57/ubuntu/18.04/chefdk_3.6.57-1_amd64.deb + sudo dpkg -i chefdk_3.6.57-1_amd64.deb - run: name: "Chef and Ruby version" command: | @@ -72,7 +78,7 @@ jobs: - run: name: "Install Gem, Cookbooks dependencies" command: | - bundle install + chef exec bundle install berks install berks update - run: From 90a2d61bcb9b9bc6379554db4456e988e3de8f76 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 4 Jan 2019 12:14:56 -0500 Subject: [PATCH 27/30] Fix systemvm_template resource and serverspec --- resources/system_template.rb | 36 +++++++------------ test/cookbooks/test/recipes/all-in-one.rb | 10 +++--- .../default/serverspec/systemvm_spec.rb | 26 +++++++------- 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/resources/system_template.rb b/resources/system_template.rb index 0f46e4c..d95ce13 100644 --- a/resources/system_template.rb +++ b/resources/system_template.rb @@ -25,17 +25,15 @@ # If URL net specify, can retreive template URL from database. property :url, String property :db_user, String, default: 'cloud' # node['cloudstack']['db']['user'] -property :db_password, String, default: 'password' # node['cloudstack']['db']['password'] +property :db_password, String, default: 'cloud' # node['cloudstack']['db']['password'] property :db_host, String, default: 'localhost' # node['cloudstack']['db']['host'] action :create do - load_current_resource - - # Chef::Log.info 'creating cloudstack database' unless current_value_exists? - converge_by("Downloading system template from: #{new_resource.url}") do - # test_connection?(new_resource.admin_apikey, new_resource.admin_secretkey) + converge_by("Creating secondary storage at: #{new_resource.nfs_path}") do secondary_storage + end + converge_by("Downloading system template from: #{new_resource.url}") do download_systemvm_template end end @@ -45,13 +43,12 @@ include Cloudstack::Helper def current_value_exists? - # if CloudStack management-server is running, it mean a systemvm template as been downloaded. + # if CloudStack management-server is running, it mean a systemvm template has been downloaded. if cloudstack_is_running? true elsif db_exist?(new_resource.db_host, new_resource.db_user, new_resource.db_password) if new_resource.url.nil? - cmd = Mixlib::ShellOut.new("mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password='#{new_resource.db_password}' --skip-column-names -U cloud -e 'select max(url) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'") - cmd.run_command + cmd = shell_out!("mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password='#{new_resource.db_password}' --skip-column-names -U cloud -e 'select max(url) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'") cmd.error! new_resource.url(cmd.stdout.chomp) end @@ -65,6 +62,7 @@ def current_value_exists? end else Chef::Log.error 'Database not configured. Cannot retrieve Template URL' + false end end @@ -72,9 +70,7 @@ def current_value_exists? def db_template_id # get template ID from database to check path Chef::Log.debug 'Retrieve template ID from database' - template_cmd = "mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password=#{new_resource.db_password} --skip-column-names -U cloud -e 'select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'" - template_id = Mixlib::ShellOut.new(template_cmd) - template_id.run_command + template_id = shell_out!("mysql -h #{new_resource.db_host} --user=#{new_resource.db_user} --password=#{new_resource.db_password} --skip-column-names -U cloud -e 'select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"#{new_resource.hypervisor}\" and removed is null'") Chef::Log.debug "template id = #{template_id.stdout.chomp}" template_id.stdout.chomp end @@ -82,13 +78,8 @@ def db_template_id # Create or mount secondary storage path def secondary_storage unless ::File.exist?(new_resource.nfs_path) - # Use condition enclosing instead of 'not_if' guard because resource nfs_path is not defined in case of resource merging - directory new_resource.nfs_path do - owner 'root' - group 'root' - action :create - recursive true - end + shell_out!("mkdir -p #{new_resource.nfs_path}") + shell_out!("chown -R root:root #{new_resource.nfs_path}") end end @@ -97,9 +88,8 @@ def download_systemvm_template # puts "Downloading system template from: #{new_resource.url}" Chef::Log.info "Downloading system template for #{new_resource.hypervisor}, this will take some time..." download_cmd = "/usr/share/cloudstack-common/scripts/storage/secondary/cloud-install-sys-tmplt -m #{new_resource.nfs_path} -u #{new_resource.url} -h #{new_resource.hypervisor} -F" - download_template = Mixlib::ShellOut.new(download_cmd) - download_template.run_command - if download_template.exitstatus == 0 - end + shell_out!(download_cmd) + # if download_template.exitstatus == 0 + # end end end diff --git a/test/cookbooks/test/recipes/all-in-one.rb b/test/cookbooks/test/recipes/all-in-one.rb index 15f3b54..01720a2 100644 --- a/test/cookbooks/test/recipes/all-in-one.rb +++ b/test/cookbooks/test/recipes/all-in-one.rb @@ -40,10 +40,12 @@ # download initial systemvm template cloudstack_system_template 'xenserver' do - nfs_path node['cloudstack']['secondary']['path'] - nfs_server node['cloudstack']['secondary']['host'] - url node['cloudstack']['systemvm']['xenserver'] - action :create + nfs_path node['cloudstack']['secondary']['path'] + nfs_server node['cloudstack']['secondary']['host'] + url node['cloudstack']['systemvm']['xenserver'] + db_user 'cloud' + db_password 'cloud' + action :create end cloudstack_setup_management node.name do diff --git a/test/integration/default/serverspec/systemvm_spec.rb b/test/integration/default/serverspec/systemvm_spec.rb index 3af2ab3..259bcf9 100644 --- a/test/integration/default/serverspec/systemvm_spec.rb +++ b/test/integration/default/serverspec/systemvm_spec.rb @@ -1,24 +1,24 @@ require 'serverspec' set :backend, :exec -describe file('/data/secondary/template/tmpl/1/1') do +describe file('/data/secondary') do it { should be_directory } end +describe file('/data/secondary/template/tmpl/1/1') do + it { should be_directory } +end + describe file('/data/secondary/template/tmpl/1/1/template.properties') do it { should be_file } it { should exist } -end +end -describe file('/data/secondary') do - it { should be_directory } -end - -describe file('/data/primary') do - it { should be_directory } -end +# describe file('/data/primary') do +# it { should be_directory } +# end -describe service('nfs-server') do - it { should be_enabled } - it { should be_running } -end +# describe service('nfs-server') do +# it { should be_enabled } +# it { should be_running } +# end From bdb1226863f0bc18e23d4bef4d43d24c7cfc3b78 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 4 Jan 2019 12:45:20 -0500 Subject: [PATCH 28/30] Fix cookstyle --- test/integration/default/serverspec/systemvm_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/default/serverspec/systemvm_spec.rb b/test/integration/default/serverspec/systemvm_spec.rb index 259bcf9..7ec7ee5 100644 --- a/test/integration/default/serverspec/systemvm_spec.rb +++ b/test/integration/default/serverspec/systemvm_spec.rb @@ -7,12 +7,12 @@ describe file('/data/secondary/template/tmpl/1/1') do it { should be_directory } -end +end describe file('/data/secondary/template/tmpl/1/1/template.properties') do it { should be_file } it { should exist } -end +end # describe file('/data/primary') do # it { should be_directory } From 55f6eb8386e1705b7eec6c31ae0233d5fc9d6878 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 4 Jan 2019 12:46:31 -0500 Subject: [PATCH 29/30] Cleanup circle config --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8734263..51e58ff 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -62,9 +62,6 @@ jobs: - docker steps: - checkout - # - run: - # name: "Set Ruby Version" - # command: echo "ruby-2.5.1" > ~/.ruby-version - run: name: "Install Chef" command: | From 9abf6d6981b1919f0702e7a10d63926dbc47cf78 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Fri, 4 Jan 2019 12:46:36 -0500 Subject: [PATCH 30/30] Bump version to v6.1.0 --- CHANGELOG.md | 5 +++++ metadata.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad375af..deeb87f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ This file is used to list changes made in each version of the cloudstack cookbook. +## 6.1.0 + +- khos2ow - Remove Provider and enhance Custom Resources +- khos2ow - Fix CircleCI configs + ## 6.0.1 - khos2ow - Add missing SystemVM URLs for CloudStack 4.10 diff --git a/metadata.rb b/metadata.rb index aeba1cb..eab985a 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,7 +4,7 @@ license 'Apache-2.0' description 'Installs/Configures cloudstack' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '6.0.1' +version '6.1.0' source_url 'https://github.com/cloudops/cookbook_cloudstack' issues_url 'https://github.com/cloudops/cookbook_cloudstack/issues'