diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py index a15b97a488..ecd87abfca 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/certificate_shell.py @@ -11,21 +11,38 @@ import os from cgtsclient import exc from cgtsclient.common import utils +from collections import OrderedDict def _print_certificate_show(certificate): fields = ['uuid', 'certtype', 'signature', 'start_date', 'expiry_date'] if type(certificate) is dict: data = [(f, certificate.get(f, '')) for f in fields] + details = ('details', certificate.get('details', '')) else: data = [(f, getattr(certificate, f, '')) for f in fields] + details = ('details', getattr(certificate, 'details', '')) + if details[1]: + data.append(details) + utils.print_tuple_list(data) @utils.arg('certificate_uuid', metavar='', - help="UUID of certificate") + help="UUID of certificate or the reserved word 'tpm' " + "to show TPM certificate") def do_certificate_show(cc, args): """Show Certificate details.""" + if args.certificate_uuid == 'tpm': + certificates = cc.certificate.list() + for cert in certificates: + if cert.certtype == 'tpm_mode': + args.certificate_uuid = cert.uuid + break + else: + print "No TPM certificate installed" + return + certificate = cc.certificate.get(args.certificate_uuid) if certificate: _print_certificate_show(certificate) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/client.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/client.py index 0266758872..72fe75765b 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/client.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/client.py @@ -69,7 +69,6 @@ from cgtsclient.v1 import sm_servicegroup from cgtsclient.v1 import health from cgtsclient.v1 import remotelogging from cgtsclient.v1 import sdn_controller -from cgtsclient.v1 import tpmconfig from cgtsclient.v1 import firewallrules from cgtsclient.v1 import partition from cgtsclient.v1 import certificate @@ -141,7 +140,6 @@ class Client(http.HTTPClient): self.health = health.HealthManager(self) self.remotelogging = remotelogging.RemoteLoggingManager(self) self.sdn_controller = sdn_controller.SDNControllerManager(self) - self.tpmconfig = tpmconfig.TpmConfigManager(self) self.firewallrules = firewallrules.FirewallRulesManager(self) self.partition = partition.partitionManager(self) self.license = license.LicenseManager(self) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/shell.py index 1962e9b6b5..a34787d662 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/shell.py @@ -55,7 +55,6 @@ from cgtsclient.v1 import license_shell from cgtsclient.v1 import health_shell from cgtsclient.v1 import remotelogging_shell from cgtsclient.v1 import sdn_controller_shell -from cgtsclient.v1 import tpmconfig_shell from cgtsclient.v1 import firewallrules_shell from cgtsclient.v1 import partition_shell from cgtsclient.v1 import certificate_shell @@ -108,7 +107,6 @@ COMMAND_MODULES = [ health_shell, remotelogging_shell, sdn_controller_shell, - tpmconfig_shell, firewallrules_shell, partition_shell, license_shell, diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig.py deleted file mode 100644 index 94e74d07f5..0000000000 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2017 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# -*- encoding: utf-8 -*- -# - -from cgtsclient.common import base -from cgtsclient import exc - -CREATION_ATTRIBUTES = ['cert_path', 'public_path', 'tpm_path'] - - -class TpmConfig(base.Resource): - def __repr__(self): - return "" % self._info - - -class TpmConfigManager(base.Manager): - resource_class = TpmConfig - - @staticmethod - def _path(id=None): - return '/v1/tpmconfig/%s' % id if id else '/v1/tpmconfig' - - def list(self): - return self._list(self._path(), "tpmconfigs") - - def get(self, tpmconfig_id): - try: - return self._list(self._path(tpmconfig_id))[0] - except IndexError: - return None - - def create(self, **kwargs): - new = {} - for (key, value) in kwargs.items(): - if key in CREATION_ATTRIBUTES: - new[key] = value - else: - raise exc.InvalidAttribute('%s' % key) - return self._create(self._path(), new) - - def delete(self, tpmconfig_id): - return self._delete(self._path(tpmconfig_id)) - - def update(self, tpmconfig_id, patch): - return self._update(self._path(tpmconfig_id), patch) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig_shell.py deleted file mode 100644 index df09ab9f19..0000000000 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/tpmconfig_shell.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2017 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# All Rights Reserved. -# - -import argparse -import sys -import time - -from cgtsclient.common import utils -from cgtsclient import exc - - -def _print_tpmconfig_show(tpmconfig): - fields = ['uuid', - 'tpm_path', - 'created_at', - 'updated_at', - 'state', - ] - data = [(f, getattr(tpmconfig, f, '')) for f in fields] - utils.print_tuple_list(data) - -def do_tpmconfig_show(cc, args): - """Show TPM config details.""" - - tpmconfigs = cc.tpmconfig.list() - if not tpmconfigs: - return - _print_tpmconfig_show(tpmconfigs[0]) - -@utils.arg('--cert_path', - metavar='', - default=None, - help="Path to certificate to upload to TPM.") -@utils.arg('--public_path', - metavar='', - default=None, - help="Path to store public certificate.") -@utils.arg('--tpm_path', - metavar='', - default=None, - help="Path to store TPM object context") -def do_tpmconfig_add(cc, args): - """Add TPM configuration.""" - - field_list = ['cert_path', 'public_path', 'tpm_path'] - - # use field list as filter - user_specified_fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - try: - tpmconfig = cc.tpmconfig.create(**user_specified_fields) - except exc.HTTPNotFound: - raise exc.CommandError("Failed to create TPM configuration entry: " - "fields %s" % user_specified_fields) - uuid = getattr(tpmconfig, 'uuid', '') - try: - tpmconfig = cc.tpmconfig.get(uuid) - except exc.HTTPNotFound: - raise exc.CommandError("Created TPM configuration UUID not found: %s" - % uuid) - _print_tpmconfig_show(tpmconfig) - -def do_tpmconfig_delete(cc, args): - """Delete a TPM configuration.""" - try: - tpmconfigs = cc.tpmconfig.list() - if not tpmconfigs: - return - tpmconfig = tpmconfigs[0] - - cc.tpmconfig.delete(tpmconfig.uuid) - except exc.HTTPNotFound: - raise exc.CommandError("Failed to delete TPM configuration entry: " - "no configuration found") - print 'Deleted TPM configuration: uuid %s' % tpmconfig.uuid - -@utils.arg('--cert_path', - metavar='', - default=None, - help="Path to certificate to upload to TPM.") -@utils.arg('--public_path', - metavar='', - default=None, - help="Path to store public certificate.") -@utils.arg('--tpm_path', - metavar='', - default=None, - help="Path to store TPM object context") -def do_tpmconfig_modify(cc, args): - """Modify a TPM configuration.""" - # find the TPM configuration first - tpmconfig = None - try: - tpmconfigs = cc.tpmconfig.list() - if tpmconfigs: - tpmconfig = tpmconfigs[0] - - field_list = ['cert_path', 'public_path', 'tpm_path'] - # use field list as filter - user_fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - configured_fields = tpmconfig.__dict__ - configured_fields.update(user_fields) - - patch = [] - for (k,v) in user_fields.items(): - patch.append({'op': 'replace', 'path': '/' + k, 'value': v}) - try: - updated_tpmconfig = cc.tpmconfig.update(tpmconfig.uuid, patch) - except: - raise exc.CommandError("Failed to modify TPM configuration: " - "tpmconfig %s : patch %s" % - (tpmconfig.uuid, patch)) - - _print_tpmconfig_show(updated_tpmconfig) - return - except exc.HTTPNotFound: - pass - finally: - if not tpmconfig: - raise exc.CommandError("Failed to modify TPM configuration: " - "no configuration found") diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/__init__.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/__init__.py index 7db82b29c6..7f93b93d90 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/__init__.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/__init__.py @@ -75,7 +75,6 @@ from sysinv.api.controllers.v1 import storage_external from sysinv.api.controllers.v1 import storage_tier from sysinv.api.controllers.v1 import system from sysinv.api.controllers.v1 import trapdest -from sysinv.api.controllers.v1 import tpmconfig from sysinv.api.controllers.v1 import upgrade from sysinv.api.controllers.v1 import user @@ -220,9 +219,6 @@ class V1(base.APIBase): sdn_controller = [link.Link] "Links to the SDN controller resource" - tpmconfig = [link.Link] - "Links to the TPM configuration resource" - firewallrules = [link.Link] "Links to customer firewall rules" @@ -688,14 +684,6 @@ class V1(base.APIBase): bookmark=True) ] - v1.tpmconfig = [link.Link.make_link('self', - pecan.request.host_url, - 'tpmconfig', ''), - link.Link.make_link('bookmark', - pecan.request.host_url, - 'tpmconfig', '', - bookmark=True)] - v1.firewallrules = [link.Link.make_link('self', pecan.request.host_url, 'firewallrules', ''), @@ -771,7 +759,6 @@ class Controller(rest.RestController): health = health.HealthController() remotelogging = remotelogging.RemoteLoggingController() sdn_controller = sdn_controller.SDNControllerController() - tpmconfig = tpmconfig.TPMConfigController() firewallrules = firewallrules.FirewallRulesController() license = license.LicenseController() diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py index 3ebcc2ee9b..f2aea1151e 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/certificate.py @@ -84,6 +84,9 @@ class Certificate(base.APIBase): mode = wtypes.text "Represents the desired mode" + details = types.MultiType({dict}) + "Represents additional details of the certificate" + updated_at = wtypes.datetime.datetime def __init__(self, **kwargs): @@ -93,6 +96,11 @@ class Certificate(base.APIBase): continue setattr(self, k, kwargs.get(k, wtypes.Unset)) + # 'details' is not part of the object.certificate.fields + # (it is an API-only attribute) + self.fields.append('details') + setattr(self, 'details', kwargs.get('details', None)) + @classmethod def convert_with_links(cls, rpc_certificate, expand=False): certificate = Certificate(**rpc_certificate.as_dict()) @@ -101,9 +109,13 @@ class Certificate(base.APIBase): 'certtype', 'issuer', 'signature', + 'details', 'start_date', 'expiry_date']) + # insert details for this certificate if they exist + certificate = _insert_certificate_details(certificate) + certificate.links = \ [link.Link.make_link('self', pecan.request.host_url, 'certificates', certificate.uuid), @@ -146,18 +158,31 @@ def _check_certificate_data(certificate): return certificate -def _clear_existing_certificate_alarms(): - # Clear all existing CERTIFICATE configuration alarms, - # for one or both controller hosts - obj = fm_api.FaultAPIs() - - alarms = obj.get_faults_by_id(fm_constants.FM_ALARM_ID_CERTIFICATE_INIT) - if not alarms: +def _insert_certificate_details(certificate): + if not certificate: return - for alarm in alarms: - obj.clear_fault( - fm_constants.FM_ALARM_ID_CERTIFICATE_INIT, - alarm.entity_instance_id) + + if certificate.certtype == constants.CERT_MODE_TPM: + try: + tpmconfig = pecan.request.dbapi.tpmconfig_get_one() + except exception.NotFound: + return certificate + + tpmdevices = pecan.request.dbapi.tpmdevice_get_list() + certificate.details = {} + states = {} + for device in tpmdevices: + # extract the state info per host + ihost = pecan.request.dbapi.ihost_get(device['host_id']) + if ihost: + states[ihost.hostname] = device.state + if tpmdevices: + certificate.details['state'] = states + if tpmconfig.updated_at: + certificate.details['updated_at'] = \ + tpmconfig.updated_at.isoformat() + + return certificate LOCK_NAME = 'CertificateController' @@ -251,7 +276,14 @@ class CertificateController(rest.RestController): fileitem = pecan.request.POST['file'] passphrase = pecan.request.POST.get('passphrase') mode = pecan.request.POST.get('mode') + certificate_file = pecan.request.POST.get('certificate_file') + # Ensure that the certificate_file is a valid file path + if os.path.isabs(certificate_file): + if not os.path.isfile(certificate_file): + msg = "'certificate_file' is not a valid file path" + LOG.info(msg) + return dict(success="", error=msg) LOG.info("certificate %s mode=%s" % (log_start, mode)) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/tpmconfig.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/tpmconfig.py deleted file mode 100644 index 67c391401e..0000000000 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/tpmconfig.py +++ /dev/null @@ -1,386 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# -# Copyright 2013 UnitedStack Inc. -# All 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. -# -# Copyright (c) 2013-2017 Wind River Systems, Inc. -# - -import jsonpatch -import os - -import pecan -from pecan import rest - -import wsme -from wsme import types as wtypes -import wsmeext.pecan as wsme_pecan - -from sysinv.api.controllers.v1 import base -from sysinv.api.controllers.v1 import collection -from sysinv.api.controllers.v1 import link -from sysinv.api.controllers.v1 import types -from sysinv.api.controllers.v1 import utils -from sysinv.common import constants -from sysinv.common import exception -from sysinv.common import utils as cutils -from sysinv import objects -from sysinv.openstack.common import excutils -from sysinv.openstack.common.gettextutils import _ -from sysinv.openstack.common import log - -from fm_api import constants as fm_constants -from fm_api import fm_api - -LOG = log.getLogger(__name__) - - -class TPMConfigPatchType(types.JsonPatchType): - @staticmethod - def mandatory_attrs(): - return [] - - -class TPMConfig(base.APIBase): - """API representation of TPM Configuration. - - This class enforces type checking and value constraints, and converts - between the internal object model and the API representation of - an tpmconfig. - """ - - uuid = types.uuid - "Unique UUID for this tpmconfig" - - cert_path = wtypes.text - "Represents the path of the SSL certificate to be stored in TPM" - - public_path = wtypes.text - "Represents the path of the SSL public key" - - tpm_path = wtypes.text - "Represents the path to store TPM certificate" - - state = types.MultiType({dict}) - "Represents the state of the TPM config" - - links = [link.Link] - "A list containing a self link and associated tpmconfig links" - - created_at = wtypes.datetime.datetime - updated_at = wtypes.datetime.datetime - - def __init__(self, **kwargs): - self.fields = objects.tpmconfig.fields.keys() - for k in self.fields: - setattr(self, k, kwargs.get(k)) - - # 'cert_path' and 'public_path' are - # not part of objects.tpmconfig.fields - # (they are an API-only attribute) - for fp in ['cert_path', 'public_path']: - self.fields.append(fp) - setattr(self, fp, kwargs.get(fp, None)) - - # 'state' is not part of objects.tpmconfig.fields - # (it is an API-only attribute) - self.fields.append('state') - setattr(self, 'state', kwargs.get('state', None)) - - @classmethod - def convert_with_links(cls, rpc_tpmconfig, expand=True): - - tpm = TPMConfig(**rpc_tpmconfig.as_dict()) - if not expand: - tpm.unset_fields_except(['uuid', - 'cert_path', - 'public_path', - 'tpm_path', - 'state', - 'created_at', - 'updated_at']) - # insert state - tpm = _insert_tpmdevices_state(tpm) - - tpm.links = [link.Link.make_link('self', pecan.request.host_url, - 'tpmconfigs', tpm.uuid), - link.Link.make_link('bookmark', pecan.request.host_url, - 'tpmconfigs', tpm.uuid, - bookmark=True)] - - return tpm - - -class TPMConfigCollection(collection.Collection): - """API representation of a collection of tpmconfigs.""" - - tpmconfigs = [TPMConfig] - "A list containing tpmconfig objects" - - def __init__(self, **kwargs): - self._type = 'tpmconfigs' - - @classmethod - def convert_with_links(cls, rpc_tpmconfigs, limit, url=None, - expand=False, **kwargs): - collection = TPMConfigCollection() - collection.tpmconfigs = [TPMConfig.convert_with_links(p, expand) - for p in rpc_tpmconfigs] - collection.next = collection.get_next(limit, url=url, **kwargs) - return collection - - -############## -# UTILS -############## - -def _check_tpmconfig_data(tpmconfig): - - if not utils.get_https_enabled(): - raise wsme.exc.ClientSideError( - _("Cannot configure TPM without HTTPS mode being enabled")) - - if not tpmconfig.get('cert_path', None): - raise wsme.exc.ClientSideError( - _("Cannot configure TPM without cert_path provided")) - - if not tpmconfig.get('public_path', None): - raise wsme.exc.ClientSideError( - _("Cannot configure TPM without public_path provided")) - - if not tpmconfig.get('tpm_path', None): - raise wsme.exc.ClientSideError( - _("Cannot configure TPM without tpm_path provided")) - - # validate the key paths - values = [tpmconfig['cert_path'], - tpmconfig['tpm_path'], - tpmconfig['public_path']] - - for i, item in enumerate(values): - # ensure valid paths - if os.path.isabs(item): - if i == 0: - # ensure key exists - if not os.path.isfile(item): - raise wsme.exc.ClientSideError(_( - "Cert path is not a valid existing file")) - else: - raise wsme.exc.ClientSideError(_( - "TPM configuration arguments must be file paths")) - return tpmconfig - - -def _clear_existing_tpmconfig_alarms(): - # Clear all existing TPM configuration alarms, - # for one or both controller hosts - obj = fm_api.FaultAPIs() - - alarms = obj.get_faults_by_id( - fm_constants.FM_ALARM_ID_TPM_INIT) - if not alarms: - return - for alarm in alarms: - obj.clear_fault( - fm_constants.FM_ALARM_ID_TPM_INIT, - alarm.entity_instance_id) - - -def _insert_tpmdevices_state(tpmconfig): - # update the tpmconfig state with the per host - # tpmdevice state - if not tpmconfig: - return - tpmdevices = pecan.request.dbapi.tpmdevice_get_list() - tpmconfig.state = {} - for device in tpmdevices: - # extract the state info per host - ihost = pecan.request.dbapi.ihost_get(device['host_id']) - if ihost: - tpmconfig.state[ihost.hostname] = device.state - return tpmconfig - - -class TPMConfigController(rest.RestController): - """REST controller for tpmconfigs.""" - - def __init__(self, parent=None, **kwargs): - self._parent = parent - - def _get_tpmconfigs_collection(self, uuid, marker, limit, - sort_key, sort_dir, expand=False, - resource_url=None): - - limit = utils.validate_limit(limit) - sort_dir = utils.validate_sort_dir(sort_dir) - - marker_obj = None - if marker: - marker_obj = objects.tpmconfig.get_by_uuid(pecan.request.context, - marker) - - tpms = pecan.request.dbapi.tpmconfig_get_list(limit, - marker_obj, - sort_key=sort_key, - sort_dir=sort_dir) - - return TPMConfigCollection.convert_with_links(tpms, limit, - url=resource_url, - expand=expand, - sort_key=sort_key, - sort_dir=sort_dir) - - def _get_updates(self, patch): - """Retrieve the updated attributes from the patch request.""" - updates = {} - for p in patch: - attribute = p['path'] if p['path'][0] != '/' else p['path'][1:] - updates[attribute] = p['value'] - return updates - - @wsme_pecan.wsexpose(TPMConfigCollection, types.uuid, types.uuid, int, - wtypes.text, wtypes.text) - def get_all(self, uuid=None, marker=None, limit=None, - sort_key='id', sort_dir='asc'): - """Retrieve a list of tpmconfigs. Only one per system""" - return self._get_tpmconfigs_collection(uuid, marker, limit, - sort_key, sort_dir) - - @wsme_pecan.wsexpose(TPMConfig, types.uuid) - def get_one(self, tpmconfig_uuid): - """Retrieve information about the given tpmconfig.""" - rpc_tpmconfig = objects.tpmconfig.get_by_uuid(pecan.request.context, - tpmconfig_uuid) - return TPMConfig.convert_with_links(rpc_tpmconfig) - - @wsme_pecan.wsexpose(TPMConfig, body=TPMConfig) - def post(self, tpmconfig): - """Create a new tpmconfig.""" - # There must not already be an existing tpm config - try: - tpm = pecan.request.dbapi.tpmconfig_get_one() - except exception.NotFound: - pass - else: - raise wsme.exc.ClientSideError(_( - "tpmconfig rejected: A TPM configuration already exists.")) - - _check_tpmconfig_data(tpmconfig.as_dict()) - try: - new_tpmconfig = pecan.request.dbapi.tpmconfig_create( - tpmconfig.as_dict()) - except exception.SysinvException as e: - LOG.exception(e) - raise wsme.exc.ClientSideError(_("Invalid data: failed to create " - "a tpm config record.")) - - # apply TPM configuration via agent RPCs - try: - pecan.request.rpcapi.update_tpm_config( - pecan.request.context, - tpmconfig.as_dict()) - - pecan.request.rpcapi.update_tpm_config_manifests( - pecan.request.context) - except Exception as e: - with excutils.save_and_reraise_exception(): - LOG.exception(e) - - return tpmconfig.convert_with_links(new_tpmconfig) - - @wsme.validate(types.uuid, [TPMConfigPatchType]) - @wsme_pecan.wsexpose(TPMConfig, types.uuid, - body=[TPMConfigPatchType]) - def patch(self, tpmconfig_uuid, patch): - """Update the current tpm configuration.""" - - tpmconfig = objects.tpmconfig.get_by_uuid(pecan.request.context, - tpmconfig_uuid) - tpmdevices = pecan.request.dbapi.tpmdevice_get_list() - - # if any of the tpm devices are in APPLYING state - # then disallow a modification till previous config - # either applies or fails - for device in tpmdevices: - if device.state == constants.TPMCONFIG_APPLYING: - raise wsme.exc.ClientSideError(_("TPM Device %s is still " - "in APPLYING state. Wait for the configuration " - "to finish before attempting a modification." % - device.uuid)) - - # get attributes to be updated - updates = self._get_updates(patch) - - # before we can update we have do a quick semantic check - if 'uuid' in updates: - raise wsme.exc.ClientSideError(_("uuid cannot be modified")) - - _check_tpmconfig_data(updates) - - # update only DB fields that have changed - # we cannot use the entire set of updates - # since some of them are API updates only - for field in objects.tpmconfig.fields: - if updates.get(field, None): - tpmconfig.field = updates[field] - tpmconfig.save() - - new_tpmconfig = tpmconfig.as_dict() - - # for conductor and agent updates, consider the entire - # set of incoming updates - new_tpmconfig.update(updates) - - # set a modify flag within the tpmconfig, this will inform - # the conductor as well as the agents that we are looking - # to modify the TPM configuration, and not a creation - new_tpmconfig['modify'] = True - - # apply TPM configuration via agent RPCs - try: - pecan.request.rpcapi.update_tpm_config( - pecan.request.context, - new_tpmconfig) - - pecan.request.rpcapi.update_tpm_config_manifests( - pecan.request.context) - except Exception as e: - with excutils.save_and_reraise_exception(): - LOG.exception(e) - - return TPMConfig.convert_with_links(tpmconfig) - - @wsme_pecan.wsexpose(None, types.uuid, status_code=204) - def delete(self, uuid): - """Delete a tpmconfig.""" - tpmconfig = objects.tpmconfig.get_by_uuid(pecan.request.context, - uuid) - - # clear all existing alarms for this TPM configuration - _clear_existing_tpmconfig_alarms() - - # clear all tpmdevice configurations for all hosts - tpmdevices = pecan.request.dbapi.tpmdevice_get_list() - for device in tpmdevices: - pecan.request.dbapi.tpmdevice_destroy(device.uuid) - - # need to cleanup the tpm file object - tpm_file = tpmconfig.tpm_path - - pecan.request.dbapi.tpmconfig_destroy(uuid) - pecan.request.rpcapi.update_tpm_config_manifests( - pecan.request.context, - delete_tpm_file=tpm_file)