Exalogic Support
Required Reading
This will only really make sense if you have read the general Mintpress Infastructure Framework documentation
What’s Implemented
The following infrasturcture types are implemented:
-
Host/VMHost -> via the ExalogicHost provider, and the UsingExalogicHost resource class
-
Networking -> via the UsingExtraExalogicNetworkInterface sub provider
-
Block storage -> via the UsingExtraExalogicBlockDevice sub provider, as well as the UsingExalogicBlockDevice for allocations unattached to a host (this is almost never done!)
-
ZFS appliance support is provided via the mintpress-infrastructure-zfs-appliance module, but is usually used with this provider - it is accessed via the
UsingZfsPlatform
resource, and attached via theUsingExtraZfsFilesystem
. It can also be attached directly viaUsingZfsFilesystem
, which providesNasShare
resources which attach to VMHosts.
Simple example
require 'mintpress-infrastructure-oracle-exalogic'
require 'mintpress-infrastructure-zfs-appliance'
# Use our exalogic host
MintPress::InfrastructureExalogic::UsingExalogicHost.new(api_url: "http://localhost:8080",
exalogic_user: "jj",
access_key: "exa_access_key.txt",
vserver_template: "EXABASE-OEL58x86-20611-64V3",
exalogic_key_name: "exakey")
# Use the ZFS appliance platform built into the exa
MintPress::Infrastructure::UsingZfsPlatform.new(api_url: 'https://172.18.117.225:215',
username: 'root',
password: 'welcome1',
verify_ssl: false)
# Add our default network interfaces
MintPress::InfrastructureExalogic::UsingExtraExalogicNetworkInterface.new(name: "default", postfix: "", interface_type: "public", vnet: 'IpoIB_Private_32')
MintPress::InfrastructureExalogic::UsingExtraExalogicNetworkInterface.new(name: "mgt", postfix: "-mgt", interface_type: "management", vnet: 'EoIB-mgmt-32[pvid=2061]')
MintPress::InfrastructureExalogic::UsingExtraExalogicNetworkInterface.new(name: "storage", postfix: "-s", interface_type: "storage", vnet: 'IPoIB-default')
# Add a OracleVM block device for logs
MintPress::InfrastructureExalogic::UsingExtraExalogicBlockDevice.new(name: "bd1", size_mb: 40000, mount_point: "/logs")
# Add a ZFS-A nas share on foo-project, which is our /oracle disk, where we store our actual data
MintPress::Infrastructure::UsingExtraZfsFilesystem.new(name: "jjtest15-fs",
pool: 'foo',
project: 'foo-project',
size_mb: 100000,
mount_point: "/oracle")
# Create a host
my_host = MintPress::Infrastructure::VMHost.new(name: "jjtest15.limepoint-training.uk",
'specs.cpu_count': 2,
'specs.ram_gb': 4)
my_host.create
Simple Chef example
# metadata.rb
depends 'environmint-common'
depends 'mintpress-controllers-infrastructure'
depends 'mintpress-controllers-infrastructure-exalogic'
depends 'mintpress-controllers-infrastructure-zfs-appliance'
# recipe
# Use our exalogic host
using_exalogic_host 'exalogic provisioning' do
api_url 'http://localhost:8080'
exalogic_user 'jj'
access_key 'exa_access_key.txt'
vserver_template 'EXABASE-OEL58x86-20611-64V3'
exalogic_key_name 'exakey'
end
# use the ZFS appliance platform built into the exa
using_zfs_platform 'zfs-exalogic' do
api_url 'https://172.18.117.225:215'
username 'root'
password Mint::Secret.new('Welcome1')
verify_ssl false
end
# set zfs pool
infrastructure_zfs_appliance_zfs_pool 'foo'
# default node attributes for chef
node_attrs = {
useful_node_attribute: true
}
# define vm host -- don't call create yet -- we'll do that later
infrastructure_vm_host "jjtest15.limepoint-training.uk" do
native_instance_type '20_CPU_2TB_MEM'
keys ssh_keyfile
admin_keys ssh_keyfile
protocol 'ssh'
action :update_model
end
# Add our default network interfaces
infrastructure_exalogic_exalogic_network_interface "default" do
host "infrastructure_vm_host[jjtest15.limepoint-training.uk]"
postfix ''
interface_type 'public'
vnet 'IpoIB_Private_32'
end
infrastructure_exalogic_exalogic_network_interface "mgt" do
host "infrastructure_vm_host[jjtest15.limepoint-training.uk]"
postfix '-mgt'
interface_type 'management'
vnet 'EoIB-mgmt-32[pvid=2061]'
end
infrastructure_exalogic_exalogic_network_interface 'storage' do
host "infrastructure_vm_host[jjtest15.limepoint-training.uk]"
postfix '-s'
interface_type 'storage'
vnet 'IpoIB-default'
end
# storage
infrastructure_zfs_appliance_zfs_filesystem "jjtest15-fs" do
host "infrastructure_vm_host[jjtest15.limepoint-training.uk]"
platform_api_url 'https://172.18.117.225:215'
platform_verify_ssl false
name 'jjtest15-fs'
pool "infrastructure_zfs_appliance_zfs_pool[foo]"
project 'foo-project'
size_mb 100000
mount_point '/oracle'
action :create
end
# set up bootstrapper for node
infrastructure_chef_bootstrapper "jjtest15.limepoint-training.uk" do
chef_environment 'my_env'
node_attributes node_attrs
knife_config_file '/path/to/non-default/knife/config.rb'
run_list ['cookbook::recipe', 'other_cookbook::recipe']
action :nothing
end
# create vm
infrastructure_vm_host "jjtest15.limepoint-training.uk" do
bootstrapper "infrastructure_chef_bootstrapper[jjtest15.limepoint-training.uk]"
action :create
end
Advanced Chef example
# metadata.rb
depends 'environmint-common'
depends 'mintpress-controllers-infrastructure'
depends 'mintpress-controllers-infrastructure-exalogic'
depends 'mintpress-controllers-infrastructure-zfs-appliance'
# recipe
# example list of vms - just one in this case
# this will usually be passed in from another source, eg JSON file with -j chef-client option or defined in another recipe.
# defined here for demonstrative purposes.
list_of_vms = [
{
"distribution_group": "abctst_osi_dg",
"hostname": "abctstosi01.subdomain.domain.tld",
"networks": {
"mgt": {
"name": "abctst-net1",
"routes": "1.2.3.0/23"
}
},
"storage": [
{
"device": "xvdm",
"mount_point": "/zeros",
"options": "rw",
"size": 1,
"virtual_name": "zeros"
},
{
"device": "xvdn",
"mount_point": "/ones",
"options": "rw,bg",
"size": 1,
"virtual_name": "ones"
}
]
}
]
# set some variables here
ssh_keyfile = ::File.('/path/to/file/or/a/node/attribute/etc')
# sanity checking
raise 'ssh_keyfile not specified!' if ssh_keyfile.nil? || ssh_keyfile.empty?
# exalogic config
using_exalogic_host 'exalogic provisioning' do
api_url '1.2.3.4:9443'
exalogic_user 'emoc_user_1'
access_key '/path/to/emoc/access/key/file'
vserver_template 'TEMPLATE_IMAGE_7'
exalogic_key_name 'exalogic_keypair_name'
use_provided_dns true
end
# dns config
using_active_directory_dns_entry 'dns' do
account 'dns_user'
password Mint::Secret.new("dns_password")
ad_domain "ad.domain.tld"
domain_server '9.10.11.12'
zone 'not.always.the.same.as.ad_domain.tld'
end
# zfs platform config
using_zfs_platform 'exalogic' do
api_url '1.2.3.4:9443'
username 'zfs_user_1'
mount_ip '13.14.15.16'
password Mint::Secret.new('zfs_password')
verify_ssl false
end
# set zfs pool
infrastructure_zfs_appliance_zfs_pool 'my_pool'
# default zfs properties
project_props = {
'acls' => 'yes, but not too many pls',
}
# define zfs project
infrastructure_zfs_appliance_zfs_project 'zfs_project' do
pool "infrastructure_zfs_appliance_zfs_pool[my_pool]"
properties project_props
end
# loop over the assets, prepare then build them.
list_of_vms.each do |vm|
mount_map = []
# default node attributes for chef
node_attrs = {
skip_legacy_provisioning: true,
useful_node_attribute: true
}
# node runlist
runlist = ['cookbook::recipe', 'other_cookbook::recipe']
# set up bootstrapper for node
infrastructure_chef_bootstrapper (vm['name']).to_s do
chef_environment 'my_env'
node_attributes node_attrs
knife_config_file '/path/to/non-default/knife/config.rb'
run_list runlist
action :nothing
end
# define vm host -- don't call create yet -- we'll do that later
infrastructure_vm_host (vm['name']).to_s do
native_instance_type '20_CPU_2TB_MEM'
keys ssh_keyfile
admin_keys ssh_keyfile
protocol 'ssh'
action :update_model
end
# storage
vm['storage'].each do |vol|
# create volume
infrastructure_zfs_appliance_zfs_filesystem vol['name'].to_s do
host "infrastructure_vm_host[#{vm['name']}]"
platform_api_url '5.6.7.8'
platform_verify_ssl false
name vol['name']
pool "infrastructure_zfs_appliance_zfs_pool[#{'my_pool'}]"
project 'zfs_project'
size_mb (vol['size'].to_i * 1000)
mount_point vol['mount_point']
vol['options'].split(',')
action :create
end
# add to mount_map for bootstrapping
mount_map << "infrastructure_zfs_appliance_zfs_filesystem[#{vol['name']}]"
end
# networking
vm['networks'].each do |net_name, net_data|
# create network interface for each network defined
infrastructure_exalogic_exalogic_network_interface "#{vm['name']}-#{net_name}" do
host "infrastructure_vm_host[#{vm['name']}]"
postfix net_data['postfix']
interface_type net_name
routes net_data['routes']
vnet net_data['name']
end
end
# create vm
infrastructure_vm_host (vm['name']).to_s do
bootstrapper "infrastructure_chef_bootstrapper[#{vm['name']}]"
mounts mount_map
action :create
end
end
About IP Allocation
-
Warning: Please read the entire section before using this functionality, particularly the final paragraphs about the risks involved in mixing dynamic and non-dynamic IP configurations
The default behaviour of this controller is to allow the exalogic EMOC to allocate IPs. This is the safest and simplest option, since it means that that system has a complete view of which IPs are used and which are available. If you would prefer, however, you can control the IP allocation yourself directly via the ips_are_dynamic
property - if set to false
, then this will use the ip
property of the network interface resources - so in one of the above options, you’d have something that looks like this:
infrastructure_vm_host (vm['name']).to_s do
bootstrapper "infrastructure_chef_bootstrapper[#{vm['name']}]"
mounts mount_map
ips_are_dynamic false
action :create
end
infrastructure_exalogic_exalogic_network_interface "#{vm['name']}-#{net_name}" do
host "infrastructure_vm_host[#{vm['name']}]"
ips "192.168.24.42"
postfix net_data['postfix']
interface_type net_name
routes net_data['routes']
vnet net_data['name']
end
bviously, you wouldn’t usually hardcode the IP in your recipe, but you could do so if you wanted to have very specific recipes. Note that it is very important that you either (a) never use dynamic IPs on your exalogic, or (b) arrange for your IPs to be reserved on the exalogic - this can be done via the iaas-allocate-ip-addresses
, documented at docs.oracle.com/cd/E18476_01/doc.220/e25258/GUID-EC9DF55D-B21A-4607-BB5A-44C2EC835EC9.htm#ELCLD77070 if you wish to do it manually. This can also be done via the mintpress SDK:
require 'mintpress-infrastructure-oracle-exalogic'
# Obtain an exalogic client
# If you've already defined a ExalogicHost object, you can also obtain
# if via:
#
# client = exalogic_host.client
#
api_url = "FIXME"
exalogic_user = "FIXME"
access_key = "FIXME"
vnet = "MY_VNET"
client = OracleExalogic::Client.new(api_url: api_url, username: exalogic_user, access_key: access_key)
# Allocate the IP
ip = client.allocate_ip_addresses(vnet: my_vnet)
puts "Allocated ip #{ip}"
# Release the IP back into the pool
client.release_ip_addresses(vnet: my_vnet, ip_addresses: ip)
It is not recommended to do this as a part of your build pipeline, becuase there is no metadata associated with the IP addresses, and hence no way to tell if an allocated IP address is acutally used, or by whom (you could, of course, list all vservers, however this would not cover IPs which are floating for use by things such as OTD and haproxy). Additionally, there is no way to allocate a specific IP address - we have succesfully used a script that allocates IPs until you get the one you want, and then releases every IP it allocated, however this carries the risk is that if the script is somehow interrupted, again you need to work out what happened and undo it. If you require assistance with this, please contact limepoint support, as it is a high risk operation if it were to go wrong.
In particular, be aware of the following failure mode:
-
You create a box with the static ip 192.168.10.4
-
Another user create a new box, which gets the dynamic ip 192.168.10.3
-
User creates a third new box, which gets the next IP in the pool, the unallocated 192.168.10.4
-
Both your box and the users second box are kicked from the IB gateway
This is not just theoretical - it has happened to multiple clients of ours, and in one case required oracle support intervention to resolve. So it is vitally important that you either never mix these two modes of operation, or always ensure that your IPs are allocated in the exalogic before using them.