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.hostprofile as hostprofile
|
||||||
import drydock_provisioner.objects.promenade as prom
|
import drydock_provisioner.objects.promenade as prom
|
||||||
import drydock_provisioner.objects.rack as rack
|
import drydock_provisioner.objects.rack as rack
|
||||||
|
import drydock_provisioner.objects.bootaction as bootaction
|
||||||
|
|
||||||
|
|
||||||
class Ingester(object):
|
class Ingester(object):
|
||||||
|
@ -119,4 +120,6 @@ class Ingester(object):
|
||||||
design_data.add_promenade_config(m)
|
design_data.add_promenade_config(m)
|
||||||
elif type(m) is rack.Rack:
|
elif type(m) is rack.Rack:
|
||||||
design_data.add_rack(m)
|
design_data.add_rack(m)
|
||||||
|
elif type(m) is bootaction.BootAction:
|
||||||
|
design_data.add_bootaction(m)
|
||||||
return status, design_data
|
return status, design_data
|
||||||
|
|
|
@ -382,6 +382,55 @@ class YamlIngester(IngesterPlugin):
|
||||||
|
|
||||||
return model
|
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):
|
def process_drydock_node(self, name, data):
|
||||||
"""Process the data/spec section of a BaremetalNode document.
|
"""Process the data/spec section of a BaremetalNode document.
|
||||||
|
|
||||||
|
@ -610,4 +659,5 @@ class YamlIngester(IngesterPlugin):
|
||||||
'HardwareProfile': process_drydock_hwprofile,
|
'HardwareProfile': process_drydock_hwprofile,
|
||||||
'HostProfile': process_drydock_hostprofile,
|
'HostProfile': process_drydock_hostprofile,
|
||||||
'BaremetalNode': process_drydock_node,
|
'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.site')
|
||||||
importlib.import_module('drydock_provisioner.objects.promenade')
|
importlib.import_module('drydock_provisioner.objects.promenade')
|
||||||
importlib.import_module('drydock_provisioner.objects.rack')
|
importlib.import_module('drydock_provisioner.objects.rack')
|
||||||
|
importlib.import_module('drydock_provisioner.objects.bootaction')
|
||||||
importlib.import_module('drydock_provisioner.objects.task')
|
importlib.import_module('drydock_provisioner.objects.task')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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),
|
ovo_fields.ObjectField('PromenadeConfigList', nullable=True),
|
||||||
'racks':
|
'racks':
|
||||||
ovo_fields.ObjectField('RackList', nullable=True),
|
ovo_fields.ObjectField('RackList', nullable=True),
|
||||||
|
'bootactions':
|
||||||
|
ovo_fields.ObjectField('BootActionList', nullable=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
@ -218,6 +220,27 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"Rack %s not found in design state" % rack_key)
|
"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):
|
def add_host_profile(self, new_host_profile):
|
||||||
if new_host_profile is None:
|
if new_host_profile is None:
|
||||||
raise errors.DesignError("Invalid HostProfile model")
|
raise errors.DesignError("Invalid HostProfile model")
|
||||||
|
|
|
@ -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
|
||||||
|
...
|
|
@ -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
|
||||||
|
...
|
|
@ -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