mirror of https://github.com/apache/cloudstack.git
Cherry-pick of 11c00977f77f45aa7b0c387dc88360eba0819e8a:
---- Author: Ian Southam <isoutham@schubergphilis.com> First commit towards moving systemvm to chef based configuration In this commit 1. cmdline json databag is created 2. ip association data bag is created 3. Basic chef cookbook to manage ips and routes Conflicts: systemvm/patches/debian/config/etc/init.d/cloud-early-config systemvm/patches/debian/config/var/chef/cookbooks/README tools/appliance/definitions/systemvm64template/postinstall.sh ---- Because we've refactored the systemvm template the change to postinstall.sh now gets its own chef.sh file.
This commit is contained in:
parent
9514f259f6
commit
5b82e2059d
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"run_list": [
|
||||
"recipe[csip::default]"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
data_bags_path "/var/chef/data_bags"
|
||||
cookbook_path "/var/chef/cookbooks"
|
||||
log_level :debug
|
||||
log_location STDOUT
|
||||
|
|
@ -1336,6 +1336,11 @@ STORAGE_NETMASK=""
|
|||
STORAGE_CIDR=""
|
||||
VM_PASSWORD=""
|
||||
|
||||
CHEF_TMP_FILE=/tmp/cmdline.json
|
||||
COMMA="\t"
|
||||
echo -e "{\n\"id\": \"cmdline\"," > ${CHEF_TMP_FILE}
|
||||
echo -e "{\n\"cmd_line\": {" > ${CHEF_TMP_FILE}
|
||||
|
||||
for i in $CMDLINE
|
||||
do
|
||||
# search for foo=bar pattern and cut out foo
|
||||
|
|
@ -1480,6 +1485,12 @@ for i in $CMDLINE
|
|||
esac
|
||||
done
|
||||
|
||||
echo -e "\n\t}\n}" >> ${CHEF_TMP_FILE}
|
||||
if [ "$TYPE" != "unknown" ]
|
||||
then
|
||||
mv ${CHEF_TMP_FILE} /var/chef/data_bags/vr/cmd_line.json
|
||||
fi
|
||||
|
||||
[ $ETH0_IP ] && LOCAL_ADDRS=$ETH0_IP
|
||||
[ $ETH0_IP6 ] && LOCAL_ADDRS=$ETH0_IP6
|
||||
[ $ETH0_IP ] && [ $ETH0_IP6 ] && LOCAL_ADDRS="$ETH0_IP,$ETH0_IP6"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
Location for cookbooks for the system appliances
|
||||
|
||||
csip - is a provider to maintain ip associations
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
csip CHANGELOG
|
||||
==============
|
||||
|
||||
This file is used to list changes made in each version of the csip cookbook.
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you 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.
|
||||
|
||||
0.1.0
|
||||
-----
|
||||
- [Ian Southam] - Initial release of csip
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
TODO
|
||||
|
||||
Routes
|
||||
|
||||
Default Route (work out differences between VR and VPCr)
|
||||
|
||||
Adding marks via ip rule
|
||||
ie. ip rule add fwmark $tableNo table $tableName
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
csip Cookbook
|
||||
=============
|
||||
TODO: Cookbook to configure and maintain ip associations for VPCr and Vr
|
||||
|
||||
Requirements
|
||||
------------
|
||||
This is specifically designed to run insode the Virtual router and VPC router appliances in Apache Cloudstack
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
License and Authors
|
||||
-------------------
|
||||
Authors:
|
||||
Issued under the Apache 2.0 license
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
require 'ipaddr'
|
||||
require 'pp'
|
||||
|
||||
a = IPAddr.new("10.0.2.180")
|
||||
pp a.mask("255.255.255.128").to_s
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# ----------------------------------------------------------- #
|
||||
# Helper functions for the cookbook
|
||||
#
|
||||
# listIps will return a list of IPs/devices that should be
|
||||
# deleted
|
||||
# ----------------------------------------------------------- #
|
||||
require 'ipaddr'
|
||||
|
||||
def listIPs(ips)
|
||||
# ----------------------------------------------------------- #
|
||||
# Collect all configured ip4 interfaces on the machine and
|
||||
# compare it to the cloudstack configuration
|
||||
# Returns a hash containing any ip/device combinations
|
||||
# that should not be there
|
||||
# ----------------------------------------------------------- #
|
||||
ipList = Hash.new
|
||||
cmd = Mixlib::ShellOut.new("ip addr show")
|
||||
cmd.run_command
|
||||
if cmd.exitstatus == 0
|
||||
cmd.stdout.each_line do |line|
|
||||
next unless line.include? "inet "
|
||||
bits = line.strip.split(/ /)
|
||||
# For now do not mess with the control interface
|
||||
next if bits[-1] == "lo" or bits[-1] == "eth0"
|
||||
if ! inConfig(ips, bits[-1], bits[1])
|
||||
ipList[ bits[-1] ] = bits[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
return ipList
|
||||
end
|
||||
|
||||
def inConfig(ips, dev, tip)
|
||||
# ----------------------------------------------------------- #
|
||||
# Returns true if the ip/dev combination is in the config
|
||||
# Returns false if it is not
|
||||
# ----------------------------------------------------------- #
|
||||
if ips[dev].nil?
|
||||
return false
|
||||
end
|
||||
ips[dev].each do |o|
|
||||
oip = o['publicIp'] + '/' << IPAddr.new(o['vlanNetmask']).to_i.to_s(2).count("1").to_s
|
||||
if oip == tip
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def execute(cmdStr)
|
||||
cmd = Mixlib::ShellOut.new("#{cmdStr}")
|
||||
cmd.run_command
|
||||
#puts "\n#{cmdStr} #{cmdPar} #{cmd.status}"
|
||||
cmd.exitstatus == 0
|
||||
end
|
||||
|
||||
def executeReturn(cmdStr)
|
||||
cmd = Mixlib::ShellOut.new("#{cmdStr}")
|
||||
cmd.run_command
|
||||
#puts "\n#{cmdStr} #{cmdPar} #{cmd.status}"
|
||||
cmd.stdout.split(/\n/)
|
||||
end
|
||||
|
||||
def calculateNetwork(ip, mask)
|
||||
return IPAddr.new(ip).mask(mask).to_s
|
||||
end
|
||||
|
||||
def calculateCIDRMask(mask)
|
||||
return IPAddr.new( mask ).to_i.to_s(2).count("1").to_s
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
name 'csip'
|
||||
maintainer 'Apache Cloudstack'
|
||||
maintainer_email 'dev@cloudstack.apache.org'
|
||||
license 'Apache 2.0'
|
||||
description 'Installs/Configures csip'
|
||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||
version '0.1.0'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
action :create do
|
||||
file "/root/testing" do
|
||||
mode '644'
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
require 'ipaddr'
|
||||
|
||||
action :create do
|
||||
if @current_resource.exists
|
||||
Chef::Log.info "#{ @new_resource.device } already configured - nothing to do."
|
||||
else
|
||||
converge_by("Setting up #{ @new_resource }") do
|
||||
plumbDevice
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action :delete do
|
||||
if @current_resource.exists
|
||||
converge_by("Removing #{ @new_resource }") do
|
||||
unPlumbDevice
|
||||
end
|
||||
else
|
||||
Chef::Log.info "#{ @new_resource.device } not configured - nothing to do."
|
||||
end
|
||||
end
|
||||
|
||||
def load_current_resource
|
||||
@current_resource = Chef::Resource::CsipDevice.new(@new_resource.name)
|
||||
@current_resource.index(@new_resource.index)
|
||||
@current_resource.name(@new_resource.name)
|
||||
@current_resource.bdev(@new_resource.bdev)
|
||||
@current_resource.object(@new_resource.object)
|
||||
@current_resource.exists = false
|
||||
if new_resource.cidrs.nil?
|
||||
@current_resource.cidrs(new_resource.object['publicIp'] + '/' + IPAddr.new( new_resource.object['vlanNetmask']).to_i.to_s(2).count("1").to_s)
|
||||
else
|
||||
@current_resource.cidrs(@new_resource.cidrs)
|
||||
end
|
||||
if device_exists?
|
||||
@current_resource.exists = true
|
||||
end
|
||||
end
|
||||
|
||||
def device_exists?
|
||||
current_resource.device = current_resource.bdev
|
||||
if current_resource.index > 0
|
||||
current_resource.device = current_resource.device + ':' + current_resource.index.to_s
|
||||
end
|
||||
if not checkDevice
|
||||
Chef::Log.error "#{ current_resource.bdev } not present cannot configure"
|
||||
return true
|
||||
end
|
||||
deviceUp?
|
||||
correctIP?
|
||||
correctConntrack?
|
||||
return current_resource.up && current_resource.configured && current_resource.contrack
|
||||
end
|
||||
|
||||
def plumbDevice
|
||||
if ! current_resource.configured
|
||||
if ! execute("ip addr add dev #{current_resource.device} #{current_resource.cidrs} brd +")
|
||||
Chef::Log.error "#{ @new_resource.device } failed to configure ip on interface"
|
||||
return false
|
||||
end
|
||||
end
|
||||
if ! current_resource.up
|
||||
if ! execute("ip link set #{current_resource.device} up")
|
||||
Chef::Log.error "#{ @new_resource.device } failed to bring interface up"
|
||||
return false
|
||||
end
|
||||
end
|
||||
if ! current_resource.contrack
|
||||
if ! execute("iptables -t mangle -A PREROUTING -i #{current_resource.device} -m state --state NEW -j CONNMARK --set-mark #{current_resource.object['nicDevId']}")
|
||||
Chef::Log.error "#{ @new_resource.device } failed to set set conmark"
|
||||
return false
|
||||
end
|
||||
end
|
||||
execute("arping -c 1 -I #{current_resource.device} -A -U -s #{current_resource.object['publicIp']} #{current_resource.object['publicIp']}")
|
||||
execute("arping -c 1 -I #{current_resource.device} -A -U -s #{current_resource.object['publicIp']} #{current_resource.object['publicIp']}")
|
||||
return true
|
||||
end
|
||||
|
||||
def unPlumbDevice
|
||||
pp "ip addr del dev #{current_resource.device} #{current_resource.cidrs}"
|
||||
if ! execute("ip addr del dev #{current_resource.device} #{current_resource.cidrs}")
|
||||
Chef::Log.error "#{ @new_resource.device } failed to delete ip on interface"
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def correctConntrack?
|
||||
current_resource.contrack = execute("iptables-save -t mangle | grep \"PREROUTING -i #{current_resource.bdev} -m state --state NEW -j CONNMARK --set-xmark\"")
|
||||
return current_resource.contrack
|
||||
end
|
||||
|
||||
def correctIP?
|
||||
current_resource.configured = execute("ip addr show #{current_resource.bdev} | grep #{current_resource.cidrs}")
|
||||
return current_resource.configured
|
||||
end
|
||||
|
||||
def deviceUp?
|
||||
current_resource.up = ! execute("ip link show #{current_resource.device} | grep DOWN")
|
||||
return current_resource.up
|
||||
end
|
||||
|
||||
def checkDevice
|
||||
file = ::File.open("/proc/net/dev")
|
||||
attempts = 0
|
||||
found = false
|
||||
until attempts > 15 or found do
|
||||
::File.readlines(file).each do |line|
|
||||
if line.include? "#{current_resource.bdev}:"
|
||||
found = true
|
||||
end
|
||||
end
|
||||
attempts += 1
|
||||
sleep(1)
|
||||
end
|
||||
file.close
|
||||
return found
|
||||
end
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
#
|
||||
# ip route flush cache
|
||||
#
|
||||
action :create do
|
||||
if @current_resource.exists
|
||||
Chef::Log.info "#{ @new_resource.dev } already exists - nothing to do."
|
||||
else
|
||||
converge_by("Creating route for #{ @new_resource }") do
|
||||
createRoute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
action :delete do
|
||||
|
||||
end
|
||||
|
||||
def load_current_resource
|
||||
@current_resource = Chef::Resource::CsipRoute.new(@new_resource.name)
|
||||
@current_resource.exists = false
|
||||
@current_resource.ip(@new_resource.ip)
|
||||
@current_resource.mask(@new_resource.mask)
|
||||
@current_resource.dev(@new_resource.dev)
|
||||
@current_resource.table(@new_resource.table)
|
||||
@current_resource.type(@new_resource.type)
|
||||
@current_resource.network(calculateNetwork(@new_resource.ip,@new_resource.mask))
|
||||
@current_resource.cidrm(calculateCIDRMask(@new_resource.mask))
|
||||
if device_exists?
|
||||
@current_resource.exists = true
|
||||
end
|
||||
end
|
||||
|
||||
def device_exists?
|
||||
Chef::Log.debug "Checking for existence of routing table"
|
||||
@current_resource.tableExists = checkTableExists
|
||||
Chef::Log.debug "Checking for existence of route"
|
||||
if @current_resource.type == "dev"
|
||||
@current_resource.routeExists = typeDevExists()
|
||||
return @current_resource.routeExists && @current_resource.tableExists
|
||||
end
|
||||
if @current_resource.type == "default"
|
||||
@current_resource.routeExists = typeDefaultExists()
|
||||
return @current_resource.routeExists && @current_resource.tableExists
|
||||
end
|
||||
Chef::Log.error "Cannot provision a route of type #{current_resource.type}"
|
||||
# Route cannot exist if the table does not but let us be belt and braces about this
|
||||
return true && @current_resource.tableExists
|
||||
end
|
||||
|
||||
def checkTableExists
|
||||
file="/etc/iproute2/rt_tables"
|
||||
::File.readlines(file).each do |line|
|
||||
next if line =~ /^#/
|
||||
next if ! line.include? "#{@current_resource.dev[3,1]} #{@current_resource.table}"
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def typeDevExists
|
||||
executeReturn("ip route show table #{@current_resource.table} dev #{current_resource.dev}").each do |line|
|
||||
next if ! line.include? "proto static"
|
||||
next if ! line.include? "#{current_resource.network}/#{current_resource.cidrm}"
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def typeDefaultExists
|
||||
executeReturn("ip route show table #{@current_resource.table} dev #{@current_resource.dev} via #{@current_resource.ip}").each do |line|
|
||||
next if ! line.include? "default"
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def createRoute
|
||||
if(! @current_resource.tableExists)
|
||||
execute(" echo #{@current_resource.dev[3,1]} #{@current_resource.table} >> /etc/iproute2/rt_tables")
|
||||
end
|
||||
if(! @current_resource.routeExists)
|
||||
if(@current_resource.type == "dev")
|
||||
execute("ip route add #{current_resource.network}/#{current_resource.cidrm} dev #{current_resource.dev} table #{current_resource.table} proto static")
|
||||
end
|
||||
if(@current_resource.type == "default")
|
||||
execute("ip route add default via #{current_resource.ip} table #{current_resource.table} proto static")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
#
|
||||
begin
|
||||
vr_ips = data_bag_item('vr', 'ips')
|
||||
rescue
|
||||
raise format('Cannot find the %s databag item within the %s databag. Please correct this', 'vr', 'ips')
|
||||
end
|
||||
|
||||
# List configured ips on this node and remove any that are not in the configuration
|
||||
listIPs(vr_ips).each do |dev, ip|
|
||||
csip_device "#{dev}-#{ip}" do
|
||||
action :delete
|
||||
cidrs ip
|
||||
index 0
|
||||
bdev dev
|
||||
end
|
||||
end
|
||||
|
||||
vr_ips.each do |name,data|
|
||||
next unless data.class == Array
|
||||
next unless data.length > 0
|
||||
idx = 0
|
||||
data.each do |ipo|
|
||||
csip_device "#{name}-#{idx}" do
|
||||
object ipo
|
||||
index idx
|
||||
bdev name
|
||||
end
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
|
||||
# Add an necessary routes
|
||||
# This could be embedded in the device recipe is done like that for self healing purposes
|
||||
vr_ips.each do |name,data|
|
||||
next unless data.class == Array
|
||||
next unless data.length > 0
|
||||
# ip route add $subnet/$mask dev $ethDev table $tableName proto static
|
||||
data.each do |ipo|
|
||||
csip_route "#{name}-dev" do
|
||||
type "dev"
|
||||
table "Table_#{name}"
|
||||
ip ipo['publicIp']
|
||||
mask ipo['vlanNetmask']
|
||||
dev name
|
||||
end
|
||||
csip_route "#{name}-default" do
|
||||
type "default"
|
||||
table "Table_#{name}"
|
||||
ip ipo['vlanGateway']
|
||||
mask ipo['vlanNetmask']
|
||||
dev name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
default_action(:create)
|
||||
|
||||
attribute(:id)
|
||||
attribute(:address)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
actions :create, :delete
|
||||
default_action(:create)
|
||||
|
||||
attribute(:device)
|
||||
attribute(:object)
|
||||
attribute(:cidrs)
|
||||
attribute(:index)
|
||||
attribute(:bdev)
|
||||
|
||||
attr_accessor :exists
|
||||
attr_accessor :up
|
||||
attr_accessor :contrack
|
||||
attr_accessor :configured
|
||||
attr_accessor :device
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
#
|
||||
actions :create, :delete
|
||||
default_action(:create)
|
||||
|
||||
# dev default
|
||||
attribute(:type)
|
||||
attribute(:table)
|
||||
attribute(:ip)
|
||||
attribute(:mask)
|
||||
attribute(:gateway)
|
||||
attribute(:dev)
|
||||
attribute(:network)
|
||||
attribute(:cidrm)
|
||||
attribute(:tableExists)
|
||||
attribute(:routeExists)
|
||||
|
||||
attr_accessor :exists
|
||||
attr_accessor :tableExists
|
||||
attr_accessor :routeExists
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
function install_chef() {
|
||||
curl -L https://www.opscode.com/chef/install.sh | sudo bash
|
||||
}
|
||||
|
||||
return 2>/dev/null || install_chef
|
||||
|
|
@ -88,6 +88,7 @@ config = {
|
|||
'../../cloud_scripts_shar_archive.sh',
|
||||
'configure_systemvm_services.sh',
|
||||
'authorized_keys.sh',
|
||||
'chef.sh',
|
||||
'configure_persistent_config.sh',
|
||||
# cleanup & space-saving
|
||||
'cleanup.sh',
|
||||
|
|
|
|||
Loading…
Reference in New Issue