OpenStack is a big distributed system. FreeIPA is designed for security in distributed system. In order to develop and test each of them, separately or together, I need a distributed system. Virtualization has been a key technology for making this kind of work possible. OpenStack is great of managing virtualization. Added to that is the benefits found when we “fly our own airplanes.” Thus, I am using OpenStack to develop OpenStack.
One of my tasks is to make it possible to easily reproduce my development environment. In the past, I would have done something like this with Bash. However, I have been coding in Python enough the past 3 years that it is as easy (if not easier) for me to think in Python than in Bash. And again, there are the benefits of actually testing and working with the OpenStack Client APIs.
In order to install Nova properly, I need two networks, a public one that connects to the outside world, and private one that Nova could manage. Each network needs a subnet, and the public subnet needs a router to connect to the public network.
For development, I need two virtual machines. One will run as the IPA Server, and one will run as the OpenStack controller (all-in-one install). In future deployments, I will need multiple controllers fronted by HA proxy, so I want a pattern that will extend.
This is a development setup, which means that I will be coding, as I do, via trial and error. I need to be able to return to a clean setup with a minimum of fuss. Not just to wipe everything, but perhaps only a teardown and recreate the hosts, or a single host, or the network.
I realized I wanted a system that ran as set of tasks. Each would run forward to create, or backwards to teardown. I wanted to be able to compose individual tasks into larger tasks and so forth.
There are many tools out there that I could have used. Ansible 2 OpenStack modules are based on the Shade library. There are other orchestration tools. However, for a small task, I want small code. The whole thing is a single python module, and is understandable in a single viewing. This is personal code, tailored to my exact inseam and sleeve length. It is easy for me to see how to modify it in the future if I want it idempotent or to handle adding random hosts to an existing network.
Well, at least that is how it started. Like most things, it has grown a bit as it is used. My whole team needs the same setups as I have. But still, this is not meant to be a shippable project, this is a software “jig” and will not be maintained after it is needed.
However, the code is worth recording. There are a couple things I feel it offers. First, it shows how to use the python-nova and python-neutron clients with a Session, getting the configuration from the command line;
@property def session(self): if not self._session: auth_plugin = ksc_auth.load_from_argparse_arguments(self.args) try: if not auth_plugin.auth_url: logging.error('OS_AUTH_URL not set. Aborting.') sys.exit(-1) except AttributeError: pass self._session = ksc_session.Session.load_from_cli_options( self.args, auth=auth_plugin) return self._session
It has examples, including the order, of the necessary Neutron commands to build a network and connect it to an external one;
As you can see here, the order is
and the reversal of the steps to tear it down:
Beyond the virtual infrastructure necessary to Run an OpenStack install, Ossipee creates a host enttry for each virtual machine, and resets the OpenSSH known_hosts entry by removing old values:
subprocess.call(['ssh-keygen', '-R', ip_address])
subprocess.check_call( ['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'PasswordAuthentication=no', '-l', self.plan.profile['cloud_user'], ip_address, 'hostname'])
Finally, it generates an Ansible inventory file that can be used with our playbooks to install IPA and OpenStack. More about them later.