Implement routedomain support

Route domains will allow multiple L3 networks
to self organize static routes. This allows additions
of L3 networks with manually updating previously deployed
networks.

- Fix a YamlIngester error with labels on NetworkLinks
- Update the CLI --block option
- Add routedomains attribue to Networks in schema and object model
- Add routedomain documentation
- Add unit test for routedomain route generation
- Add unit test coverage reporting

Change-Id: I059d2eae6da84c4f9ad909f0287432e6cf0970d0
This commit is contained in:
Scott Hussey 2017-11-15 10:27:50 -06:00
parent d340096b0c
commit 1964d7f9b0
16 changed files with 744 additions and 28 deletions

View File

@ -11,7 +11,7 @@ the task API for task status and results.
Task Document Schema
--------------------
This document can be posted to the Drydock :ref:`task-api` to create a new task.::
This document can be posted to the Drydock :ref:`tasks-api` to create a new task.::
{
"action": "validate_design|verify_site|prepare_site|verify_node|prepare_node|deploy_node|destroy_node",

View File

@ -122,6 +122,7 @@ Example YAML schema of the Network spec:
vlan: '102'
mtu: 1500
cidr: 172.16.3.0/24
routedomain: storage
ranges:
- type: static
start: 172.16.3.15
@ -133,6 +134,9 @@ Example YAML schema of the Network spec:
- subnet: 0.0.0.0/0
gateway: 172.16.3.1
metric: 10
- gateawy: 172.16.3.2
metric: 10
routedomain: storage
dns:
domain: sitename.example.com
servers: 8.8.8.8
@ -147,6 +151,11 @@ to the NetworkLink ``mtu``.
``cidr`` is the classless inter-domain routing address for the network.
``routedomain`` is a logical grouping of L3 networks such that a network that
describes a static route for accessing the route domain will yield a list of
static routes for all the networks in the routedomain. See the description
of ``routes`` below for more information.
``ranges`` defines a sequence of IP addresses within the defined ``cidr``.
Ranges cannot overlap.
@ -161,15 +170,18 @@ Ranges cannot overlap.
* ``start``: The starting IP of the range, inclusive.
* ``end``: The last IP of the range, inclusive
*NOTE: Static routes are not currently implemented beyond specifying a route for
``0.0.0.0/0`` for default route*
``routes`` defines a list of static routes to be configured on nodes attached to
this network.
this network. The routes can defined in one of two ways: an explicit destination
``subnet`` where the route will be configured exactly as described or a destination
``routedomain`` where Drydock will calculate all the destination L3 subnets for the
routedomain and add routes for each of them using the ``gateway`` and ``metric``
defined.
* ``subnet``: Destination CIDR for the route
* ``gateway``: The gateway IP on this Network to use for accessing the destination
* ``metric``: The metric or weight for this route
* ``routedomain``: Use this route's gateway and metric for accessing networks in the
defined routedomain.
``dns`` is used for specifying the list of DNS servers to use if this network
is the primary network for the node.

View File

@ -0,0 +1,23 @@
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Constants for the CLI and API client."""
from enum import Enum
class TaskStatus(Enum):
Requested = 'requested'
Queued = 'queued'
Running = 'running'
Terminating = 'terminating'
Terminated = 'terminated'
Complete = 'complete'

View File

@ -15,7 +15,7 @@
import time
from drydock_provisioner.cli.action import CliAction
from drydock_provisioner.cli.const import TaskStatus
class TaskList(CliAction): # pylint: disable=too-few-public-methods
"""Action to list tasks."""
@ -99,7 +99,7 @@ class TaskCreate(CliAction): # pylint: disable=too-few-public-methods
while True:
time.sleep(self.poll_interval)
task = self.api_client.get_task(task_id=task_id)
if task.get('status', '') in ['completed', 'terminated']:
if task.get('status', '') in [TaskStatus.Complete, TaskStatus.Terminated]:
return task
@ -134,5 +134,5 @@ class TaskShow(CliAction): # pylint: disable=too-few-public-methods
while True:
time.sleep(self.poll_interval)
task = self.api_client.get_task(task_id=task_id)
if task.status in ['completed', 'terminated']:
if task.status in [TaskStatus.Complete, TaskStatus.Terminated]:
return task

View File

@ -541,6 +541,9 @@ class CreateNetworkTemplate(BaseMaasAction):
for n in design_networks:
src_subnet = subnet_list.singleton({'cidr': n.cidr})
for r in n.routes:
# care for case of routedomain routes that are logical placeholders
if not r.get('subnet', None):
continue
route_net = r.get('subnet')
# Skip the default route case
if route_net == '0.0.0.0/0':

View File

@ -82,6 +82,7 @@ class Subnet(model_base.ResourceBase):
:param metric: weight to assign this gateway
"""
sr = maas_route.StaticRoutes(self.api_client)
sr.refresh()
current_route = sr.singleton({
'source': self.resource_id,
'destination': dest_subnet

View File

@ -286,6 +286,7 @@ class DeckhandIngester(IngesterPlugin):
model.cidr = data.get('cidr', None)
model.vlan_id = data.get('vlan', None)
model.mtu = data.get('mtu', None)
model.routedomain = data.get('routedomain', None)
dns = data.get('dns', {})
model.dns_domain = dns.get('domain', 'local')
@ -309,6 +310,7 @@ class DeckhandIngester(IngesterPlugin):
'subnet': r.get('subnet', None),
'gateway': r.get('gateway', None),
'metric': r.get('metric', None),
'routedomain': r.get('routedomain', None),
})
dhcp_relay = data.get('dhcp_relay', None)

View File

@ -246,13 +246,7 @@ class YamlIngester(IngesterPlugin):
model.source = hd_fields.ModelSource.Designed
model.name = name
metalabels = data.get('labels', [])
for l in metalabels:
if model.metalabels is None:
model.metalabels = [l]
else:
model.metalabels.append(l)
model.metalabels = data.get('labels', {})
bonding = data.get('bonding', {})
@ -289,17 +283,12 @@ class YamlIngester(IngesterPlugin):
model.source = hd_fields.ModelSource.Designed
model.name = name
metalabels = data.get('labels', [])
for l in metalabels:
if model.metalabels is None:
model.metalabels = [l]
else:
model.metalabels.append(l)
model.metalabels = data.get('labels', {})
model.cidr = data.get('cidr', None)
model.vlan_id = data.get('vlan', None)
model.mtu = data.get('mtu', None)
model.routedomain = data.get('routedomain', None)
dns = data.get('dns', {})
model.dns_domain = dns.get('domain', 'local')
@ -323,6 +312,7 @@ class YamlIngester(IngesterPlugin):
'subnet': r.get('subnet', None),
'gateway': r.get('gateway', None),
'metric': r.get('metric', None),
'routedomain': r.get('routedomain', None),
})
dhcp_relay = data.get('dhcp_relay', None)

View File

@ -88,14 +88,14 @@ class Network(base.DrydockPersistentObject, base.DrydockObject):
'site': ovo_fields.StringField(),
'metalabels': ovo_fields.DictOfNullableStringsField(),
'cidr': ovo_fields.StringField(),
'allocation_strategy': ovo_fields.StringField(),
'vlan_id': ovo_fields.StringField(nullable=True),
'routedomain': ovo_fields.StringField(nullable=True),
'mtu': ovo_fields.IntegerField(nullable=True),
'dns_domain': ovo_fields.StringField(nullable=True),
'dns_servers': ovo_fields.StringField(nullable=True),
# Keys of ranges are 'type', 'start', 'end'
'ranges': ovo_fields.ListOfDictOfNullableStringsField(),
# Keys of routes are 'subnet', 'gateway', 'metric'
# Keys of routes are 'subnet', 'routedomain', 'gateway', 'metric'
'routes': ovo_fields.ListOfDictOfNullableStringsField(),
'dhcp_relay_self_ip': ovo_fields.StringField(nullable=True),
'dhcp_relay_upstream_target': ovo_fields.StringField(nullable=True),

View File

@ -247,8 +247,12 @@ class Orchestrator(object):
Given a fully populated Site model, compute the effecitve
design by applying inheritance and references
"""
for n in getattr(site_design, 'baremetal_nodes', []):
n.compile_applied_model(site_design)
try:
nodes = site_design.baremetal_nodes
for n in nodes or []:
n.compile_applied_model(site_design)
except AttributeError:
self.logger.debug("Model inheritance skipped, no node definitions in site design.")
return
@ -281,7 +285,8 @@ class Orchestrator(object):
if status.status == hd_fields.ActionResult.Success:
self.compute_model_inheritance(site_design)
self.compute_bootaction_targets(site_design)
status = val.validate_design(site_design, result_status=status)
self.render_route_domains(site_design)
status = val.validate_design(site_design, result_status=status)
except Exception as ex:
if status is not None:
status.add_status_msg(
@ -547,3 +552,37 @@ class Orchestrator(object):
nodename, task.get_id(), identity_key, action_id, ba.name)
return identity_key
def render_route_domains(self, site_design):
"""Update site_design with static routes for route domains.
site_design will be updated in place with explicit static routes
for all routedomain members
:param site_design: a populated instance of objects.SiteDesign
"""
self.logger.info("Rendering routes for network route domains.")
if site_design.networks is not None:
routedomains = dict()
for n in site_design.networks:
if n.routedomain is not None:
if n.routedomain not in routedomains:
self.logger.info("Adding routedomain %s to render map." % n.routedomain)
routedomains[n.routedomain] = list()
routedomains[n.routedomain].append(n)
for rd, nl in routedomains.items():
rd_cidrs = [n.cidr for n in nl]
self.logger.debug("Target CIDRs for routedomain %s: %s" % (rd, ','.join(rd_cidrs)))
for n in site_design.networks:
gw = None
metric = None
for r in n.routes:
if 'routedomain' in r and r.get('routedomain', None) == rd:
gw = r.get('gateway')
metric = r.get('metric')
self.logger.debug("Use gateway %s for routedomain %s on network %s." %
(gw, rd, n.get_name()))
break
if gw is not None and metric is not None:
for cidr in rd_cidrs:
n.routes.append(dict(subnet=cidr, gateway=gw, metric=metric))

View File

@ -48,6 +48,8 @@ data:
type: 'number'
vlan:
type: 'string'
routedomain:
type: 'string'
routes:
type: 'array'
items:
@ -60,6 +62,8 @@ data:
format: 'ipv4'
metric:
type: 'number'
routedomain:
type: 'string'
additionalProperties: false
labels:
type: 'object'

View File

@ -1,5 +1,6 @@
pytest-mock
pytest
pytest-cov
responses
mock
tox

View File

@ -0,0 +1,53 @@
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from drydock_provisioner.objects import fields as hd_fields
from drydock_provisioner.ingester.ingester import Ingester
from drydock_provisioner.statemgmt.state import DrydockState
from drydock_provisioner.orchestrator.orchestrator import Orchestrator
class TestRouteDomains(object):
def test_routedomain_render(self, input_files, setup):
input_file = input_files.join("deckhand_routedomain.yaml")
design_state = DrydockState()
design_ref = "file://%s" % str(input_file)
ingester = Ingester()
ingester.enable_plugin(
'drydock_provisioner.ingester.plugins.deckhand.DeckhandIngester')
orchestrator = Orchestrator(
state_manager=design_state, ingester=ingester)
design_status, design_data = orchestrator.get_effective_site(
design_ref)
assert design_status.status == hd_fields.ActionResult.Success
net_rack3 = design_data.get_network('storage_rack3')
route_cidrs = list()
for r in net_rack3.routes:
if 'subnet' in r and r.get('subnet') is not None:
route_cidrs.append(r.get('subnet'))
assert len(route_cidrs) == 3
assert '172.16.1.0/24' in route_cidrs
assert '172.16.2.0/24' in route_cidrs
assert '172.16.3.0/24' in route_cidrs

View File

@ -0,0 +1,77 @@
#Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
schema: 'drydock/Network/v1'
metadata:
schema: 'metadata/Document/v1'
name: storage_rack1
storagePolicy: 'cleartext'
labels:
application: 'drydock'
data:
vlan: '100'
mtu: 1500
cidr: 172.16.1.0/24
routedomain: 'storage'
ranges:
- type: static
start: 172.16.1.15
end: 172.16.1.254
routes:
- routedomain: storage
gateway: 172.16.1.1
metric: 10
---
schema: 'drydock/Network/v1'
metadata:
schema: 'metadata/Document/v1'
name: storage_rack2
storagePolicy: 'cleartext'
labels:
application: 'drydock'
data:
vlan: '100'
mtu: 1500
cidr: 172.16.2.0/24
routedomain: storage
ranges:
- type: static
start: 172.16.2.15
end: 172.16.2.254
routes:
- routedomain: storage
gateway: 172.16.2.1
metric: 10
---
schema: 'drydock/Network/v1'
metadata:
schema: 'metadata/Document/v1'
name: storage_rack3
storagePolicy: 'cleartext'
labels:
application: 'drydock'
data:
vlan: '100'
mtu: 1500
cidr: 172.16.3.0/24
routedomain: 'storage'
ranges:
- type: static
start: 172.16.3.15
end: 172.16.3.254
routes:
- routedomain: storage
gateway: 172.16.3.1
metric: 10
...

View File

@ -0,0 +1,501 @@
#Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
####################
#
# bootstrap_seed.yaml - Site server design definition for physical layer
#
####################
# version the schema in this file so consumers can rationally parse it
---
apiVersion: 'drydock/v1'
kind: Region
metadata:
name: sitename
date: 17-FEB-2017
description: Sample site design
author: sh8121@att.com
spec:
tag_definitions:
- tag: test
definition_type: lshw_xpath
definition: "//node[@id=\"display\"]/'clock units=\"Hz\"' > 1000000000"
authorized_keys:
- |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDENeyO5hLPbLLQRZ0oafTYWs1ieo5Q+XgyZQs51Ju
jDGc8lKlWsg1/6yei2JewKMgcwG2Buu1eqU92Xn1SvMZLyt9GZURuBkyjcfVc/8GiU5QP1Of8B7CV0c
kfUpHWYJ17olTzT61Hgz10ioicBF6cjgQrLNcyn05xoaJHD2Vpf8Unxzi0YzA2e77yRqBo9jJVRaX2q
wUJuZrzb62x3zw8Knz6GGSZBn8xRKLaw1SKFpd1hwvL62GfqX5ZBAT1AYTZP1j8GcAoK8AFVn193SEU
vjSdUFa+RNWuJhkjBRfylJczIjTIFb5ls0jpbA3bMA9DE7lFKVQl6vVwFmiIVBI1 samplekey
---
apiVersion: 'drydock/v1'
kind: NetworkLink
metadata:
name: oob
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 1 attributes. Primary key is 'name'. These settings will generally be things the switch and server have to agree on
spec:
bonding:
mode: disabled
mtu: 1500
linkspeed: 100full
trunking:
mode: disabled
default_network: oob
allowed_networks:
- oob
---
# pxe is a bit of 'magic' indicating the link config used when PXE booting
# a node. All other links indicate network configs applied when the node
# is deployed.
apiVersion: 'drydock/v1'
kind: NetworkLink
metadata:
name: pxe
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 1 attributes. Primary key is 'name'. These settings will generally be things the switch and server have to agree on
spec:
bonding:
mode: disabled
mtu: 1500
linkspeed: auto
# Is this link supporting multiple layer 2 networks?
# none is a port-based VLAN identified by default_network
# tagged is is using 802.1q VLAN tagging. Untagged packets will default to default_netwokr
trunking:
mode: disabled
# use name, will translate to VLAN ID
default_network: pxe
allowed_networks:
- pxe
---
apiVersion: 'drydock/v1'
kind: NetworkLink
metadata:
name: gp
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 1 attributes. These CIs will generally be things the switch and server have to agree on
# pxe is a bit of 'magic' indicating the link config used when PXE booting
# a node. All other links indicate network configs applied when the node
# is deployed.
spec:
# If this link is a bond of physical links, how is it configured
# 802.3ad
# active-backup
# balance-rr
# Can add support for others down the road
bonding:
mode: 802.3ad
# For LACP (802.3ad) xmit hashing policy: layer2, layer2+3, layer3+4, encap3+4
hash: layer3+4
# 802.3ad specific options
peer_rate: slow
mtu: 9000
linkspeed: auto
# Is this link supporting multiple layer 2 networks?
trunking:
mode: 802.1q
default_network: mgmt
allowed_networks:
- public
- mgmt
---
apiVersion: 'drydock/v1'
kind: Rack
metadata:
name: rack1
region: sitename
date: 24-AUG-2017
author: sh8121@att.com
description: A equipment rack
spec:
# List of TOR switches in this rack
tor_switches:
switch01name:
mgmt_ip: 1.1.1.1
sdn_api_uri: polo+https://polo-api.web.att.com/switchmgmt?switch=switch01name
switch02name:
mgmt_ip: 1.1.1.2
sdn_api_uri: polo+https://polo-api.web.att.com/switchmgmt?switch=switch02name
# GIS data for this rack
location:
clli: HSTNTXMOCG0
grid: EG12
# Networks wholly contained to this rack
# Nodes in a rack can only connect to local_networks of that rack
local_networks:
- pxe-rack1
---
apiVersion: 'drydock/v1'
kind: Network
metadata:
name: oob
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
cidr: 172.16.100.0/24
ranges:
- type: static
start: 172.16.100.15
end: 172.16.100.254
dns:
domain: ilo.sitename.att.com
servers: 172.16.100.10
---
apiVersion: 'drydock/v1'
kind: Network
metadata:
name: pxe
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
# Layer 2 VLAN segment id, could support other segmentations. Optional
vlan_id: '99'
# If this network utilizes a dhcp relay, where does it forward DHCPDISCOVER requests to?
dhcp_relay:
# Required if Drydock is configuring a switch with the relay
self_ip: 172.16.0.4
# Can refer to a unicast IP
upstream_target: 172.16.5.5
# MTU for this VLAN interface, if not specified it will be inherited from the link
mtu: 1500
# Network address
cidr: 172.16.0.0/24
# Desribe IP address ranges
ranges:
- type: dhcp
start: 172.16.0.5
end: 172.16.0.254
# DNS settings for this network
dns:
# Domain addresses on this network will be registered under
domain: admin.sitename.att.com
# DNS servers that a server using this network as its default gateway should use
servers: 172.16.0.10
---
apiVersion: 'drydock/v1'
kind: Network
metadata:
name: mgmt
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
vlan_id: '100'
# Allow MTU to be inherited from link the network rides on
mtu: 1500
# Network address
cidr: 172.16.1.0/24
# Desribe IP address ranges
ranges:
- type: static
start: 172.16.1.15
end: 172.16.1.254
# Static routes to be added for this network
routes:
- subnet: 0.0.0.0/0
# A blank gateway would leave to a static route specifying
# only the interface as a source
gateway: 172.16.1.1
metric: 10
# DNS settings for this network
dns:
# Domain addresses on this network will be registered under
domain: mgmt.sitename.example.com
# DNS servers that a server using this network as its default gateway should use
servers: 172.16.1.9,172.16.1.10
---
apiVersion: 'drydock/v1'
kind: Network
metadata:
name: private
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
vlan_id: '101'
mtu: 9000
cidr: 172.16.2.0/24
# Desribe IP address ranges
ranges:
# Type can be reserved (not used for baremetal), static (all explicit
# assignments should fall here), dhcp (will be used by a DHCP server on this network)
- type: static
start: 172.16.2.15
end: 172.16.2.254
dns:
domain: priv.sitename.example.com
servers: 172.16.2.9,172.16.2.10
---
apiVersion: 'drydock/v1'
kind: Network
metadata:
name: public
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
vlan_id: '102'
# MTU size for the VLAN interface
mtu: 1500
cidr: 172.16.3.0/24
# Desribe IP address ranges
ranges:
- type: static
start: 172.16.3.15
end: 172.16.3.254
routes:
- subnet: 0.0.0.0/0
gateway: 172.16.3.1
metric: 10
dns:
domain: sitename.example.com
servers: 8.8.8.8
---
apiVersion: 'drydock/v1'
kind: HostProfile
metadata:
name: defaults
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
# No magic to this host_profile, it just provides a way to specify
# sitewide settings. If it is absent from a node's inheritance chain
# then these values will NOT be applied
spec:
# OOB (iLO, iDRAC, etc...) settings. Should prefer open standards such
# as IPMI over vender-specific when possible.
oob:
type: ipmi
# OOB networking should be preconfigured, but we can include a network
# definition for validation or enhancement (DNS registration)
network: oob
account: admin
credential: admin
# Specify storage layout of base OS. Ceph out of scope
storage:
# How storage should be carved up: lvm (logical volumes), flat
# (single partition)
layout: lvm
# Info specific to the boot and root disk/partitions
bootdisk:
# Device will specify an alias defined in hwdefinition.yaml
device: primary_boot
# For LVM, the size of the partition added to VG as a PV
# For flat, the size of the partition formatted as ext4
root_size: 50g
# The /boot partition. If not specified, /boot will in root
boot_size: 2g
# Info for additional partitions. Need to balance between
# flexibility and complexity
physical_devices:
name:
partitions:
name:
part_uuid:
size:
bootable:
filesystem:
mountpoint:
format:
mount_options:
fs_uuid:
fs_label:
volume_group:
logical_volumes:
name:
volume_group:
size:
lv_uuid:
filesystem:
mountpoint:
format:
mount_options:
fs_uuid:
fs_label:
# Platform (Operating System) settings
platform:
image: ubuntu_16.04
kernel: generic
kernel_params:
quiet: true
console: ttyS2
# Additional metadata to apply to a node
metadata:
# Freeform tags to be applied to the host
tags:
- deployment=initial
owner_data:
foo: bar
---
apiVersion: 'drydock/v1'
kind: HostProfile
metadata:
name: k8-node
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
# host_profile inheritance allows for deduplication of common CIs
# Inheritance is additive for CIs that are lists of multiple items
# To remove an inherited list member, prefix the primary key value
# with '!'.
host_profile: defaults
# Hardware profile will map hardware specific details to the abstract
# names uses in the host profile as well as specify hardware specific
# configs. A viable model should be to build a host profile without a
# hardware_profile and then for each node inherit the host profile and
# specify a hardware_profile to map that node's hardware to the abstract
# settings of the host_profile
hardware_profile: HPGen9v3
# Network interfaces.
primary_network: mgmt
interfaces:
# Keyed on device_name
# pxe is a special marker indicating which device should be used for pxe boot
- device_name: pxe
# The network link attached to this
device_link: pxe
# Slaves will specify aliases from hwdefinition.yaml
slaves:
- prim_nic01
# Which networks will be configured on this interface
networks:
- pxe
- device_name: bond0
network_link: gp
# If multiple slaves are specified, but no bonding config
# is applied to the link, design validation will fail
slaves:
- prim_nic01
- prim_nic02
# If multiple networks are specified, but no trunking
# config is applied to the link, design validation will fail
networks:
- mgmt
- private
metadata:
# Explicit tag assignment
tags:
- 'test'
---
apiVersion: 'drydock/v1'
kind: BaremetalNode
metadata:
name: controller01
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
host_profile: k8-node
# the hostname for a server, could be used in multiple DNS domains to
# represent different interfaces
interfaces:
- device_name: bond0
networks:
# '!' prefix for the value of the primary key indicates a record should be removed
- '!private'
# Addresses assigned to network interfaces
addressing:
# Which network the address applies to. If a network appears in addressing
# that isn't assigned to an interface, design validation will fail
- network: pxe
# The address assigned. Either a explicit IPv4 or IPv6 address
# or dhcp or slaac
address: dhcp
- network: mgmt
address: 172.16.1.20
- network: public
address: 172.16.3.20
- network: oob
address: 172.16.100.20
metadata:
rack: rack1
---
apiVersion: 'drydock/v1'
kind: BaremetalNode
metadata:
name: compute01
region: sitename
date: 17-FEB-2017
author: sh8121@att.com
description: Describe layer 2/3 attributes. Primarily CIs used for configuring server interfaces
spec:
host_profile: k8-node
addressing:
- network: pxe
address: dhcp
- network: mgmt
address: 172.16.1.21
- network: private
address: 172.16.2.21
- network: oob
address: 172.16.100.21
metadata:
rack: rack2
---
apiVersion: 'drydock/v1'
kind: HardwareProfile
metadata:
name: HPGen9v3
region: sitename
date: 17-FEB-2017
author: Scott Hussey
spec:
# Vendor of the server chassis
vendor: HP
# Generation of the chassis model
generation: '8'
# Version of the chassis model within its generation - not version of the hardware definition
hw_version: '3'
# The certified version of the chassis BIOS
bios_version: '2.2.3'
# Mode of the default boot of hardware - bios, uefi
boot_mode: bios
# Protocol of boot of the hardware - pxe, usb, hdd
bootstrap_protocol: pxe
# Which interface to use for network booting within the OOB manager, not OS device
pxe_interface: 0
# Map hardware addresses to aliases/roles to allow a mix of hardware configs
# in a site to result in a consistent configuration
device_aliases:
- address: '0000:00:03.0'
alias: prim_nic01
# type could identify expected hardware - used for hardware manifest validation
dev_type: '82540EM Gigabit Ethernet Controller'
bus_type: 'pci'
- address: '0000:00:04.0'
alias: prim_nic02
dev_type: '82540EM Gigabit Ethernet Controller'
bus_type: 'pci'
- address: '2:0.0.0'
alias: primary_boot
dev_type: 'VBOX HARDDISK'
bus_type: 'scsi'
...

12
tox.ini
View File

@ -1,5 +1,5 @@
[tox]
envlist = unit,pep8,bandit
envlist = coverage-unit,pep8,bandit
[testenv]
setenv = YAMLDIR = {toxinidir}/tests/yaml_samples/
@ -33,6 +33,16 @@ commands=
py.test \
tests/unit/{posargs}
[testenv:coverage-unit]
usedevelop=True
setenv=
PYTHONWARNING=all
YAMLDIR={toxinidir}/tests/yaml_samples/
commands=
py.test \
--cov=drydock_provisioner \
tests/unit/{posargs}
[testenv:integration]
setenv=
PYTHONWARNING=all