OpenStack – Playing with heat patterns

My attempts to figure out OpenStack are happily producing more headaches for me. This is still on tha Matika release.

I have temporarily suspended my attempts to get migration between compute nodes working as I have been sidetracked by heat templates and stacks. Although in testing for this post I discovered some instances were being deployed on the second compute node, identified by everything starting on the second compute node complaining it cannot contact the metadata service so the vxlan setup may not be correct even tho instances can be started there, but without networking; so disabled that compute node while I play with templates. But that will be another post; this is on using a template to create a stack.

Template issues in general

The major unexpected issues in using heat templates I have encountered already are…

  • users even with admin authority to an openstack project are not permitted to create stacks with the “openstack stack create” command for the projects, it errors with ‘not heat_stack_owner’
  • the only workaround is to create a new user for the project the stack is being created for with a role of ‘heat_stack_owner’; and of course creating a new ssh key-pair for the user as a ssh key is needed to access servers created by the stack and as the stack is created by the new user that user has no access to any other keys
  • once the stack is created it seems other members of the project can manage the stack, at least other members with admin roles can delete the stack after it is created anyway

So the issue is that it seems that the use of ‘stacks’ is by design intended to be used by users seperate from the day-to-day management of instances; or basically admin users cannot create stacks and a user can have only one role so in a test environment where I am the only user I need a minimum of two userids just to do admin functions. It is just inconvenient for a single user system, but I guess in the real world there may be a need to prevent admin users from creating stacks; but personally I think the admin role should be renamed from ‘admin’ if it is not a god role to avoid confusion.

YAML syntax is a bit of a pain as well, took me about an hour to get rid of unexpected start/end block errors in my test template for ‘openstack stack create’ playtime, the solution was… I was missing a SPACE character before a parameter; indentation onto exact columns is a requirement, don’t miss out those leading spaces.

Fedora supplied cloud image (Fedora-Cloud-Base-24-1.2.x86_64)

The only other major issue encountered was not with OpenStack itself but with the Fedora supplied cloud image (Fedora-Cloud-Base-24-1.2.x86_64) for use with OpenStack. The issue there being that the F24 cloud image is shipped with python3 and the cloud-init scripts that handle user provided data to an image try to use python, so all fail to run complaining that the ‘python’ command is not found.

The fix for that is to create a symbolic link for python pointing to the phyton3 symbolic link, in a new image. Which painfully is to fire up an instance using the Fedora supplied F24 cloud image, login to it, and as root “cd /usr/bin;ln -s python3 python”; then shutdown the instance, snapshot it, use the “glance image-download” command to retrieve the snapshot as a qcow2 disk image, virt-sysprep that new qcow2 file, and use glance to install that new qcow2 file as a new image with a name meaningfull to you; and use that new image to launch future instances that require user data to be passed to them. However as while doing that you can also install additional packages to the image to make it more useful to you is not really a wasted effort.

It also does not have the “wc_notify” command so is presumably missing some heat packages in the cloud image; but that is not causing me any issues as long as I ensure I do not use that command in any of the user_data scripts.

My example template

This template is for my customised environment, all the parameters can be overidden at stack creation time. The reason the some parameters differ from the supplied users and flavours in a new openstack install are

  • as noted earlier in the post, a new user with heat_owner role was required to be created with a new keypair, so the key pair used is mark_heatstack_owner_keypair as that is a key created for that user, and the only key the user has access to
  • it uses my OpenStack network configuration, the project is my personal project so the private network is tenant-mark-10-0-3-0 with subnet tenant-mark-10-0-3-0-subnet1; and the external network available to this project is ext-net-192-flat
  • as noted earlier in the post the Fedora supplied F24 cloud image cannot process user_data passed to cloud-init, so the image used in my example is F24-CloudBase-24-1.2.x86_64-python which is a copy of the F24 image with the only change from the origional being the python link has been created so cloud-init can find python and process the user_data
  • the instance types are my customised ones, override with your own, the cloud base virtual disk needs 3Gb minimum, and has no swap partition so needs 256Mb memory minimum or 128Mb memory and a swap filesystem used in the flavor

This template example creates two instances and customises them as follows to make them usable. The idea is all access to instances in the stack are via the public ip-address on server1; in the real world there would probably be a proxy service on server1 providing passthru to other instances in the stack if the instances were to be running for more than a few days… but cloud instances are supposed to be throw up and tear down, not long running.

  • server1 is assigned a floating ip-address as well as a private ip-address, server2 only has a private ip-address; so access to the instances in the stack is via ssh key to server1
  • the root password is set for both servers (this is for troubleshooting from the console, you would not normally do that)
  • server2 has the sshd_config altered to allow login using a password instead of the default of only allowing login via ssh keys; this is to avoid having to scp/sftp to ssh keys to server1 to be able to login to server2 from server1
  • server2 has a password set for the fedora user, that can then be used when logging on from server1
  • from the dashboard stack overview page after the stack is created the outputs are ip-addreses assigned and passwords used

Filename is test_two_servers.yaml and the command to create the stack is therefore “openstack stack create –template test_two_servers.yaml mark_test_stack01”, running it with environment settings for a user with a heat_owner role. And the contents of the yaml file are below.


heat_template_version: 2016-04-08

description: >
  Test of stack deploy that sets root password,
  using my private network and a floating ip assigned.

parameters:
  key_name:
    type: string
    label: Key Name
    description: Name of key-pair to be used for compute instance
    default: mark_heatstack_owner_keypair
  image_id:
    type: string
    label: Image ID
    description: Image to be used for compute instance
    default: F24-CloudBase-24-1.2.x86_64-python
  instance_type:
    type: string
    label: Instance Type
    description: Type of instance (flavor) to be used
    default: marks.tiny
    constraints:
      - allowed_values: [ marks.tiny, marks.small, m1.tiny ]
        description: Value must be one of marks.tiny, marks.small or m1.tiny.
  root_password:
    type: string
    label: Root User Password
    description: Password to be used for root user
    hidden: true
    default: letmein
    constraints:
      - length: { min: 6, max: 8 }
        description: Password length must be between 6 and 8 characters.
      - allowed_pattern: "[a-zA-Z0-9]+"
        description: Password must consist of characters and numbers only.
  user_password:
    type: string
    label: Fedora Cloud User Password
    description: Password to be used for fedora user on servers with only private ips
    hidden: true
    default: password
    constraints:
      - length: { min: 6, max: 8 }
        description: Password length must be between 6 and 8 characters.
      - allowed_pattern: "[a-zA-Z0-9]+"
        description: Password must consist of characters and numbers only.
  net:
    description: name of network used to launch instance.
    type: string
    default: tenant-mark-10-0-3-0
  subnet:
    description: name of subnet within network used to launch instance.
    type: string
    default: tenant-mark-10-0-3-0-subnet1
  public_network:
    description: name of the public network to associate floating ip from.
    type: string
    default: ext-net-192-flat

resources:
  my_server1:
    type: OS::Nova::Server
    properties:
      name: mark-server1
      key_name: { get_param: key_name }
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      networks: 
        - network: { get_param: net }
      user_data: 
         str_replace:
            template: |
              #!/bin/bash
              echo "Customising system image..."
              # For troubleshooting use a known password for console login
              echo "$ROOTPSWD" | passwd root --stdin
              echo "...end of install"
              # wc_notify not in F24 cloud image base
              # wc_notify --data-binary '{"status": "SUCCESS"}'
              exit 0
              # ... done
            params: 
              $ROOTPSWD: { get_param: root_password }
  floating_ip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network: {get_param: public_network}
  association:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_resource: floating_ip }
      port_id: {get_attr: [my_server1, addresses, {get_param: net}, 0, port]}

  my_server2:
    type: OS::Nova::Server
    properties:
      name: mark-server2
      key_name: { get_param: key_name }
      image: { get_param: image_id }
      flavor: { get_param: instance_type }
      networks: 
        - network: { get_param: net }
      user_data: 
         str_replace:
            template: |
              #!/bin/bash
              echo "Customising system image..."
              # For troubleshooting use a known password for console login
              echo "$ROOTPSWD" | passwd root --stdin
              # Servers with only private ips can allow password logins
              # (or all the ssh keys would have to be copied to all servers
              # in the private network that might want to logon to this server).
              cd /etc/ssh
              cat sshd_config | sed -e 's/PasswordAuthentication no/PasswordAuthentication yes/' > sshd_config.new
              datenow=`date +"%Y%m%d"`
              mv sshd_config sshd_config.${datenow}
              mv sshd_config.new sshd_config
              chmod 644 sshd_config
              service sshd restart
              # But we leave "PermitRootLogin no" so set the Fedora cloud
              # user password here as that is the user they ssh keys would
              # normally be used to login to, so we can use that
              echo "$USERPSWD" | passwd fedora --stdin
              #
              echo "...end of install"
              exit 0
              # ... done
            params: 
              $ROOTPSWD: { get_param: root_password }
              $USERPSWD: { get_param: user_password }

outputs:
  instance_private_ip_server1:
    description: Private IP address of server1
    value: { get_attr: [my_server1, networks, {get_param: net}, 0] }
  instance_public_ip_server1:
    description: Public IP address of server1
    value: { get_attr: [my_server1, networks, {get_param: net}, 1] }
  instance_private_ip_server2:
    description: Private IP address of server2
    value: { get_attr: [my_server2, networks, {get_param: net}, 0] }
  instance_keypair:
    description: SSH Key-Pair to be used to access the instances
    value: { get_param: key_name }
  instance_rootpw:
    description: Root password for both servers at instance creation
    value: { get_param: root_password }
  instance_userpw:
    description: User fedora password for servers with only private ips
    value: { get_param: user_password }

top tip: for testing use the –dry-run option (ie:openstack stack create –dry-run –template test_two_servers.yaml mark_test_stack01) and that will (if the template passes validation) produce a detailed list of all settings available should you want to tweak it further.

About mark

At work, been working on Tandems for around 30yrs (programming + sysadmin), plus AIX and Solaris sysadmin also thrown in during the last 20yrs; also about 5yrs on MVS (mainly operations and automation but also smp/e work). At home I have been using linux for decades. Programming background is commercially in TAL/COBOL/SCOBOL/C(Tandem); 370 assembler(MVS); C, perl and shell scripting in *nix; and Microsoft Macro Assembler(windows).
This entry was posted in Home Life. Bookmark the permalink.