Create Resource
Create the Resource Project
The resource comprises 2 Apache servers defined in a HEAT template (one that uses an existing SSH key pair pre-created in Openstack, the other uses a new SSH key pair created by the HEAT template) and configured by Ansible playbooks.
Start by creating a directory for the Resource project and navigating to it
mkdir hw-apache2 && cd hw-apache2
Use LMCTL to create the basis of a Resource project
lmctl project create --type Resource --rm brent
Each resource requires a resource descriptor in YAML format that is located in the ‘Definitions/lm/resource.yaml’ file of the resource package. The format of this file is defined by the TNC-O Resource Descriptor YAML Specification.
Add Resource Descriptor
Update the Definitions/lm/resource.yaml
file with the following content:
description: descriptor for hw-apache2
properties:
server1_ssh_key:
type: key
default: apache1_server_key
description: This is the name of an existing SSH key pair in Openstack, used by apache_server1 server
server2_ssh_key_name:
description: This is the name given to a new SSH key pair generated by the HEAT template, and used by apache_server2 server
default: apache2_server_key
type: string
image_id:
default: xenial-server-cloudimg-amd64-disk1
description: Image to be used for compute instance
flavor:
default: m1.small
description: Type of instance (flavor) to be used
server1_internal_ip:
read-only: true
description: IP assigned to the apache1 server on the internal network
server1_public_ip:
read-only: true
description: IP assigned to the apache1 server to access from the external network
server2_internal_ip:
read-only: true
description: IP assigned to the apache2 server on the internal network
server2_public_ip:
read-only: true
description: IP assigned to the apache2 server to access from the external network
private-properties:
server2_ssh_key:
description: An SSH key pair created by the HEAT template, used by apache_server2 server. This will be stored in TNC-O (both the public and private key portions, the private key portion will be stored securely).
type: key
infrastructure:
Openstack: {}
lifecycle:
Create:
drivers:
openstack:
selector:
infrastructure-type:
- Openstack
Delete:
drivers:
openstack:
selector:
infrastructure-type:
- Openstack
The descriptor includes 4 input properties, each correspond to an input in our HEAT template:
server1_ssh_key
: the name of an existing SSH key (created in Openstack and stored as a shared infrastructure key in TNC-O), used when provisioning apache_server1server2_ssh_key_name
: the name to give the SSH key generated by the HEAT template and used when provisioning apache_server2image_id
: the Openstack VM image idflavor
: the Openstack VM flavor
The descriptor also includes 4 read-only properties, which correspond to outputs in our HEAT template: server1_internal_ip
, server1_public_ip
, server2_internal_ip
, server2_public_ip
. Note that server2_ssh_key
is a private property because we don’t wish to expose it outside of the resource manager (Brent).
infrastructure
defines the infrastructure type as that of Openstack. infrastructure-type
property for drivers of lifecycles can then use a wildcard value '*'
and the default resource infrastructure will be automatically registered by TNC-O.
Under lifecycle
section are 2 basic lifecycle transitions for the resource: Create and Delete. These will be handled by the Openstack VIM Driver to manage infrastructure (e.g create VMs with compute, storage and network infrastructure required on Openstack) to fulfill the resource’s function.
Note that “Openstack” under infrastructure
is the infrastructure type by default for all lifecycles, while “openstack” under lifecycle.Create.drivers
is the Resource Driver type used by a particular lifecycle.
For “Create” lifecycle, the resource driver will define the format of the templates to be used and automatically pick up suitable infrastructure template under Lifecycle/openstack
. In the next step we will create a HEAT template for this lifecycle.
Add Infrastructure
For this example, we will create a new file called openstack-heat.yaml
at Lifecycle/openstack
with the following content:
heat_template_version: "2018-08-31"
description: "Base infrastructure for an Apache2 example"
parameters:
server1_ssh_key:
type: string
label: Key Name
description: Name of an existing Openstack SSH key pair
server2_ssh_key_name:
type: string
description: Name of new Openstack SSH key pair created by the HEAT template
image_id:
type: string
label: Image ID
description: Image to be used for compute instance
flavor:
type: string
label: Instance Type
description: Type of instance (flavor) to be used
resources:
ap_security_group:
type: "OS::Neutron::SecurityGroup"
properties:
rules:
- port_range_min: 1
port_range_max: 100
protocol: tcp
- remote_ip_prefix: 0.0.0.0/0
protocol: icmp
name: ap_security_group
ap_net:
type: "OS::Neutron::Net"
properties:
admin_state_up: true
name: ap_net
ap_subnet:
type: "OS::Neutron::Subnet"
properties:
network: { get_resource: ap_net }
name: ap_subnet
enable_dhcp: true
cidr: "10.10.10.0/24"
ap_port1:
type: "OS::Neutron::Port"
properties:
admin_state_up: true
fixed_ips:
- subnet: { get_resource: ap_subnet }
security_groups:
- { get_resource: ap_security_group }
name: ap_port
network: { get_resource: ap_net }
ap_port2:
type: "OS::Neutron::Port"
properties:
admin_state_up: true
fixed_ips:
- subnet: { get_resource: ap_subnet }
security_groups:
- { get_resource: ap_security_group }
name: ap_port
network: { get_resource: ap_net }
ap_router:
type: "OS::Neutron::Router"
properties:
admin_state_up: true
name: ap_router
external_gateway_info:
network: "public"
ap_routerinterface:
type: "OS::Neutron::RouterInterface"
properties:
router: { get_resource: ap_router }
subnet: { get_resource: ap_subnet }
apache_server1_floating_ip:
type: OS::Neutron::FloatingIP
properties:
floating_network: "public"
port_id: { get_resource: ap_port1 }
apache_server2_floating_ip:
type: OS::Neutron::FloatingIP
properties:
floating_network: "public"
port_id: { get_resource: ap_port2 }
apache_server1:
type: "OS::Nova::Server"
properties:
networks:
- port: { get_resource: ap_port1 }
name: apache_server
flavor: { get_param: flavor }
key_name: { get_param: server1_ssh_key }
image: { get_param: image_id }
config_drive: true
user_data_format: RAW
user_data: |
#cloud-config
manage_etc_hosts: true
bootcmd:
- [ sysctl, net.ipv4.ip_forward=1 ]
- [ sh, -c, echo 'nameserver 8.8.8.8' > /etc/resolv.conf ]
packages:
- "python"
apache_server2:
type: "OS::Nova::Server"
properties:
networks:
- port: { get_resource: ap_port2 }
name: apache_server
flavor: { get_param: flavor }
key_name: { get_resource: server2_ssh_key }
image: { get_param: image_id }
config_drive: true
user_data_format: RAW
user_data: |
#cloud-config
manage_etc_hosts: true
bootcmd:
- [ sysctl, net.ipv4.ip_forward=1 ]
- [ sh, -c, echo 'nameserver 8.8.8.8' > /etc/resolv.conf ]
packages:
- "python"
server2_ssh_key:
type: OS::Nova::KeyPair
properties:
name: { get_param: server2_ssh_key_name }
save_private_key: True
outputs:
server1_internal_ip:
value: { get_attr: [ apache_server1 , first_address ] }
server1_public_ip:
value: { get_attr: [ apache_server1_floating_ip , floating_ip_address ] }
server2_internal_ip:
value: { get_attr: [ apache_server2 , first_address ] }
server2_public_ip:
value: { get_attr: [ apache_server2_floating_ip , floating_ip_address ] }
server2_ssh_key:
value:
str_replace:
template: $key_name#$private_key#$public_key
params:
$key_name: { get_param: [ server2_ssh_key_name ] }
$private_key: { get_attr: [ server2_ssh_key, private_key ] }
$public_key: { get_attr: [ server2_ssh_key, public_key ] }
This will create two Apache Servers running in an Openstack VM.
- apache_server1 will use an existing Openstack SSH key pair, the name of which is given by the value of the
server1_ssh_key
property (defaulted toapache1_server_key
). Note that this is defined as akey
property in the resource descriptor. TNC-O will substitute this with the real key from the shared infrastructure key pool. The value of this input property will become the TNC-O property value (in this case, the name of the infrastructure key). Two further synthetic properties will be constructed;server1_ssh_key_public
andserver1_ssh_key_private
will contain the values of the public and private keys, respectively. That is, the TNC-O key property will result in three properties being available to the driver:- [lm property]: the name of the infrastructure key
- [lm property]_public: the public portion of the infrastructure key (if present)
- [lm property]_private: the private portion of the infrastructure key (if present)
- apache_server2 will use a new SSH key pair (
server2_key
) generated by the HEAT template, the name of which will be given by the value of theserver2_ssh_key_name
property.
It will output the IP addresses of the Apache servers, along with the combined private and public portions of the apache_server2’s key as an output key
property called server2_ssh_key
. Note the structure of the server2_ssh_key
output property value; it consists of a single line containing the key name, private and public key portions (in PEM format), separated by hashes. Note also the definition of server2_ssh_key
as property of type key
in the private-properties section of the resource descriptor. This defines the property as private to Brent, with a type of key
. Note that private string
properties can be ommitted from this section (the “string” type is the default).
Next Steps
You have now created the basic files needed for a simple Resource with OpenStack infrastructure. Move on to creating a shared infrastructure key.