Add pacemaker integration code into VSM puppetry

This patch adds in the option to support pacemaker integration in OSP7.
Specifically when pacemaker integration is enabled two VMs will be
created- one for the primary, and one for the secondary. Neither VM
will be defined or started. Addditionally MACs will be generated for
both VMs to prevent an issue on VSM switchover.

Code was also added to support cases where the VSM needs to be
brought up in setups where there's an existing bridge.

Change-Id: I2ca2ccc12a9db56348440d210eef4bde25142aef
This commit is contained in:
Steven Hillman 2015-08-21 11:56:02 -07:00
parent 7b57af350f
commit a9bbbc6e64
6 changed files with 245 additions and 59 deletions

View File

@ -5,14 +5,31 @@
#
class n1k_vsm::deploy
{
require n1k_vsm
include n1k_vsm
#ensure tap interfaces and deploy the vsm
$ctrltap = 'vsm-ctrl0'
$mgmttap = 'vsm-mgmt0'
$pkttap = 'vsm-pkt0'
# Validate and get the array of digits for the vsm_mac_base (or use default)
# Using _vmb as the name for the final string to increase readability
$tmp_mac_base = regsubst($n1k_vsm::vsm_mac_base, '[^0-9a-fA-F]+', '')
if (inline_template('<%= @tmp_mac_base.length %>') < 7) {
$vmb = split('005dc79', '')
} else {
$vmb = split($tmp_mac_base, '')
}
# Generate MACs for VSM
$ctrlmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}1"
$mgmtmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}2"
$pktmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}3"
exec { 'Exec_create_disk':
command => "/usr/bin/qemu-img create -f raw ${n1k_vsm::diskfile} ${n1k_vsm::disksize}G",
unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}",
creates => $n1k_vsm::diskfile,
}
$targetxmlfile = "/var/spool/cisco/vsm/vsm_${n1k_vsm::vsm_role}_deploy.xml"
@ -21,19 +38,49 @@ class n1k_vsm::deploy
owner => 'root',
group => 'root',
mode => '0666',
seltype => 'virt_content_t',
content => template('n1k_vsm/vsm_vm.xml.erb'),
require => Exec['Exec_create_disk'],
}
exec { 'Exec_Define_VSM':
command => "/usr/bin/virsh define ${targetxmlfile}",
unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}",
}
# Don't start VSM if this is pacemaker controlled deployment
if !($n1k_vsm::pacemaker_control) {
exec { 'Exec_Define_VSM':
command => "/usr/bin/virsh define ${targetxmlfile}",
unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}",
require => File['File_Target_XML_File'],
}
exec { 'Exec_Launch_VSM':
command => "/usr/bin/virsh start ${n1k_vsm::vsmname}",
unless => "/usr/bin/virsh list --all | grep ${n1k_vsm::vsmname} | grep -c running",
}
exec { 'Exec_Launch_VSM':
command => "/usr/bin/virsh start ${n1k_vsm::vsmname}",
unless => ("/usr/bin/virsh list --all | grep ${n1k_vsm::vsmname} | grep -c running"),
require => Exec['Exec_Define_VSM'],
}
} else {
# For pacemker controlled deployment, set up the secondary VSM as well
# ensure tap interfaces and deploy the vsm
$ctrltap_s = 'vsm-ctrl1'
$mgmttap_s = 'vsm-mgmt1'
$pkttap_s = 'vsm-pkt1'
# Generate MACs
$ctrlmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}4"
$mgmtmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}5"
$pktmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}6"
Exec['Exec_create_disk'] -> File['File_Target_XML_File'] -> Exec['Exec_Define_VSM'] -> Exec['Exec_Launch_VSM']
exec { 'Exec_create_disk_Secondary':
command => "/usr/bin/qemu-img create -f raw ${n1k_vsm::diskfile_s} ${n1k_vsm::disksize}G",
creates => $n1k_vsm::diskfile_s,
}
$targetxmlfile_s = "/var/spool/cisco/vsm/vsm_${n1k_vsm::vsm_role_s}_deploy.xml"
file { 'File_Target_XML_File_Secondary':
path => $targetxmlfile_s,
owner => 'root',
group => 'root',
mode => '0666',
seltype => 'virt_content_t',
content => template('n1k_vsm/vsm_vm_secondary.xml.erb'),
require => Exec['Exec_create_disk_Secondary'],
}
}
}

View File

@ -36,6 +36,19 @@
# [*n1kv_version*]
# (required) Version of the Nexus1000v VSM
#
# [*pacemaker_control*]
# (optional) Set to determine if pacemaker will control the VSM. If true will deploy both
# primary and secondary VSMs on all nodes and will not start VSM. Defaults to false and
# thus is optional unless this functionality is being used.
#
# [*existing_bridge*]
# (required) If VSM should be installed behind an existing bridge, this should be set to
# true and the bridge name should be provided in phy_if_bridge.
#
# [*vsm_mac_base*]
# (optional) If set, provides randomization for the MAC addresses for the VSM VM(s).
# Should be a (random) hexadecimal number of at least 7 digits (more is fine).
#
class n1k_vsm(
$n1kv_source = '',
$n1kv_version = 'latest',
@ -47,6 +60,9 @@ class n1k_vsm(
$vsm_mgmt_ip,
$vsm_mgmt_netmask,
$vsm_mgmt_gateway,
$pacemaker_control = false,
$existing_bridge = false,
$vsm_mac_base = ''
) {
if($::osfamily != 'Redhat') {
@ -55,6 +71,15 @@ class n1k_vsm(
fail("Unsupported osfamily ${::osfamily}")
}
# Ensure role is set to primary for pacemaker controlled deployment
# Additionally setup the extra variables for the secondary VSM
if ($n1k_vsm::pacemaker_control) {
$vsm_role_s = 'secondary'
$vsmname_s = 'vsm-s'
$imgfile_s = "/var/spool/cisco/vsm/${vsm_role_s}_repacked.iso"
$diskfile_s = "/var/spool/cisco/vsm/${vsm_role_s}_disk"
}
if ($n1k_vsm::vsm_role == 'primary') or ($n1k_vsm::vsm_role == 'standalone') {
$vsmname = 'vsm-p'
$mgmtip = $vsm_mgmt_ip
@ -73,7 +98,9 @@ class n1k_vsm(
$disksize = 4
$imgfile = "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso"
$diskfile = "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_disk"
$ovsbridge = 'vsm-br'
#Set bridge name properly
$ovsbridge = 'vsm-br'
#VSM installation will be done only once. Will not respond to puppet sync
$_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G')

View File

@ -19,7 +19,7 @@ class n1k_vsm::pkgprep_ovscfg
# VSM dependent packages installation section
package { 'Package_qemu-kvm':
ensure => installed,
name => 'qemu-kvm',
name => 'qemu-kvm-rhev',
}
package {'Package_libvirt':
@ -64,8 +64,11 @@ class n1k_vsm::pkgprep_ovscfg
notify { "Debug br ${n1k_vsm::ovsbridge} intf ${n1k_vsm::phy_if_bridge} ." : withpath => true }
notify { "Debug ${n1k_vsm::vsmname} ip ${n1k_vsm::phy_ip_addr} mask ${n1k_vsm::phy_ip_mask} gw_intf ${n1k_vsm::gw_intf}" : withpath => true }
# Check if we've already configured the ovs
if $n1k_vsm::gw_intf != $n1k_vsm::ovsbridge {
$_ovsbridge = regsubst($n1k_vsm::ovsbridge, '[.:-]+', '_', 'G')
$_ovsbridge_mac = inline_template("<%= scope.lookupvar('::macaddress_${_ovsbridge}') %>")
# Check if we've already configured the vsm bridge, skip configuration if so
if ($_ovsbridge_mac == '') {
# Modify Ovs bridge inteface configuation file
augeas { 'Augeas_modify_ifcfg-ovsbridge':
name => $n1k_vsm::ovsbridge,
@ -87,47 +90,50 @@ class n1k_vsm::pkgprep_ovscfg
'set USERCTL no',
],
}
# Modify Physical Interface config file
augeas { 'Augeas_modify_ifcfg-phy_if_bridge':
name => $n1k_vsm::phy_if_bridge,
context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::phy_if_bridge}",
changes => [
'set TYPE OVSPort',
"set DEVICE ${n1k_vsm::phy_if_bridge}",
'set DEVICETYPE ovs',
"set OVS_BRIDGE ${n1k_vsm::ovsbridge}",
'set NM_CONTROLLED no',
'set BOOTPROTO none',
'set ONBOOT yes',
"set NAME ${n1k_vsm::phy_if_bridge}",
'set DEFROUTE no',
'set IPADDR ""',
'rm NETMASK',
'rm GATEWAY',
'set USERCTL no',
],
}
exec { 'Flap_n1kv_phy_if':
command => "/sbin/ifdown ${n1k_vsm::phy_if_bridge} && /sbin/ifup ${n1k_vsm::phy_if_bridge}",
require => augeas['Augeas_modify_ifcfg-phy_if_bridge'],
}
exec { 'Flap_n1kv_bridge':
command => "/sbin/ifdown ${n1k_vsm::ovsbridge} && /sbin/ifup ${n1k_vsm::ovsbridge}",
require => augeas['Augeas_modify_ifcfg-ovsbridge'],
require => Augeas['Augeas_modify_ifcfg-ovsbridge'],
}
# Make sure that networking comes fine after reboot- add init file and restart networking
file { 'Create_Init_File':
replace => 'yes',
path => '/etc/init.d/n1kv',
owner => 'root',
group => 'root',
mode => '0775',
source => 'puppet:///modules/n1k_vsm/n1kv',
require => exec['Flap_n1kv_phy_if', 'Flap_n1kv_bridge'],
notify => Service['Service_network'],
if !($n1k_vsm::existing_bridge) {
# If there isn't an existing bridge, the interface is a port, and we
# need to add it to vsm-br
# Modify Physical Interface config file
augeas { 'Augeas_modify_ifcfg-phy_if_bridge':
name => $n1k_vsm::phy_if_bridge,
context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::phy_if_bridge}",
changes => [
'set TYPE OVSPort',
"set DEVICE ${n1k_vsm::phy_if_bridge}",
'set DEVICETYPE ovs',
"set OVS_BRIDGE ${n1k_vsm::ovsbridge}",
'set NM_CONTROLLED no',
'set BOOTPROTO none',
'set ONBOOT yes',
"set NAME ${n1k_vsm::phy_if_bridge}",
'set DEFROUTE no',
'set IPADDR ""',
'rm NETMASK',
'rm GATEWAY',
'set USERCTL no',
],
}
exec { 'Flap_n1kv_phy_if':
command => "/sbin/ifdown ${n1k_vsm::phy_if_bridge} && /sbin/ifup ${n1k_vsm::phy_if_bridge}",
require => Augeas['Augeas_modify_ifcfg-phy_if_bridge'],
}
} else {
# If there is an existing bridge- create patch ports to connect vsm-br to it
exec { 'Create_patch_port_on_existing_bridge':
command => "/bin/ovs-vsctl --may-exist add-port ${n1k_vsm::phy_if_bridge} ${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge} -- set Interface ${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge} type=patch options:peer=${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge}",
require => Exec['Flap_n1kv_bridge'],
}
exec { 'Create_patch_port_on_vsm_bridge':
command => "/bin/ovs-vsctl --may-exist add-port ${n1k_vsm::ovsbridge} ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} -- set Interface ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} type=patch options:peer=${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge}",
require => Exec['Flap_n1kv_bridge'],
}
}
} # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}"
} # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}" or ($n1k_vsm::existing_bridge == 'true')
}
'Ubuntu': {
}

View File

@ -35,12 +35,9 @@ class n1k_vsm::vsmprep
}
} else {
$vsmimage_uri = 'unspec'
$vsm_path = '/opt/cisco/vsm'
}
# exec { 'Prev_VSM':
# command => "/bin/rm -f /var/spool/cisco/vsm/* || /bin/true",
# }
if $vsmimage_uri == 'file' {
#specify location on target-host where image file will be downloaded to.
file { $vsmtgtimg:
@ -63,8 +60,9 @@ class n1k_vsm::vsmprep
}
}
package {'nexus-1000v-iso':
ensure => $n1k_vsm::n1kv_version,
name => 'nexus-1000v-iso'
ensure => $n1k_vsm::n1kv_version,
name => 'nexus-1000v-iso',
provider => 'yum',
}
}
@ -80,8 +78,15 @@ class n1k_vsm::vsmprep
# Now generate ovf xml file and repackage the iso
exec { 'Exec_VSM_Repackage_Script':
command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso ",
unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}",
command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso",
creates => "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso",
}
# If we're under pacemaker_control, create a secondary VSM iso as well
if ($n1k_vsm::pacemaker_control) {
exec { 'Exec_VSM_Repackage_Script_secondary':
command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname_s} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role_s} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role_s}_repacked.iso",
creates => "/var/spool/cisco/vsm/${n1k_vsm::vsm_role_s}_repacked.iso",
}
}
}

View File

@ -41,6 +41,9 @@
<virtualport type='openvswitch' />
<target dev='<%= @ctrltap %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @ctrlmac %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</interface>
@ -49,6 +52,9 @@
<virtualport type='openvswitch' />
<target dev='<%= @mgmttap %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @mgmtmac %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</interface>
@ -57,6 +63,9 @@
<virtualport type='openvswitch' />
<target dev='<%= @pkttap %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @pktmac %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</interface>

View File

@ -0,0 +1,92 @@
<domain type='kvm' >
<name><%= scope.lookupvar('n1k_vsm::vsmname_s') %></name>
<memory unit='KiB'><%= scope.lookupvar('n1k_vsm::memory') %></memory>
<vcpu placement='static'> <%= scope.lookupvar('n1k_vsm::vcpu') %></vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel7.1.0'>hvm</type>
<boot dev='hd'/>
<boot dev='cdrom'/>
</os>
<features> <acpi/> <apic/> <pae/> </features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='<%= scope.lookupvar('n1k_vsm::diskfile_s') %>'/>
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='<%= scope.lookupvar('n1k_vsm::imgfile_s') %>'/>
<target dev='hdb' bus='ide'/>
<readonly/>
</disk>
<controller type='ide' index='0'>
<alias name='ide0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='bridge'>
<source bridge='<%= scope.lookupvar('n1k_vsm::ovsbridge') %>'/>
<virtualport type='openvswitch' />
<target dev='<%= @ctrltap_s %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @ctrlmac_s %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</interface>
<interface type='bridge'>
<source bridge='<%= scope.lookupvar('n1k_vsm::ovsbridge') %>'/>
<virtualport type='openvswitch' />
<target dev='<%= @mgmttap_s %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @mgmtmac_s %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</interface>
<interface type='bridge'>
<source bridge='<%= scope.lookupvar('n1k_vsm::ovsbridge') %>'/>
<virtualport type='openvswitch' />
<target dev='<%= @pkttap_s %>'/>
<model type='e1000'/>
<% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %>
<mac address='<%= @pktmac_s %>'/>
<% end %>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='en-us'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
<console type='pty' tty='/dev/pts/<%= scope.lookupvar('n1k_vsm::consolepts') %>'>
<source path='/dev/pts/<%= scope.lookupvar('n1k_vsm::consolepts') %>'/>
<target port='0'/>
</console>
</devices>
</domain>