[openstack-dev] [TripleO] Network Configuration in TripleO UI

Dan Sneddon dsneddon at redhat.com
Tue Dec 13 17:15:45 UTC 2016

On 12/08/2016 08:10 PM, Jason Rist wrote:
> On 12/08/2016 05:28 PM, Dan Sneddon wrote:
>> On 12/08/2016 06:05 AM, Jiri Tomasek wrote:
>>> Hi all,
>>> I've been investigating how to implement TripleO network configuration
>>> in TripleO UI. Based on my findings I'd like to propose a solution.
>>> tl;dr proposal: Slightly refactor Network environment files to match
>>> GUI usage, Use Jinja Templating to generate dynamic parts of the
>>> templates/environments
>>> # Overview
>>> I've used Ben Nemec's amazing Network template generator as a reference
>>> to help me understand how the network configuration works [1]. In
>>> general the process of configuring the network in TripleO is:
>>> Define which Networks we intend to use -> Assign Roles to the Networks
>>> (+ Assign Role Services to the Network) -> Generate NIC config
>>> templates based on previous information
>>> # Deeper dive into templates
>>> We currently have 2 environment files in THT [2] which define network
>>> configuration:
>>> network-environment.yaml [3] - holds the information on NIC
>>> configuration for each Role using
>>> OS::TripleO::<RoleName>::Net::SoftwareConfig resource + related
>>> parameter configuration
>>> network-isolation.yaml [4]
>>> - defines the list of networks using
>>> OS::TripleO::Network::<NetworkName> resource
>>> - defines ports configuration for each network using
>>> OS::TripleO::Network::Ports::<NetworkName>VipPort (note that both
>>> resources point to the static templates - those templates don't require
>>> any manual modification)
>>> - holds  Roles - Networks assignment using
>>> OS::TripleO::<RoleName>::Ports::<NetworkName>Port for each role and
>>> storage (again, templates referenced by those resources don't require
>>> any modification)
>>> User is intended to go ahead and modify those environments and provide
>>> NIC config templates to achieve a network configuration that matches
>>> his needs.
>>> # How GUI works
>>> Before proceeding to proposed changes I need to describe briefly how
>>> TripleO UI works. TripleO UI is using THT as a source of truth, which
>>> means that it is trying not to add any additional business logic or
>>> manipulate templates. Rather it uses environment files as a 'features'
>>> which user can enable or disable depending on the needs of the
>>> deployment. The information about inter-environment relationships is
>>> tracked in capabilities-map.yaml which is also part of the THT. Based
>>> on these choices, UI allows user to configure parameters for those
>>> features. The parameter values and information about which environments
>>> are selected is stored in mistral environment. This approach leaves the
>>> plan templates intact. Huge benefit of this approach is that UI (or
>>> tripleo-common) does not need to hold explicit business logic related
>>> to certain deployment features as it is purely driven by THT. Also
>>> Adding a new feature involves only providing the templates/environments
>>> and it automatically appears as an option in UI.
>>> To achieve best user experience while using this approach, the
>>> environment files need to be defined in a granular manner, so they
>>> don't require user to modify them and each describe an isolated 'feature'.
>>> Roles and Network Configuration are exceptions to this concept as they
>>> require modification/generation of the templates/environments and
>>> therefore they use Jinja templating to achieve that.
>>> # The proposal
>>> So having described previous, here is the approach I think we should
>>> use to achieve network configuration using TripleO UI:
>>> 1. Put networks definitions into separate environment for each network:
>>> - this way GUI can provide a list of networks available to use and let
>>> user select which of them he wants to use. These environments are not
>>> dynamic and if user wants to add a new network, he does so by creating
>>> new templates and environment for it. UI also provides means to
>>> configure parameters for each network at this point (if needed).
>>> For example the environment for a Storage Network looks like this:
>>> resource_registry:
>>>   OS::TripleO::Network::Storage: ../network/storage.yaml
>>>   OS::TripleO::Network::Ports::StorageVipPort:
>>> ../network/ports/storage.yaml
>>> 2. Assign Roles to Networks
>>> Having the Networks selected as well as Roles defined, TripleO UI
>>> provides user with means to assign Roles to Networks. This step
>>> involves generating the network-environment.yaml file. So TripleO UI
>>> sends the mapping of roles to network in json format to tripleo-common
>>> which in turn uses network-isolation.j2.yaml Jinja template to generate
>>> the environment file. I expect that pre-defined network-isolation.yaml
>>> will be included in default plan so the user does not need to start
>>> from scratch. Tripleo-common also provides an action to fetch
>>> network-roles assignment data by parsing the network-isolation.yaml
>>> In addition, user is able to assign individual Role Services to a
>>> Network. ServiceNetMap parameter is currently used for this. GUI needs
>>> to make sure that it represents Services-Networks assignment grouped by
>>> Role so it is ensured that user assigns Services to only networks where
>>> their Role is assigned.
>>> 3. Generate NIC Config templates
>>> TripleO UI provides means to configure NICS, Bonds etc. for each Role,
>>> using the information from previous steps. It sends the data in json
>>> format to tripleo-common which then generates nic config templates for
>>> each Role based on network/config/nic-configs/role.j2.yaml Jinja
>>> template and generates network-environment.yaml based on
>>> network-environment.j2.yaml which references those templates.
>>> Note that network-environment.j2.yaml probably can't be combined with
>>> network-isolation.j2.yaml as every time that environment would need to
>>> get updated, all data the template needs would need to be provided.
>>> There are wireframes made by Liz Blanchard currently available [5],
>>> althought they are not exactly up to date to this proposal. Ideally
>>> whole network configuration would happen on a screen based on the
>>> graphical representation of network [6].
>>> Any comments to this proposal are very welcome, please note that I am
>>> not a networking expert so I might be missing something.
>>> There is a spec [7] in progress aimed for Ocata, but the feature will
>>> highly probably not land in Ocata, so we'll need to update the spec and
>>> move it to next cycle.
>>> [1]
>>> http://blog.nemebean.com/content/tripleo-network-isolation-template-generator
>>> [2] https://github.com/openstack/tripleo-heat-templates
>>> [3]
>>> https://github.com/openstack/tripleo-heat-templates/blob/master/environments/network-environment.yaml
>>> [4]
>>> https://github.com/openstack/tripleo-heat-templates/blob/master/environments/network-isolation.yaml
>>> [5] https://openstack.invisionapp.com/share/UM87J4NBQ#/screens/179046668
>>> [6] https://openstack.invisionapp.com/share/UM87J4NBQ#/screens/179046679
>>> [7] https://review.openstack.org/#/c/396383/
>>> Thanks
>>> Jirka
>>> __________________________________________________________________________
>>> OpenStack Development Mailing List (not for usage questions)
>>> Unsubscribe: OpenStack-dev-request at lists.openstack.org?subject:unsubscribe
>>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>> Jirka,
>> Thanks for putting this together, I think this is a great summary of
>> the issue and a good thing to discuss.
>> I have done put some thought into how we might convert the existing
>> YAML NIC config templates to Jinja. Most of the templates are pretty
>> modular if you look closely. For instance, working from the
>> bond-with-vlans templates, the bridge definition is the same for all nodes:
>>       - type: ovs_bridge
>>         name: bridge_name
>>         dns_servers:
>>           get_param: DnsServers
>>         members:
>>         - type: ovs_bond
>>           name: bond1
>>           ovs_options:
>>             get_param: BondInterfaceOvsOptions
>>           members:
>>           - type: interface
>>             name: nic2
>>             primary: true
>>           - type: interface
>>             name: nic3
>> Then, we have each of the VLANs, which can be enabled or disabled based
>> on whether a network is enabled or not on a node. For instance, the
>> external network might be defined like this:
>> {% if role.has_net_external %}
>>         - type: vlan
>>           device: bond1
>>           vlan_id:
>>             get_param: ExternalNetworkVlanID
>>           addresses:
>>           - ip_netmask:
>>               get_param: ExternalIpSubnet
>>   {% if role.default_route_network == 'external' }
>>           routes:
>>           - default: true
>>             next_hop:
>>               get_param: ExternalInterfaceDefaultRoute
>>   {% endif %}
>> {% endif %}
>> (note that there might be a better way to test for the external
>> network, consider the above psuedo-code)
>> The drawback to this approach is that we need a different template for
>> each physical configuration.
> How many are we talking?

We would probably want at least as many as we have currently:
single-nic-vlans, single-nic-linux-bridge-vlans, bond-with-vlans, and
multiple NICs.

We could add other topologies, such as two bonds, but at a certain
point I think we need to recognize that we can't cover every possible
physical topology. I think we just need to demonstrate how to create
the physical NIC config template, and the deployer can work from the
samples to develop a custom config.

>> If the controllers have more NICs than the
>> computes, then that requires a different base configuration. One
>> potential advantage to this approach is that you could even use one
>> unified template with different physical ports depending on the role.
>> For instance:
>>         - type: ovs_bond
>>           name: bond1
>>           ovs_options:
>>             get_param: BondInterfaceOvsOptions
>>           members:
>>           - type: interface
>>             name: nic2
>>             primary: true
>>           - type: interface
>>             name: nic3
>> {% if role.name == Controller %}
>>           - type: interface
>>             name: nic4
>>             primary: true
>>           - type: interface
>>             name: nic5
>> {% endif %}
>> However, the above might be a little difficult to model in a graphical
>> interface, especially if the configuration is significantly different.
>> So this would change the workflow slightly. You would first develop a
>> template that included all the possible networks that could appear in
>> that physical configuration, then enable them conditionally based on
>> which networks were assigned to each role. It would also increase the
>> complexity of developing templates by hand, but it would probably
>> still be easier to manage one or two complex template than 5 or more
>> simple configurations.
>> Since the physical template might be something that we could develop
>> automatically based on LLDP data collected during introspection, we
>> could potentially automate all parts of the configuration other than
>> customizing which networks to use where. Note that while it's easy
>> to conceptualize automatic template generation based on LLDP data
>> received from the switch, I also expect this to be pretty
>> error-prone. For instance, it may be difficult to detect which
>> interfaces should be part of a bond or bridge. Also, in cases where
>> a VLAN appears on more than one interface, it isn't easy to figure
>> out which interface Director should use for which. This could happen,
>> for instance, when the External VLAN is configured on one interface
>> for the public API, but it's also being shared on a bridge with many
>> VLANs trunked for Neutron routers.
>> [1] - https://openstack.invisionapp.com/share/UM87J4NBQ#/screens/179046679
> Dan - see above comment.
> I think the combination of Jirka's and Dan's approach seems very reasonable.
> -J

Dan Sneddon         |  Senior Principal OpenStack Engineer
dsneddon at redhat.com |  redhat.com/openstack
dsneddon:irc        |  @dxs:twitter

More information about the OpenStack-dev mailing list