Boot Action document definition
Boot actions are defined by YAML documents in the site topology. This PS defines the schema for those documents and adds a representation to the Drydock ORM and ingester. - Create JSON schema document for boot action documents - Model for BootAction objects - Parsing for BootAction documents Change-Id: I154807e8400389ff94a596ffd1fb2cab0efa128b
This commit is contained in:
parent
575e7acbb8
commit
3eac4d4d53
@ -25,6 +25,7 @@ import drydock_provisioner.objects.node as node
|
||||
import drydock_provisioner.objects.hostprofile as hostprofile
|
||||
import drydock_provisioner.objects.promenade as prom
|
||||
import drydock_provisioner.objects.rack as rack
|
||||
import drydock_provisioner.objects.bootaction as bootaction
|
||||
|
||||
|
||||
class Ingester(object):
|
||||
@ -119,4 +120,6 @@ class Ingester(object):
|
||||
design_data.add_promenade_config(m)
|
||||
elif type(m) is rack.Rack:
|
||||
design_data.add_rack(m)
|
||||
elif type(m) is bootaction.BootAction:
|
||||
design_data.add_bootaction(m)
|
||||
return status, design_data
|
||||
|
@ -382,6 +382,55 @@ class YamlIngester(IngesterPlugin):
|
||||
|
||||
return model
|
||||
|
||||
def process_drydock_bootaction(self, name, data):
|
||||
"""Process the data/spec section of a BootAction document.
|
||||
|
||||
:param name: the document name attribute
|
||||
:Param data: the dictionary of the parsed data/spec section
|
||||
"""
|
||||
model = objects.BootAction()
|
||||
model.name = name
|
||||
model.source = hd_fields.ModelSource.Designed
|
||||
|
||||
assets = data.get('assets')
|
||||
|
||||
model.asset_list = objects.BootActionAssetList()
|
||||
|
||||
for a in assets:
|
||||
ba = self.process_bootaction_asset(a)
|
||||
model.asset_list.append(ba)
|
||||
|
||||
node_filter = data.get('node_filter', None)
|
||||
|
||||
if node_filter is not None:
|
||||
nfs = self.process_bootaction_nodefilter(node_filter)
|
||||
model.node_filter = nfs
|
||||
|
||||
return model
|
||||
|
||||
def process_bootaction_asset(self, asset_dict):
|
||||
"""Process a dictionary representing a BootAction Data Asset.
|
||||
|
||||
:param asset_dict: dictionary representing the bootaction asset
|
||||
"""
|
||||
model = objects.BootActionAsset(**asset_dict)
|
||||
return model
|
||||
|
||||
def process_bootaction_nodefilter(self, nf):
|
||||
"""Process a dictionary representing a BootAction NodeFilter Set.
|
||||
|
||||
:param nf: dictionary representing the bootaction nodefilter set.
|
||||
"""
|
||||
model = objects.NodeFilterSet()
|
||||
model.filter_set_type = nf.get('filter_set_type', None)
|
||||
model.filter_set = []
|
||||
|
||||
for nf in nf.get('filter_set', []):
|
||||
nf_model = objects.NodeFilter(**nf)
|
||||
model.filter_set.append(nf_model)
|
||||
|
||||
return model
|
||||
|
||||
def process_drydock_node(self, name, data):
|
||||
"""Process the data/spec section of a BaremetalNode document.
|
||||
|
||||
@ -610,4 +659,5 @@ class YamlIngester(IngesterPlugin):
|
||||
'HardwareProfile': process_drydock_hwprofile,
|
||||
'HostProfile': process_drydock_hostprofile,
|
||||
'BaremetalNode': process_drydock_node,
|
||||
'BootAction': process_drydock_bootaction,
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ def register_all():
|
||||
importlib.import_module('drydock_provisioner.objects.site')
|
||||
importlib.import_module('drydock_provisioner.objects.promenade')
|
||||
importlib.import_module('drydock_provisioner.objects.rack')
|
||||
importlib.import_module('drydock_provisioner.objects.bootaction')
|
||||
importlib.import_module('drydock_provisioner.objects.task')
|
||||
|
||||
|
||||
|
117
drydock_provisioner/objects/bootaction.py
Normal file
117
drydock_provisioner/objects/bootaction.py
Normal file
@ -0,0 +1,117 @@
|
||||
# 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.
|
||||
"""Object models for BootActions."""
|
||||
|
||||
import oslo_versionedobjects.fields as ovo_fields
|
||||
|
||||
import drydock_provisioner.objects.base as base
|
||||
import drydock_provisioner.objects.fields as hd_fields
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class BootAction(base.DrydockPersistentObject, base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'name':
|
||||
ovo_fields.StringField(),
|
||||
'source':
|
||||
hd_fields.ModelSourceField(nullable=False),
|
||||
'asset_list':
|
||||
ovo_fields.ObjectField('BootActionAssetList', nullable=False),
|
||||
'node_filter':
|
||||
ovo_fields.ObjectField('NodeFilterSet', nullable=True),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# NetworkLink keyed by name
|
||||
def get_id(self):
|
||||
return self.get_name()
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class BootActionList(base.DrydockObjectListBase, base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objects': ovo_fields.ListOfObjectsField('BootAction'),
|
||||
}
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class BootActionAsset(base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'type': ovo_fields.StringField(nullable=True),
|
||||
'path': ovo_fields.StringField(nullable=True),
|
||||
'location': ovo_fields.StringField(nullable=True),
|
||||
'data': ovo_fields.StringField(nullable=True),
|
||||
'location_pipeline': ovo_fields.ListOfStringsField(nullable=True),
|
||||
'data_pipeline': ovo_fields.ListOfStringsField(nullable=True),
|
||||
'permissions': ovo_fields.IntegerField(nullable=True),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class BootActionAssetList(base.DrydockObjectListBase, base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'objects': ovo_fields.ListOfObjectsField('BootActionAsset'),
|
||||
}
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class NodeFilterSet(base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'filter_set_type': ovo_fields.StringField(nullable=False),
|
||||
'filter_set': ovo_fields.ListOfObjectsField('NodeFilter'),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@base.DrydockObjectRegistry.register
|
||||
class NodeFilter(base.DrydockObject):
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'filter_type': ovo_fields.StringField(nullable=False),
|
||||
'node_names': ovo_fields.ListOfStringsField(nullable=True),
|
||||
'node_tags': ovo_fields.ListOfStringsField(nullable=True),
|
||||
'node_labels': ovo_fields.DictOfStringsField(nullable=True),
|
||||
'rack_names': ovo_fields.ListOfStringsField(nullable=True),
|
||||
'rack_labels': ovo_fields.DictOfStringsField(nullable=True),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
@ -148,6 +148,8 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||
ovo_fields.ObjectField('PromenadeConfigList', nullable=True),
|
||||
'racks':
|
||||
ovo_fields.ObjectField('RackList', nullable=True),
|
||||
'bootactions':
|
||||
ovo_fields.ObjectField('BootActionList', nullable=True),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@ -218,6 +220,27 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||
raise errors.DesignError(
|
||||
"Rack %s not found in design state" % rack_key)
|
||||
|
||||
def add_bootaction(self, new_ba):
|
||||
"""Add a bootaction definition to this site design.
|
||||
|
||||
:param new_ba: instance of BootAction to add to the design
|
||||
"""
|
||||
if self.bootactions is None:
|
||||
self.bootactions = objects.BootActionList()
|
||||
|
||||
self.bootactions.append(new_ba)
|
||||
|
||||
def get_bootaction(self, ba_key):
|
||||
"""Select a boot action from this site design with the matchkey key.
|
||||
|
||||
:param ba_key: Value should match the ``get_id()`` value of the BootAction returned
|
||||
"""
|
||||
for ba in self.bootactions:
|
||||
if ba.get_id() == ba_key:
|
||||
return ba
|
||||
raise errors.DesignError(
|
||||
"BootAction %s not found in design state" % ba_key)
|
||||
|
||||
def add_host_profile(self, new_host_profile):
|
||||
if new_host_profile is None:
|
||||
raise errors.DesignError("Invalid HostProfile model")
|
||||
|
89
drydock_provisioner/schemas/bootaction.yaml
Normal file
89
drydock_provisioner/schemas/bootaction.yaml
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
schema: 'deckhand/DataSchema/v1'
|
||||
metadata:
|
||||
schema: metadata/Control/v1
|
||||
name: drydock/BootAction/v1
|
||||
labels:
|
||||
application: drydock
|
||||
data:
|
||||
$schema: 'http://json-schema.org/schema#'
|
||||
id: 'http://att.com/att-comdev/drydock/bootaction.yaml'
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
properties:
|
||||
assets:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
properties:
|
||||
path:
|
||||
type: 'string'
|
||||
pattern: '^/.+'
|
||||
location:
|
||||
type: 'string'
|
||||
type:
|
||||
type: 'string'
|
||||
enum:
|
||||
- 'unit'
|
||||
- 'file'
|
||||
- 'pkg_list'
|
||||
data:
|
||||
type: 'string'
|
||||
location_pipeline:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'string'
|
||||
enum:
|
||||
- 'template'
|
||||
data_pipeline:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'string'
|
||||
enum:
|
||||
- 'base64_encode'
|
||||
- 'template'
|
||||
- 'base64_decode'
|
||||
permissions:
|
||||
type: 'integer'
|
||||
required:
|
||||
- 'type'
|
||||
node_filter:
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
properties:
|
||||
filter_set_type:
|
||||
type: 'string'
|
||||
enum:
|
||||
- 'intersection'
|
||||
- 'union'
|
||||
filter_set:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
properties:
|
||||
filter_type:
|
||||
type: 'string'
|
||||
enum:
|
||||
- 'intersection'
|
||||
- 'union'
|
||||
node_names:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'string'
|
||||
node_tags:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'string'
|
||||
node_labels:
|
||||
type: 'object'
|
||||
additionalProperties: true
|
||||
rack_names:
|
||||
type: 'array'
|
||||
items:
|
||||
type: 'string'
|
||||
rack_labels:
|
||||
type: 'object'
|
||||
additionalProperties: true
|
||||
...
|
26
tests/yaml_samples/bootaction.yaml
Normal file
26
tests/yaml_samples/bootaction.yaml
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
apiVersion: 'drydock/v1'
|
||||
kind: BootAction
|
||||
metadata:
|
||||
name: helloworld
|
||||
region: sitename
|
||||
date: 17-FEB-2017
|
||||
author: Scott Hussey
|
||||
spec:
|
||||
assets:
|
||||
- path: /var/tmp/hello.sh
|
||||
type: file
|
||||
permissions: 555
|
||||
data: |
|
||||
IyEvYmluL2Jhc2gKCmVjaG8gJ0hlbGxvIFdvcmxkIScK
|
||||
data_pipeline:
|
||||
- base64_decode
|
||||
- path: /lib/systemd/system/hello.service
|
||||
type: unit
|
||||
data: |
|
||||
W1VuaXRdCkRlc2NyaXB0aW9uPUhlbGxvIFdvcmxkCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4
|
||||
ZWNTdGFydD0vdmFyL3RtcC9oZWxsby5zaAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIu
|
||||
dGFyZ2V0Cg==
|
||||
data_pipeline:
|
||||
- base64_decode
|
||||
...
|
18
tests/yaml_samples/invalid_bootaction.yaml
Normal file
18
tests/yaml_samples/invalid_bootaction.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
data:
|
||||
assets:
|
||||
- path: /var/tmp/hello.sh
|
||||
type: file
|
||||
permissions: 555
|
||||
data: |
|
||||
IyEvYmluL2Jhc2gKCmVjaG8gJ0hlbGxvIFdvcmxkIScK
|
||||
data_pipeline:
|
||||
- foo
|
||||
- path: hello.service
|
||||
type: unit
|
||||
data: |
|
||||
W1VuaXRdCkRlc2NyaXB0aW9uPUhlbGxvIFdvcmxkCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4
|
||||
ZWNTdGFydD0vdmFyL3RtcC9oZWxsby5zaAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIu
|
||||
dGFyZ2V0Cg==
|
||||
data_pipeline:
|
||||
- base64_decode
|
||||
|
Loading…
Reference in New Issue
Block a user