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:
parent
d340096b0c
commit
1964d7f9b0
@ -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",
|
||||
|
@ -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.
|
||||
|
23
drydock_provisioner/cli/const.py
Normal file
23
drydock_provisioner/cli/const.py
Normal 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'
|
@ -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
|
||||
|
@ -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':
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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))
|
||||
|
@ -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'
|
||||
|
@ -1,5 +1,6 @@
|
||||
pytest-mock
|
||||
pytest
|
||||
pytest-cov
|
||||
responses
|
||||
mock
|
||||
tox
|
||||
|
53
tests/unit/test_render_routedomain.py
Normal file
53
tests/unit/test_render_routedomain.py
Normal 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
|
77
tests/yaml_samples/deckhand_routedomain.yaml
Normal file
77
tests/yaml_samples/deckhand_routedomain.yaml
Normal 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
|
||||
...
|
501
tests/yaml_samples/hostprof.yaml
Normal file
501
tests/yaml_samples/hostprof.yaml
Normal 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
12
tox.ini
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user