Nitrous plugin will install Base OS, multipath options, create VMs and their network settings for Fuel provisioning and deployment.

US809843

Change-Id: I18c8c10021da170ad9aaa29fe1410c4b4072ece5
This commit is contained in:
Dinesh Yadav 2016-11-21 23:06:58 +05:30 committed by Omar Rivera
parent c2a23b04f1
commit df37614679
27 changed files with 2470 additions and 0 deletions

202
LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 AT&T 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.

23
components.yaml Normal file
View File

@ -0,0 +1,23 @@
# Copyright 2016 AT&T, 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.
- name: additional_service:nitrous
compatible:
- name: 'hypervisor:kvm'
- name: 'hypervisor:qemu'
requires: []
incompatible:
- name: 'hypervisor:vmware'
label: "Nitrous"
description: "Configures bare metal servers and Fuel deployable VMs."

View File

@ -0,0 +1,25 @@
# Copyright (c) 2016 AT&T 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.
notice('MODULAR: nitrous/nitrous.pp')
include nitrous
class { 'nitrous::packages': }
class { 'nitrous::config': }
exec { '/etc/ops_create.sh' :
path => '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin',
require => Class['nitrous'],
}

View File

@ -0,0 +1,26 @@
# Copyright (c) 2016 AT&T 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 Puppet::Parser::Functions
newfunction(:find_node, :type => :rvalue, :doc => <<-EOS
EOS
) do |args|
nodes = args[0]
required_name = args[1]
fail "Nodes should be an Array! Got: #{nodes.inspect}" unless nodes.is_a? Array
nodes.find do |node|
node['mac_address'] == required_name
end
end
end

View File

@ -0,0 +1,68 @@
# Copyright (c) 2016 AT&T 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 Puppet::Parser::Functions
newfunction(:opsvm_filter, :type => :rvalue, :doc => <<-EOS
Filter the ops_server_config array and convert to the structure readable by the opsvm script.
EOS
) do |args|
ops_server_config = args[0]
pxe_br = args[2]
kvm_filter = args[1]
mgt_br = args[3]
fail "The ops_server_config should be an Array! Got: #{ops_server_config}" unless ops_server_config.is_a? Array
kvm_hosts = []
ops_server_config.each do |op_host|
next unless op_host['kvm'] == kvm_filter
host_hash = {}
host_hash['name'] = op_host['name'] if op_host['name']
host_hash['cpu'] = op_host.fetch('cpu', 2)
host_hash['ram'] = op_host.fetch('ram', 2).to_i * 1024
networks = []
pxe_network = {}
pxe_network['network'] = "#{pxe_br}"
pxe_network['mac'] = op_host['mac_address']
networks << pxe_network
mgmt_network = {}
mgmt_network['network'] = "#{mgt_br}"
networks << mgmt_network
host_hash['networks'] = networks
volumes = []
app_volume = {}
app_volume['size'] = op_host.fetch('app_disk', 10).to_i * 1024 * 1024 * 1024
app_volume['name'] = op_host['app_volume_name']
app_volume['name'] = "app_disk_#{host_hash['name']}" unless app_volume['name']
volumes << app_volume
os_volume = {}
os_volume['size'] = op_host.fetch('os_disk', 10).to_i * 1024 * 1024 * 1024
os_volume['name'] = op_host['os_volume_name']
os_volume['name'] = "os_disk_#{host_hash['name']}" unless os_volume['name']
volumes << os_volume
log_volume = {}
log_volume['size'] = op_host.fetch('log_disk', 10).to_i * 1024 * 1024 * 1024
log_volume['name'] = op_host['log_volume_name']
log_volume['name'] = "log_disk_#{host_hash['name']}" unless log_volume['name']
volumes << log_volume
host_hash['volumes'] = volumes
kvm_hosts << host_hash
end
kvm_hosts
end
end

View File

@ -0,0 +1,198 @@
# Copyright (c) 2016 AT&T 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.
require 'rexml/document'
require 'tempfile'
Puppet::Type.type(:opsvm_pool).provide(:virsh) do
commands :virsh => 'virsh'
def self.instances
list = virsh('-q', 'pool-list', '--all')
list.split(/\n/)[0..-1].map do |line|
values = line.strip.split(/ +/)
new(
:name => values[0],
:active => values[1].match(/^act/)? :true : :false,
:autostart => values[2].match(/no/) ? :false : :true,
:provider => self.name
)
end
end
def status
list = virsh('-q', 'pool-list', '--all')
list.split(/\n/)[0..-1].detect do |line|
fields = line.strip.split(/ +/)
if (fields[0].match(/^#{resource[:name]}$/))
return :present
end
end
return :absent
end
def self.prefetch(resources)
pools = instances
resources.keys.each do |name|
if provider = pools.find{ |pool| pool.name == name}
resources[name].provider = provider
end
end
end
def create
defined = self.definePool
if !defined
# for some reason the pool has not been defined
# malformed xml
# or failed tmpfile creationa
# or ?
raise Puppet::Error.new("Unable to define the pool")
end
self.buildPool
@property_hash[:ensure] = :present
should_active = @resource.should(:active)
unless self.active == should_active
self.active = should_active
end
should_autostart = @resource.should(:autostart)
unless self.autostart == should_autostart
self.autostart = should_autostart
end
end
def destroy
self.destroyPool
@property_hash.clear
end
def definePool
result = false
begin
tmpFile = Tempfile.new("pool.#{resource[:name]}")
xml = buildPoolXML resource
tmpFile.write(xml)
tmpFile.rewind
virsh('pool-define', tmpFile.path)
result = true
ensure
tmpFile.close
tmpFile.unlink
end
return result
end
def buildPool
begin
virsh('pool-build', '--pool', resource[:name])
rescue
# Unable to build the pool maybe because
# it is already defined (it this case we should consider
# to continue execution)
# or there is permission issue on the fs
# or ?
# in these cases we should consider raising something
notice("Unable to build the pool")
end
end
def destroyPool
begin
virsh('pool-destroy', resource[:name])
rescue Puppet::ExecutionFailure => e
notice(e.message)
end
virsh('pool-undefine', resource[:name])
end
def active
@property_hash[:active] || :false
end
def active=(active)
if (active == :true)
virsh 'pool-start', '--pool', resource[:name]
@property_hash[:active] = 'true'
else
virsh 'pool-destroy', '--pool', resource[:name]
@property_hash[:active] = 'false'
end
end
def autostart
@property_hash[:autostart] || :false
end
def autostart=(autostart)
if (autostart == :true)
virsh 'pool-autostart', '--pool', resource[:name]
@property_hash[:autostart] = :true
else
virsh 'pool-autostart', '--pool', resource[:name], '--disable'
@property_hash[:autostart] = :false
end
end
def exists?
@property_hash[:ensure] != :absent
end
def buildPoolXML(resource)
root = REXML::Document.new
pool = root.add_element 'pool', {'type' => resource[:type]}
name = pool.add_element 'name'
name.add_text resource[:name]
srcHost = resource[:sourcehost]
srcPath = resource[:sourcepath]
srcDev = resource[:sourcedev]
srcName = resource[:sourcename]
srcFormat = resource[:sourceformat]
if (srcHost || srcPath || srcDev || srcName || srcFormat)
source = pool.add_element 'source'
source.add_element('host', {'name' => srcHost}) if srcHost
source.add_element('dir', {'path' => srcPath}) if srcPath
source.add_element('format', {'type' => srcFormat}) if (srcFormat)
if (srcDev)
Array(srcDev).each do |dev|
source.add_element('device', {'path' => dev})
end
end
if (srcName)
srcNameEl = source.add_element 'name'
srcNameEl.add_text srcName
end
end
target = resource[:target]
if target
targetEl = pool.add_element 'target'
targetPathEl = targetEl.add_element 'path'
targetPathEl.add_text target
end
return root.to_s
end # buildPoolXML
end

View File

@ -0,0 +1,118 @@
# Copyright (c) 2016 AT&T 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.
Puppet::Type.newtype(:opsvm_pool) do
@doc = %q{Manages opsvm pools
Example :
opsvm_pool { 'default' :
ensure => absent
}
opsvm_pool { 'mydirpool' :
ensure => present,
active => true,
autostart => true,
type => 'dir',
target => '/tmp/mypool',
}
opsvm_pool { 'vm_storage':
ensure => 'present',
active => 'true',
type => 'logical',
sourcedev => ['/dev/sdb', '/dev/sdc'],
target => '/dev/vg0'
}
}
ensurable do
desc 'Creation or the removal of a pool`present` means that the pool will be defined and created
`absent` means that the pool will be purged from the system'
defaultto(:present)
newvalue(:present) do
provider.create
end
newvalue(:absent) do
if (provider.exists?)
provider.destroy
end
end
def retrieve
provider.status
end
end
newparam(:name, :namevar => true) do
desc 'The pool name.'
newvalues(/^\S+$/)
end
newparam(:type) do
desc 'The pool type.'
newvalues(:dir, :netfs, :fs, :logical, :disk, :iscsi, :mpath, :rbd, :sheepdog)
end
newparam(:sourcehost) do
desc 'The source host.'
newvalues(/^\S+$/)
end
newparam(:sourcepath) do
desc 'The source path.'
newvalues(/(\/)?(\w)/)
end
newparam(:sourcedev) do
desc 'The source device.'
newvalues(/(\/)?(\w)/)
end
newparam(:sourcename) do
desc 'The source name.'
newvalues(/^\S+$/)
end
newparam(:sourceformat) do
desc 'The source format.'
newvalues(:auto, :nfs, :glusterfs, :cifs)
end
newparam(:target) do
desc 'The target.'
newvalues(/(\/)?(\w)/)
end
newproperty(:active) do
desc 'Whether the pool should be started.'
defaultto(:true)
newvalues(:true)
newvalues(:false)
end
newproperty(:autostart) do
desc 'Whether the pool should be autostarted.'
defaultto(:false)
newvalues(:true)
newvalues(:false)
end
end

View File

@ -0,0 +1,65 @@
# Copyright (c) 2016 AT&T 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.
class nitrous::config {
$ops_hosts = $::nitrous::kvm_hosts
$ops_endpoints_keys = $::nitrous::endpoints_keys
$pool_type = $::nitrous::opsvm_pool_type
file { 'opsvms_settings' :
ensure => 'present',
path => '/etc/hiera/plugins/fuel_opsvms.yaml',
owner => 'root',
group => 'root',
mode => '0644',
content => inline_template('<%= require "yaml"; YAML.dump(@ops_hosts) + "\n" %>'),
}
file_line { 'kvm_user':
path => '/etc/libvirt/qemu.conf',
line => 'user = "root"',
match => '#user = "root"',
} ~>
service {'libvirtd':
ensure => 'running',
}
opsvm_pool { 'default' :
ensure => present,
type => "$pool_type",
active => true,
target => '/opt/opsvm',
}
if !($::nitrous::node_name == '') {
exec { "/bin/hostname $::nitrous::node_name" :
path => '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin',
}
} else {
warning('Node is not available, please check Nitrous config.')
}
puppet::ops_endpoints_keys::keys { $ops_endpoints_keys: }
define puppet::ops_endpoints_keys::keys ($ops_endpoints_keys = $title) {
if ($::nitrous::net_bridge == 'linuxbr') {
opsvm_net { "$ops_endpoints_keys" :
forward_mode => 'bridge',
bridge => "$ops_endpoints_keys",
autostart => true,
}
}
}
}

View File

@ -0,0 +1,125 @@
# Copyright (c) 2016 AT&T 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.
class nitrous {
$hiera_values = hiera_hash('nitrous', {})
$nitrous_config = $hiera_values['node_additional_config']
$nodes_hash = parseyaml($nitrous_config)
$nodes_array = pick($nodes_hash['nodes'], [])
$authors = 'Dinesh Yadav(dy270k@att.com)'
$plugin_version = $hiera_values['metadata']['plugin_version']
$agent_conf = '/etc/puppet/puppet.conf'
$env_conf = '/etc/rc.local'
$libvirt_conf = '/etc/libvirt'
$line = $hiera_values['puppet_master_entry']
$proxy_line = $hiera_values['aic_env_proxy']
$site_yaml = '/etc/hiera/plugins/site.yaml'
$network_scheme = hiera_hash('network_scheme', {})
$net_bridge = $hiera_values['selective_default_bridge']
$endpoints = pick($network_scheme['endpoints'])
$endpoints_keys = keys($endpoints)
$node_nic = upcase($::macaddress_br_fw_admin)
$bond_nic = upcase($::macaddress_bond0)
$nitrous_node = find_node($nodes_array, $node_nic)
$node_name = downcase($nitrous_node['name'])
$kvm_hostname = "$node_name"
$ops_vms_array = parseyaml($hiera_values["ops_server_config"])
$initiator_config='/etc/iscsi/initiatorname.iscsi'
$storage = $nitrous_node['storage']
$luns = $storage['luns']
$storage_type = $storage['initiator_name']
$storage_array = pick($nodes_hash['storage'], [])
$target_node = $storage_array['targets']
$opsvm_pool_type = $hiera_values['selective_opsvm_pool']
$kvm_hosts = opsvm_filter($ops_vms_array, $kvm_hostname, br-fw-admin, br-mgmt)
$vlan_tag = split($stg_nm, '\.')
$vlan_id = $::nitrous::vlan_tag[1]
$nic_bond = pick($network_scheme['transformations'])
$mgmt = $nic_bond[6]
$mgmt_brg = pick($mgmt['bridge'])
$mgmt_nm = pick($mgmt['name'])
$stg = $nic_bond[7]
$stg_brg = pick($stg['bridge'])
$stg_nm = pick($stg['name'])
$prv = $nic_bond[8]
$prv_brg = pick($prv['bridge'])
$prv_nm = pick($prv['name'])
if !($proxy_line == 'undef') {
file_line { 'env_proxy':
ensure => 'present',
line => "export http_proxy=$:nitrous::proxy_line",
path => "$::nitrous::env_conf",
}
}
exec { "src_bash":
command => "bash -c 'source $env_conf'",
path => '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin',
}
file_line { 'agent_conf' :
ensure => 'present',
line => "server = $line",
path => "$agent_conf",
after => 'pluginsync = True',
}
file { "$site_yaml":
ensure => 'present',
owner => 'root',
group => 'root',
mode => '0766',
content => template('nitrous/nitrous.yaml.erb'),
}
if !($vlan_id == '') {
file { '/usr/local/bin/rm_vlan.sh':
ensure => 'present',
owner => 'root',
group => 'root',
mode => '0766',
content => template('nitrous/vlan.erb'),
}
exec { 'remove_vlan':
command => '/usr/local/bin/rm_vlan.sh',
path => '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin',
}
exec { 'add_brg':
command => "brctl addif br-mgmt bond0",
path => '/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin',
}
}
file { '/usr/bin/opsvm':
ensure => 'present',
owner => 'root',
group => 'root',
mode => '0766',
content => template('nitrous/opsvm.erb'),
}
anchor {'nitrous_begin' : } ->
Class['nitrous::packages'] ->
Class['nitrous::config'] ->
anchor {'nitrous_end' : }
}

View File

@ -0,0 +1,46 @@
# Copyright (c) 2016 AT&T 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.
define nitrous::opsvm_net (
$bridge,
$forward_mode = 'bridge',
$virtualport_type = undef,
$portgroups = [],
$autostart = true,
) {
exec {"opsvm-network-${name}":
command => join(['f=$(mktemp) && echo "',
template('nitrous/netbr.erb'),
'" > $f && virsh net-define $f && rm $f']),
provider => 'shell',
creates => "${nitrous::libvirt_conf}/qemu/networks/${name}.xml",
}
if ($autostart) {
exec {"opsvm-network-autostart-${name}":
command => "virsh net-autostart ${name}",
provider => 'shell',
creates => "${nitrous::libvirt_conf}/qemu/networks/autostart/${name}.xml",
require => Exec["opsvm-network-${name}"],
}
exec {"opsvm-network-start-${name}":
command => "virsh net-start ${name}",
provider => 'shell',
unless => "virsh net-list | tail -n +3 | cut -d ' ' -f 2 | \
grep -q ^${name}$",
require => Exec["opsvm-network-${name}"],
}
}
}

View File

@ -0,0 +1,24 @@
# Copyright (c) 2016 AT&T 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.
class nitrous::packages {
# Resources defaults
$required_pkgs = ['qemu-kvm', 'libvirt-bin', 'db-util', 'db5.3-util', 'debhelper', 'dh-apparmor', 'gettext', 'ieee-data', 'intltool-debian', 'libcroco3', 'libunistring0', 'open-iscsi', 'po-debconf', 'python-crypto', 'python-ecdsa', 'python-libvirt', 'python-markupsafe', 'python-netaddr', 'python-netifaces', 'python-paramiko', 'qemu-utils', 'sasl2-bin', 'libasprintf-dev', 'libgettextpo-dev', 'libmail-sendmail-perl', 'sharutils','virtinst', 'ebtables', 'dnsmasq', 'libpcre3', 'cloud-guest-utils', 'cloud-image-utils', 'cloud-utils', 'euca2ools', 'fabric', 'ipmitool', 'genisoimage', 'libattr1', 'libreadline6', 'libsqlite3-0','mime-support', 'module-assistant', 'openvswitch-datapath-source', 'python-ipaddr', 'python-lxml', 'python-mako','python-nose', 'python-oauth', 'python-oauthlib', 'python-pexpect', 'python-requestbuilder', 'python-requests-oauthlib', 'readline-common' ]
package { $required_pkgs :
ensure => installed
}
}

View File

@ -0,0 +1,27 @@
<%=
# Copyright (c) 2016 AT&T 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.
%>
<network>
<name><%= @name %></name>
<% if @forward_mode -%>
<forward mode='<%= @forward_mode %>'/>
<% end -%>
<% if @bridge -%>
<bridge name='<%= @bridge %>'/>
<% end -%>
<% if @virtualport_type -%>
<virtualport type='<%= @virtualport_type %>'/>
<% end -%>
</network>

View File

@ -0,0 +1,15 @@
# Copyright (c) 2016 AT&T 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.
---
<%= @nitrous_config %>

View File

@ -0,0 +1,692 @@
#!/usr/bin/env ruby
#
# Copyright (c) 2016 AT&T 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.
require 'optparse'
require 'yaml'
require 'open3'
require 'securerandom'
# Libvirt API interface functions
module LibVirt
# Delete a domain by it's name
# @param [String] domain_name
def domain_delete(domain_name)
commands = [
'virsh',
'undefine',
domain_name,
]
debug "Domain delete: #{commands.join ' '}"
_output, success = run commands
error "Failed to delete domain: #{domain_name}" unless success
success
end
# Start a domain by it's name
# @param [String] domain_name
def domain_start(domain_name)
commands = [
'virsh',
'start',
domain_name,
]
debug "Domain start: #{commands.join ' '}"
_output, success = run commands
warning "Failed to start domain: #{domain_name}" unless success
success
end
# Set autostart for a domain by it's name
# @param [String] domain_name
def domain_autostart(domain_name)
commands = [
'virsh',
'autostart',
domain_name,
]
debug "Domain autostart: #{commands.join ' '}"
_output, success = run commands
warning "Failed to autostart domain: #{domain_name}" unless success
success
end
# Unset autostart for a domain by it's name
# @param [String] domain_name
def domain_no_autostart(domain_name)
commands = [
'virsh',
'--disable',
'autostart',
domain_name,
]
debug "Domain no autostart: #{commands.join ' '}"
_output, success = run commands
warning "Failed to stop autostart domain: #{domain_name}" unless success
success
end
# Stop a domain by it's name
# @param [String] domain_name
def domain_stop(domain_name)
commands = [
'virsh',
'destroy',
domain_name,
]
debug "Domain stop: #{commands.join ' '}"
_output, success = run commands
warning "Failed to stop domain: #{domain_name}" unless success
success
end
# Get a list of all defined domains, states and ids (if running)
# @return [Hash<String => Hash>]
def domain_list
command = %w(virsh list --all)
domains = {}
output, success = run command
error 'Failed to get domain list! Is you libvirt service running?' unless success
output.split("\n").each do |line|
line_array = line.split
id = line_array[0]
name = line_array[1]
state = line_array[2..-1]
next unless id and name and state
id = id.chomp.strip
name = name.chomp.strip
state = state.join(' ').chomp.strip
next if id == 'Id'
domain_hash = {}
domain_hash['state'] = state
domain_hash['id'] = id unless id == '-'
domains[name] = domain_hash
end
domains
end
# Check if a domain is started for it's name
# @param [String] domain_name
# @return [true,false]
def domain_started?(domain_name)
domain_state(domain_name) == 'running'
end
# Get a state of a domain by it's name
# @param [String] domain_name
# @return [String]
def domain_state(domain_name)
domain_attributes = domain_list.fetch domain_name, {}
domain_attributes.fetch 'state', 'missing'
end
# Check if a domain is defined by it's name
# @param [String] domain_name
# @return [true,false]
def domain_defined?(domain_name)
domain_list.key? domain_name
end
# Create a new libvirt volume if a pool
# @param [String] volume_name
# @param [String] virt_type
# @param [String,Numeric] volume_size
# @return [true,false] success?
def volume_create(volume_name, virt_type, volume_size)
commands = [
'virsh',
'vol-create-as',
virt_type,
volume_name,
volume_size,
]
debug "Volume create: #{commands.join ' '}"
_output, success = run commands
error "Failed to create volume: #{volume_name}" unless success
success
end
# Get a path of a volume in a pool by it's name
# Returns nil if there is no such volume
# @param [String] volume_name
# @param [String] pool_name
# @return [String,nil]
def volume_path(volume_name, pool_name)
volume_list(pool_name).fetch(volume_name, nil)
end
# Delete a volume in a pool by its name
# @param [String] volume_name
# @param [String] pool_name
# @return [true,false] success?
def volume_delete(volume_name, pool_name)
commands = [
'virsh',
'vol-delete',
'--pool', pool_name,
volume_name
]
debug "Delete volume: #{commands.join ' '}"
_output, success = run commands
error "Failed to delete volume: #{volume_name}" unless success
success
end
# List all volumes in a pool
# @param [String] pool_name
# @return [Hash<String => String>] Volume name and path
def volume_list(pool_name)
commands = [
'virsh',
'vol-list',
'--pool', pool_name,
]
output, success = run commands
error "Failed to get volume list of pool: #{pool_name}!" unless success
volumes = {}
output.split("\n").each do |line|
line_array = line.split
name = line_array[0]
path = line_array[1]
next unless name and path
name = name.chomp.strip
path = path.chomp.strip
next if name == 'Name'
volumes[name] = path
end
volumes
end
# Check if a volume in a pool is defined
# @param [String] volume_name
# @param [String] pool_name
# @return [true,false]
def volume_defined?(volume_name, pool_name)
volume_list(pool_name).key? volume_name
end
# Generate a new serial for a disk
# @return [String]
def generate_disk_serial
::SecureRandom.uuid
end
# Create a new domain using it's attributes structure
# @param [String] domain_name
# @param [Hash] domain_attributes
# @return [true,false] success?
def domain_create(domain_name, domain_attributes)
name = domain_attributes.fetch 'name', domain_name
fail 'There is no domain name!' unless name
ram = domain_attributes.fetch 'ram', '1024'
cpu = domain_attributes.fetch 'cpu', '2'
volumes = domain_attributes.fetch 'volumes', {}
networks = domain_attributes.fetch 'networks', {}
commands = [
'virt-install',
'--name', name,
'--ram', ram,
'--vcpus', "#{cpu},cores=#{cpu}",
'--os-type', 'linux',
'--virt-type', options[:virt],
'--pxe',
'--boot', 'network,hd',
'--noautoconsole',
'--graphics', 'vnc,listen=0.0.0.0',
'--autostart',
]
volumes.each do |volume|
volume['serial'] = generate_disk_serial unless volume['serial']
volume['cache'] = 'none' unless volume['cache']
volume['bus'] = 'virtio' unless volume['bus']
unless volume['path']
warning "Volume: #{volume.inspect} has no path defined! Skipping!"
next
end
disk_string = volume.reject do |attribute_name, _attribute_value|
%w(size name).include? attribute_name
end.map do |attribute_name, attribute_value|
"#{attribute_name}=#{attribute_value}"
end.join ','
commands += ['--disk', disk_string]
end
networks.each do |network|
network['model'] = 'virtio' unless network['model']
unless network['network']
warning "Network: #{network.inspect} has no 'network' defined! Skipping!"
next
end
network_string = network.map do |attribute_name, attribute_value|
"#{attribute_name}=#{attribute_value}"
end.join ','
commands += ['--network', network_string]
end
debug "Domain create: #{commands.join ' '}"
_output, success = run commands
error "Failed to create the domain: #{name}" unless success
success
end
end
# Configuration and settings related functions
module Configuration
# The structure describing the domains to manage
# @return [Hash]
def domain_settings
error "There is no YAML file: #{options[:yaml]}" unless File.exists? options[:yaml]
begin
data = YAML.load_file options[:yaml]
rescue => exception
error "Could not read YAML file: #{options[:yaml]}: #{exception}"
end
error "Data format of YAML file: #{options[:yaml]} is incorrect!" unless data.is_a? Array
data
end
# Console options structure
# @return [Hash]
def options
return @options if @options
@options = {}
OptionParser.new do |opts|
opts.banner = 'opsvm [options] (domain)'
opts.on('-D', '--delete', 'Delete the created domains and volumes') do
@options[:delete] = true
end
opts.on('-R', '--recreate', 'Delete and create the domains and volumes') do
@options[:recreate] = true
end
opts.on('-s', '--stop', 'Stop all created domains') do
@options[:stop] = true
end
opts.on('-r', '--start', 'Start all created domains') do
@options[:start] = true
end
opts.on('-l', '--list', 'List the domains and volumes') do
@options[:list] = true
@options[:all] = true
end
opts.on('-c', '--config', 'Show the requested configuration of the domains and volumes') do
@options[:config] = true
end
opts.on('-a', '--all', 'Process all domains') do
@options[:all] = true
end
opts.on('-d', '--debug', 'Show debug messages') do
@options[:debug] = true
end
opts.on('-C', '--console', 'Run the debug console') do
@options[:debug] = true
@options[:console] = true
end
opts.on('-y', '--yaml FILE', 'Settings YAML file') do |value|
@options[:yaml] = value
end
opts.on('-q', '--qemu', 'Use QEMU instead of KVM') do
@options[:virt] = 'qemu'
end
opts.on('-p', '--pool POOL', 'The name of the libvirt storage pool') do |value|
@options[:pool] = value
end
end.parse!
@options
end
def munge_options
return unless options.is_a? Hash
options[:yaml] = '/etc/hiera/plugins/fuel_opsvms.yaml' unless options[:yaml]
options[:pool] = 'default' unless options[:pool]
options[:virt] = 'kvm' unless options[:virt]
options[:hosts] = ARGV.compact.uniq
unless options[:all] or (options[:hosts] and options[:hosts].any?)
error "You have to provided any hosts names to work with.
Please, give obne or more host name or use '-a' to work on all defined hosts!
Defined hosts: #{domain_names.join ', '}"
end
debug "Options: #{options.inspect}"
end
end
# Main KVM control logic class
class KvmControl
attr_writer :options
include Configuration
include LibVirt
# The filtered list of domains
# It should contain only the domains from the command line
# or all domains if the "-a" is set.
def domains
domain_settings.select do |domain|
options[:all] or options[:hosts].include? domain['name']
end
end
# Get an array of defined domain names
# @return [Array<Staring>]
def domain_names
domain_settings.map do |domain|
domain['name']
end.compact.uniq
end
# Run the debug console
def console
require 'pry'
binding.pry
exit(0)
end
# Show the configuration
def show_config
info YAML.dump domains
exit(0)
end
# The 'list' action
# Lists all domains and their statuses
def action_list
domain_statuses = domain_list
max_length = domain_names.max_by { |d| d.length }.length
domain_names.each do |domain_name|
domain_attributes = domain_statuses.fetch(domain_name, {})
domain_state = domain_attributes.fetch 'state', 'missing'
info "#{domain_name.ljust max_length} - #{domain_state}"
end
exit(0)
end
# The 'delete' action
# Stops domains and deletes volumes and domains
def action_delete
domains_stop
domains_delete
volumes_delete
end
# The 'create action'
# Creates volumes and domains,
# starts domains and marks them for autostart
def action_create
volumes_create
domains_create
domains_autostart
domains_stop
domains_start
end
# The 'recreate' action
# Calls 'delete' and 'create' actions
def action_recreate
action_delete
action_create
end
# The 'stop' action
# Stop all domains in the working set
def action_stop
domains_stop
end
# The 'start' action
# Start all domains in the working set
def action_start
domains_start
end
# Create all domains in the working set
def domains_create
debug 'Call: domains_create'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
if domain_defined? domain_name
warning "Domain: #{domain_name} is already defined! Skipping!"
next
end
resolve_volume_paths domain['volumes']
domain_create domain_name, domain
end
end
# Resolve the path of a libvirt volumes by their names
# If volume has a path already defined it will be skipped
# @param [Array] volumes
def resolve_volume_paths(volumes)
return unless volumes.is_a? Array
volumes.each do |volume|
next if volume['path']
volume['path'] = volume_path volume['name'], options[:pool]
end
end
# Create volumes for the domains in the working set
def volumes_create
domains.each do |domain|
volumes = domain.fetch 'volumes', {}
volumes.each do |volume|
volume_size = volume.fetch 'size'
volume_name = volume.fetch 'name'
next unless volume_name and volume_size
if volume_defined? volume_name, options[:pool]
warning "Volume: #{volume_name} of the pool: #{options[:pool]} is already created! Skipping!"
next
end
if volume['path']
info "Volume: #{volume_name} has a path already defined. Assuming it's already created!"
next
end
volume_create volume_name, options[:pool], volume_size
end
end
end
# Delete all volumes of domains in the working set
def volumes_delete
debug 'Call: volumes_delete'
domains.each do |domain|
volumes = domain.fetch 'volumes', {}
volumes.each do |volume|
volume_name = volume.fetch 'name'
next unless volume_name
unless volume_defined? volume_name, options[:pool]
info "Volume: #{volume_name} of the pool: #{options[:pool]} is not defined! Skipping!"
next
end
volume_delete volume_name, options[:pool]
end
end
end
# Delete all domains in the working set
def domains_delete
debug 'Call: domains_delete'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
unless domain_defined? domain_name
warning "Domain: #{domain_name} is not defined! Skipping!"
next
end
domain_delete domain_name
end
end
# Start all domains in the working set
def domains_start
debug 'Call: domains_start'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
unless domain_defined? domain_name
warning "Domain: #{domain_name} is not defined! Skipping!"
next
end
if domain_started? domain_name
warning "Domain: #{domain_name} is already started! Skipping!"
next
end
domain_start domain_name
end
end
# Unset autostart mark from all domain in the working set
def domains_no_autostart
debug 'Call: domains_no_autostart'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
unless domain_defined? domain_name
warning "Domain: #{domain_name} is not defined! Skipping!"
next
end
domain_no_autostart domain_name
end
end
# Mark all domains in the working set for autostart
def domains_autostart
debug 'Call: domains_autostart'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
unless domain_defined? domain_name
warning "Domain: #{domain_name} is not defined! Skipping!"
next
end
domain_autostart domain_name
end
end
# Stop all domains in the working set
def domains_stop
debug 'Call: domains_stop'
domains.each do |domain|
domain_name = domain.fetch 'name'
next unless domain_name
unless domain_defined? domain_name
warning "Domain: #{domain_name} is not defined! Skipping!"
next
end
unless domain_started? domain_name
warning "Domain: #{domain_name} is not started! Skipping!"
next
end
domain_stop domain_name
end
end
# Run the command
# @param [Array] commands
# @return [Array] Array of stdout and success boolean value
def run(*commands)
commands.flatten!
commands.map!(&:to_s)
out, status = Open3.capture2 *commands
[out, status.exitstatus == 0]
end
def debug(message)
$stdout.puts message if options[:debug]
end
def warning(message)
$stdout.puts "WARNING: #{message}"
end
def info(message)
$stdout.puts message
end
def error(message)
$stderr.puts "ERROR: #{message}"
exit(0)
end
# The main function
def main
munge_options
if options[:console]
console
exit(0)
end
if options[:config]
show_config
exit(0)
end
if options[:list]
action_list
end
if options[:delete]
action_delete
exit(0)
end
if options[:recreate]
action_recreate
exit(0)
end
if options[:stop]
action_stop
exit(0)
end
if options[:start]
action_start
exit(0)
end
action_create
end
end
if $0 == __FILE__
opsvm = KvmControl.new
opsvm.main
end

View File

@ -0,0 +1,40 @@
#!/bin/sh
#
# Copyright (c) 2016 AT&T 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.
brctl delif <%= @mgmt_brg %> <%= @mgmt_nm %>
if [ $? == 0 ]; then
echo "Deleted <%= @mgmt_nm %>" > /var/log/nitrous-vlan.log
vconfig rem <%= @mgmt_nm %>
if [ $? == 0 ]; then
echo "Removed <%= @mgmt_nm %>" >> /var/log/nitrous-vlan.log
fi
fi
brctl delif <%= @stg_brg %> <%= @stg_nm %>
if [ $? == 0 ]; then
echo "Deleted <%= @stg_nm %>" >> /var/log/nitrous-vlan.log
vconfig rem <%= @stg_nm %>
if [ $? == 0 ]; then
echo "Removed <%= @stg_nm %>" >> /var/log/nitrous-vlan.log
fi
fi
brctl delif <%= @prv_brg %> <%= @prv_nm %>
if [ $? == 0 ]; then
echo "Deleted <%= @prv_nm %>" >> /var/log/nitrous-vlan.log
vconfig rem <%= @prv_nm %>
if [ $? == 0 ]; then
echo "Removed <%= @prv_nm %>" >> /var/log/nitrous-vlan.log
fi
fi

49
deployment_tasks.yaml Normal file
View File

@ -0,0 +1,49 @@
# Copyright 2016 AT&T, 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.
- id: nitrous
type: group
role: [nitrous]
tasks: [hiera, globals, tools, logging, netconfig, hosts, deploy_start]
parameters:
strategy:
type: parallel
- id: nitrous-deployment-puppet
type: puppet
role: [nitrous]
version: 2.0.0
required_for: [deploy_end]
requires: [deploy_start]
parameters:
puppet_manifest: puppet/manifests/nitrous.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: nitrous-post-deployment-sh
type: shell
version: 2.0.0
role: [nitrous]
cross-depends:
- name: post_deployment_start
cross-depended-by:
- name: post_deployment_end
requires: [post_deploy_start]
required_for: [post_deploy_end]
parameters:
cmd: |
echo -e "#!/bin/sh \n\n/bin/sleep 60 && /usr/bin/opsvm -a >>/var/log/nitrous.log" > /etc/ops_create.sh && chmod +x /etc/ops_create.sh;
retries: 0
interval: 10
timeout: 120

498
environment_config.yaml Normal file
View File

@ -0,0 +1,498 @@
# Copyright 2016 AT&T, 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.
attributes:
metadata:
# Settings group can be one of "general", "security", "compute", "network",
# "storage", "logging", "openstack_services" and "other".
group: 'other'
puppet_master_address:
value: 'localhost'
label: 'Puppet master address'
description: 'This will make entry of puppet master in Nitrous nodes.'
weight: 21
type: "text"
env_proxy:
value: 'undef'
label: 'Enviornment Proxy'
description: 'Use if the server requires a proxy. The default value is "undef".'
weight: 22
type: "text"
node_additional_config:
label: "Nitrous config"
type: "textarea"
validate: "yaml"
weight: 30
value: |
webvirt: xxx.xxx.xxx.xx
dhcp_helper: xxx.xxx.xxx.11
site_name: YOUR_SITENAME
ubuntu_repo: http://archive.ubuntu.com/ubuntu/
domain_name: YOUR_DOMAIN
network:
bonds:
- bond-mode: active-backup
members:
- em1
- em2
name: bond0
vlans:
- name: 100
native: true
- bond-mode: 802.3ad
members:
- p1p1
- p1p2
- p2p1
- p2p2
mtu: '9000'
name: bond1
vlans:
- name: 101 #Management
- name: 102 #Storage
- name: 103 #Private
dhcp-ranges:
- end: 10.1.0.252
gateway: 10.1.0.1
mask: 255.255.255.255
name: rack01
start: 10.1.0.12
dns-nameservers:
- 8.8.8.8
storage:
iscsi_reservation_enabled: false
lun_mapping:
#ADD YOUR STORAGE LUN INFORMATION
storage_backend: local
storage_blacklist_enabled: true
storage_subnets:
- xxx.xx.xxx.0/24
storage_type: idc
storage_vlan: 102
targets:
- xxx.xx.xxx.xx
nodes:
- host_profile: cp-hp2
ipmi_address: xxx.xxx.xxx.1
ipmi_password: YOUR_PASSWORD
ipmi_username: YOUR_USERNAME
mac_address: xx:xx:xx:xx:xx:xx
name: svr01r01a001
power_type: ipmi
pxe_address: 10.1.0.5
pxe_subnet: rack01
server_hardware: DellR900
storage:
initiator_name: iqn.xxxx-xx.abc.abcdefg:svr01r01a001-6383eecf
luns:
#ADD YOUR STORAGE LUN INFORMATION
type: seed
vlans:
- address:
address: 10.1.0.5
gateway: 10.1.0.1
netmask: 255.255.255.255
name: 100
- address:
address: 10.1.1.5
gateway: 10.1.1.3
netmask: 255.255.255.255
name: 101
- address:
address: 10.1.2.5
gateway: 10.1.2.3
netmask: 255.255.255.255
name: 102
- address:
address: 10.1.3.5
gateway: 10.1.3.3
netmask: 255.255.255.255
name: 103
- host_profile: cp-hp2
ipmi_address: xxx.xxx.xxx.2
ipmi_password: YOUR_PASSWORD
ipmi_username: YOUR_USERNAME
mac_address: xx:xx:xx:xx:xx:xx
name: svr01r01a002
power_type: ipmi
pxe_address: 10.1.0.6
pxe_subnet: rack01
server_hardware: DellR900
storage:
initiator_name: iqn.xxxx-xx.abc.abcdefg:svr01r01a002-0bfa33c0
luns:
#ADD YOUR STORAGE LUN INFORMATION
type: lcp
vlans:
- address:
address: 10.1.0.6
gateway: 10.1.0.1
netmask: 255.255.255.255
name: 100
- address:
address: 10.1.1.6
gateway: 10.1.1.3
netmask: 255.255.255.255
name: 101
- address:
address: 10.1.2.6
gateway: 10.1.2.3
netmask: 255.255.255.255
name: 102
- address:
address: 10.1.3.6
gateway: 10.1.3.3
netmask: 255.255.255.255
name: 103
- host_profile: cp-hp2
ipmi_address: xxx.xxx.xxx.3
ipmi_password: YOUR_PASSWORD
ipmi_username: YOUR_USERNAME
mac_address: xx:xx:xx:xx:xx:xx
name: svr01r01a003
power_type: ipmi
pxe_address: 10.1.0.7
pxe_subnet: rack01
server_hardware: DellR900
storage:
initiator_name: iqn.xxxx-xx.abc.abcdefg:svr01r01a003-cab3c6a4
luns:
#ADD YOUR STORAGE LUN INFORMATION
type: lcp
vlans:
- address:
address: 10.1.0.7
gateway: 10.1.0.1
netmask: 255.255.255.255
name: 100
- address:
address: 10.1.1.7
gateway: 10.1.1.3
netmask: 255.255.255.255
name: 101
- address:
address: 10.1.2.7
gateway: 10.1.2.3
netmask: 255.255.255.255
name: 102
- address:
address: 10.1.3.7
gateway: 10.1.3.3
netmask: 255.255.255.255
name: 103
- availability_zone: null
host_profile: nv-hp1
ipmi_address: xxx.xxx.xxx.4
ipmi_password: YOUR_PASSWORD
ipmi_username: YOUR_USERNAME
mac_address: xx:xx:xx:xx:xx:xx
name: svr01r01a004
power_type: ipmi
pxe_address: 10.1.0.8
pxe_subnet: rack04
server_hardware: DellR900
storage:
initiator_name: iqn.xxxx-xx.abc.abcdefg:svr01r01a004-98c8ace6
type: compute
vlans:
- address:
address: 10.1.0.8
gateway: 10.1.0.1
netmask: 255.255.255.255
name: 100
- address:
address: 10.1.1.8
gateway: 10.1.1.3
netmask: 255.255.255.255
name: 101
- address:
address: 10.1.2.8
gateway: 10.1.2.3
netmask: 255.255.255.255
name: 102
- address:
address: 10.1.3.8
gateway: 10.1.3.3
netmask: 255.255.255.255
name: 103
image_base_path: /var/lib/libvirt/images/
host_aggregates:
- host_profiles:
- nd-hp1
- nd-hp2
meta:
- nd: true
- cpu_allocation_ratio: 1.0
name: svr01-nd-ha01
- host_profiles:
- nv-hp1
meta:
- nv: true
- cpu_allocation_ratio: 1.0
name: svr01-nv-ha01
- host_profiles:
- gv-hp1
meta:
- gv: true
- c2: true
- cpu_allocation_ratio: 2.0
name: svr01-gv-ha01
selective_default_bridge:
label: "Select network bridge for KVM Host"
description: 'Default network bridge is "Linux", select as per your requirement.'
type: "radio"
weight: 40
value: "linuxbr"
values:
- data: "linuxbr"
label: "Linux Bridge"
- data: "ovsbr"
label: "OVS Bridge"
selective_opsvm_pool:
label: "Select storage pool for OpenStack Vms"
description: 'Default pool type for OpenStack vms is directory(dir), please select storage pool type as per your equirement.'
type: "radio"
weight: 50
value: "dir"
values:
- data: "dir"
label: "Directory"
- data: "mpath"
label: "Multipath"
ops_server_config:
label: "OpenStack Vms config"
type: "textarea"
validate: "yaml"
weight: 60
value: |
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: false
is_vm: true
kvm: svr01r01a002
mac_address: 52:54:00:e5:e4:06
name: mosc01
network_profile: vm_ops-profile
os_volume_name: mpath_mosc01
ram: 32
server_type: controller
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:c2:dd:c5
name: mosc02
network_profile: vm_ops-profile
os_volume_name: mpath_mosc02
ram: 32
server_type: controller
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a002
mac_address: 52:54:00:b3:dc:b2
name: mosc03
network_profile: vm_ops-profile
os_volume_name: mpath_mosc03
ram: 32
server_type: controller
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: false
is_vm: true
kvm: svr01r01a002
mac_address: 52:54:00:3b:e5:fb
name: dbmq01
network_profile: vm_ops-profile
os_volume_name: mpath_dbmq01
ram: 32
server_type: dbmq
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:92:35:52
name: dbmq02
network_profile: vm_ops-profile
os_volume_name: mpath_dbmq02
ram: 32
server_type: dbmq
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:aa:53:25
name: dbmq03
network_profile: vm_ops-profile
os_volume_name: mpath_dbmq03
ram: 32
server_type: dbmq
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a002
mac_address: 52:54:00:7d:8c:ad
name: mong01
network_profile: vm_ops-profile
os_volume_name: mpath_mong01
ram: 32
server_type: mongo_db
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:21:5d:b3
name: mong02
network_profile: vm_ops-profile
os_volume_name: mpath_mong02
ram: 32
server_type: mongo_db
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:00:86:3e
name: mong03
network_profile: vm_ops-profile
os_volume_name: mpath_mong03
ram: 32
server_type: mongo_db
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: false
is_vm: true
kvm: svr01r01a002
mac_address: 52:54:00:f0:2b:5d
name: hapr01
network_profile: vm_ops-profile
os_volume_name: mpath_hapr01
ram: 32
server_type: haproxy
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:9a:d8:61
name: hapr02
network_profile: vm_ops-profile
os_volume_name: mpath_hapr02
ram: 32
server_type: haproxy
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a002
mac_address: 52:54:00:5c:b3:eb
name: hapr03
network_profile: vm_ops-profile
os_volume_name: mpath_hapr03
ram: 32
server_type: haproxy
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: false
is_vm: true
kvm: svr01r01a002
mac_address: 52:54:00:07:f1:bd
name: kshz01
network_profile: vm_ops-profile
os_volume_name: mpath_kshz01
ram: 32
server_type: identity
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:75:24:24
name: kshz02
network_profile: vm_ops-profile
os_volume_name: mpath_kshz02
ram: 32
server_type: identity
- app_volume_name: null
cpu: 8
app_disk: 120
log_disk: 15
os_disk: 80
ignore: true
is_vm: false
kvm: svr01r01a003
mac_address: 52:54:00:5d:08:78
name: kshz03
network_profile: vm_ops-profile
os_volume_name: mpath_kshz03
ram: 32
server_type: identity
- app_volume_name: null
cpu: 0
ignore: true
is_vm: false
kvm: xx:xx:xx:xx:xx:xx
name: svr01r01a004
network_profile: dellr900_nv-hp1
os_volume_name: null
ram: 0
server_type: compute

43
metadata.yaml Normal file
View File

@ -0,0 +1,43 @@
# Copyright 2016 AT&T, 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.
name: nitrous
title: Nitrous plugin for Bare Metal provisioning.
version: '1.0.0'
description: Nitrous plugin will install Base OS, multipath options, create VMs and their network settings for Fuel provisioning and deployment.
fuel_version: ['9.0']
licenses: ['Apache License Version 2.0']
authors: ['Dinesh Yadav (dy270k@att.com), AT&T Inc.']
homepage: 'https://github.com/openstack/fuel-plugin-nitrous'
groups: []
is_hotpluggable: false
releases:
- os: ubuntu
version: kilo-9.0
mode: ['ha', 'multinode']
deployment_scripts_path: deployment_scripts/
repository_path: repositories/ubuntu
- os: ubuntu
version: liberty-9.0
mode: ['ha', 'multinode']
deployment_scripts_path: deployment_scripts/
repository_path: repositories/ubuntu
- os: ubuntu
version: mitaka-9.0
mode: ['ha', 'multinode']
deployment_scripts_path: deployment_scripts/
repository_path: repositories/ubuntu
package_version: '4.0.0'

28
network_roles.yaml Normal file
View File

@ -0,0 +1,28 @@
# Copyright 2016 AT&T, 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.
- id: "example_net_role"
# Role mapping to network
default_mapping: "public"
properties:
# Should be true if network role requires subnet being set
subnet: true
# Should be true if network role requires gateway being set
gateway: false
# List of VIPs to be allocated
vip:
# Unique VIP name
- name: "vip_name"
# Optional linux namespace for VIP
namespace: "haproxy"

20
node_roles.yaml Normal file
View File

@ -0,0 +1,20 @@
# Copyright 2016 AT&T, 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.
nitrous:
name: Nitrous
description: Base OS installation on bare metal with KVM/QEMU/libvirt hypervisor and creates VMs for Fuel provisioning and deployment.
has_primary: false
public_ip_required: false
weight: 100

43
post_install.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
#
# Copyright (c) 2016 AT&T 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.
DEBUG=true
REL_NAME='Ubuntu 14.04'
FUEL='/usr/bin/fuel'
REL=`$FUEL rel | grep -i "${REL_NAME}.* available " | awk '{print $1}'`
FUEL_REL=`$FUEL rel | grep -i "${REL_NAME}.* available " | awk '{print $NF}'`
function debug {
if $DEBUG; then
echo $@
fi
}
function set_min_controller_count {
count=$1
workdir=$(mktemp -d /tmp/modifyenv.XXXX)
local os_roles=(ceph-osd cinder compute controller cinder-block-device ironic mongo)
for role in ${os_roles[@]}; do
$FUEL role --rel $REL --role $role --file $workdir/${role}.yaml
sed -i "s/ min: ./ min: ${count}/" $workdir/${role}.yaml
$FUEL role --rel $REL --update --file $workdir/${role}.yaml
done
rm -rf $workdir
}
set_min_controller_count 0
$FUEL rel --sync-deployment-tasks --dir /etc/puppet/$FUEL_REL

21
pre_build_hook Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
#
# Copyright 2016 AT&T, 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
# Add here any the actions which are required before plugin build
# like packages building, packages downloading from mirrors and so on.
# The script should return 0 if there were no errors.
set -eux

View File

View File

40
tasks.yaml Normal file
View File

@ -0,0 +1,40 @@
# Copyright (c) 2016 AT&T 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.
# WARNING: `tasks.yaml` will be deprecated in further releases.
# Please, use `deployment_tasks.yaml` to describe tasks instead.
# This tasks will be applied on controller nodes,
# here you can also specify several roles, for example
# ['cinder', 'compute'] will be applied only on
# cinder and compute nodes
- role: ['controller']
stage: post_deployment
type: shell
parameters:
cmd: bash deploy.sh
timeout: 42
# Task is applied for all roles
- role: '*'
stage: pre_deployment
type: shell
parameters:
cmd: echo all > /tmp/plugin.all
timeout: 42
# "reboot" task reboots the nodes and waits until they get back online
# - role: '*'
# stage: pre_deployment
# type: reboot
# parameters:
# timeout: 600

34
volumes.yaml Normal file
View File

@ -0,0 +1,34 @@
# Copyright 2016 AT&T, 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.
volumes_roles_mapping:
nitrous:
- {allocate_size: "min", id: "os"}
- {allocate_size: "min", id: "logs"}
- {allocate_size: "all", id: "nitrous"}
volumes:
- id: "nitrous"
type: "vg"
min_size:
generator: "calc_gb_to_mb"
generator_args: [10]
label: "Nitrous Vol"
volumes:
- mount: "/opt"
type: "lv"
name: "nitrous"
size:
generator: "calc_total_vg"
generator_args: ["nitrous"]
file_system: "ext4"