Create new host_fs postgres table

Create a new host-fs postgres table to store information about a
host’s filesystem. Replicated filesystem will continue to be stored
in the controller_fs table.

This commit creates the table. The sysinv agent creates the docker,
backup and scratch filesystem for each supported host. If the
filesystems have changed the audit triggers an update.

These changes were testing with AIO-SX and Standard lab installs.

Change-Id: I8167dfe74688c05fd8b747caac3d418d2749a740
Partial-Bug: 1830142
Signed-off-by: Kristine Bujold <kristine.bujold@windriver.com>
This commit is contained in:
Kristine Bujold 2019-06-27 14:07:51 -04:00
parent eaf25e1f14
commit 10a595f22d
13 changed files with 519 additions and 16 deletions

View File

@ -1,2 +1,2 @@
SRC_DIR="sysinv"
TIS_PATCH_VER=325
TIS_PATCH_VER=326

View File

@ -17,7 +17,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -146,12 +146,14 @@ class AgentManager(service.PeriodicService):
self._iconfig_read_config_reported = None
self._ihost_personality = None
self._ihost_uuid = ""
self._ihost_rootfs_device = ""
self._agent_throttle = 0
self._mgmt_ip = None
self._prev_disk = None
self._prev_partition = None
self._prev_lvg = None
self._prev_pv = None
self._prev_fs = None
self._subfunctions = None
self._subfunctions_configured = False
self._notify_subfunctions_alarm_clear = False
@ -745,6 +747,7 @@ class AgentManager(service.PeriodicService):
self._ihost_uuid = ihost['uuid']
self._ihost_personality = ihost['personality']
self._mgmt_ip = ihost['mgmt_ip']
self._ihost_rootfs_device = ihost['rootfs_device']
if os.path.isfile(tsc.PLATFORM_CONF_FILE):
# read the platform config file and check for UUID
@ -1157,8 +1160,8 @@ class AgentManager(service.PeriodicService):
LOG.debug("SysInv Agent Audit running.")
if force_updates:
LOG.debug("SysInv Agent Audit force updates: (%s)" %
(', '.join(force_updates)))
LOG.info("SysInv Agent Audit force updates: (%s)" %
(', '.join(force_updates)))
self._update_ttys_dcd_status(icontext, self._ihost_uuid)
if self._agent_throttle > 5:
@ -1182,7 +1185,7 @@ class AgentManager(service.PeriodicService):
self._prev_disk = None
# if this audit is requested by conductor, clear
# previous states for disk, lvg and pv to force an update
# previous states for disk, lvg, pv and fs to force an update
if force_updates:
if constants.DISK_AUDIT_REQUEST in force_updates:
self._prev_disk = None
@ -1192,6 +1195,8 @@ class AgentManager(service.PeriodicService):
self._prev_pv = None
if constants.PARTITION_AUDIT_REQUEST in force_updates:
self._prev_partition = None
if constants.FILESYSTEM_AUDIT_REQUEST in force_updates:
self._prev_fs = None
# Update disks
idisk = self._idisk_operator.idisk_get()
@ -1250,6 +1255,55 @@ class AgentManager(service.PeriodicService):
self._prev_lvg = None
pass
# Update the filesystems
# Get the supported filesystems for this host
filesystems = []
# check if the scratch fs is supported for current host
if utils.is_filesystem_supported(constants.FILESYSTEM_NAME_SCRATCH, self._ihost_personality):
scratch_lv_size = utils.get_controller_fs_scratch_size()
data = {
'name': constants.FILESYSTEM_NAME_SCRATCH,
'size': scratch_lv_size,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_SCRATCH]
}
filesystems.append(data)
# check if the backup fs is supported for current host
if utils.is_filesystem_supported(constants.FILESYSTEM_NAME_BACKUP, self._ihost_personality):
backup_lv_size = utils.get_controller_fs_backup_size(self._ihost_rootfs_device)
data = {
'name': constants.FILESYSTEM_NAME_BACKUP,
'size': backup_lv_size,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_BACKUP]
}
filesystems.append(data)
# check if the docker fs is supported for current host
if utils.is_filesystem_supported(constants.FILESYSTEM_NAME_DOCKER, self._ihost_personality):
data = {
'name': constants.FILESYSTEM_NAME_DOCKER,
'size': constants.KUBERNETES_DOCKER_STOR_SIZE,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_DOCKER]
}
filesystems.append(data)
if filesystems and ((self._prev_fs is None) or (self._prev_fs != filesystems)):
try:
rpcapi.create_host_filesystems(icontext,
self._ihost_uuid,
filesystems)
self._prev_fs = filesystems
except exception.SysinvException:
LOG.exception("Sysinv Agent exception updating fs"
"conductor.")
self._prev_fs = None
pass
self._report_config_applied(icontext)
if os.path.isfile(tsc.PLATFORM_CONF_FILE):

View File

@ -526,6 +526,26 @@ FILESYSTEM_LV_DICT = {
FILESYSTEM_NAME_PATCH_VAULT: 'patch-vault-lv',
}
FILESYSTEM_CONTROLLER_SUPPORTED_LIST = [
FILESYSTEM_NAME_SCRATCH,
FILESYSTEM_NAME_BACKUP,
FILESYSTEM_NAME_DOCKER,
]
FILESYSTEM_WORKER_SUPPORTED_LIST = [
FILESYSTEM_NAME_DOCKER,
]
FILESYSTEM_STORAGE_SUPPORTED_LIST = [
FILESYSTEM_NAME_DOCKER,
]
FILESYSTEM_HOSTS_SUPPORTED_LIST_DICT = {
CONTROLLER: FILESYSTEM_CONTROLLER_SUPPORTED_LIST,
WORKER: FILESYSTEM_WORKER_SUPPORTED_LIST,
STORAGE: FILESYSTEM_STORAGE_SUPPORTED_LIST,
}
SUPPORTED_LOGICAL_VOLUME_LIST = FILESYSTEM_LV_DICT.values()
SUPPORTED_FILEYSTEM_LIST = [
@ -599,10 +619,12 @@ DISK_AUDIT_REQUEST = "audit_disk"
LVG_AUDIT_REQUEST = "audit_lvg"
PV_AUDIT_REQUEST = "audit_pv"
PARTITION_AUDIT_REQUEST = "audit_partition"
FILESYSTEM_AUDIT_REQUEST = "audit_fs"
CONTROLLER_AUDIT_REQUESTS = [DISK_AUDIT_REQUEST,
LVG_AUDIT_REQUEST,
PV_AUDIT_REQUEST,
PARTITION_AUDIT_REQUEST]
PARTITION_AUDIT_REQUEST,
FILESYSTEM_AUDIT_REQUEST]
# Interface definitions
NETWORK_TYPE_NONE = 'none'

View File

@ -1,6 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
@ -1364,3 +1364,11 @@ class UnsupportedAssignedInterfaceDataNetworkType(Conflict):
class UnsupportedRemovedInterfaceDataNetworkType(Conflict):
message = _("Cannot remove datanetwork with type '%(network_type)s' "
"from an interface.")
class FilesystemAlreadyExists(Conflict):
message = _("A Host FS with name %(name)s already exists.")
class FilesystemNotFound(NotFound):
message = _("No Host FS with id %(fs_id)s not found")

View File

@ -1605,6 +1605,16 @@ def get_dhcp_client_iaid(mac_address):
return hwaddr[2] << 24 | hwaddr[3] << 16 | hwaddr[4] << 8 | hwaddr[5]
def is_filesystem_supported(fs, personality):
""" Check to see if a filesystem is supported for the host personality.
"""
if personality in constants.FILESYSTEM_HOSTS_SUPPORTED_LIST_DICT:
if fs in constants.FILESYSTEM_HOSTS_SUPPORTED_LIST_DICT[personality]:
return True
return False
def get_controller_fs_scratch_size():
""" Get the filesystem scratch size setup by kickstart.
"""
@ -1636,6 +1646,38 @@ def get_controller_fs_scratch_size():
return scratch_gib
def get_controller_fs_backup_size(rootfs_device):
""" Get the filesystem backup size.
"""
disk_size = get_disk_capacity_mib(rootfs_device)
disk_size = int(disk_size / 1024)
if disk_size > constants.DEFAULT_SMALL_DISK_SIZE:
LOG.debug("Disk size : %s ... large disk defaults" % disk_size)
database_storage = constants.DEFAULT_DATABASE_STOR_SIZE
cgcs_lv_size = constants.DEFAULT_CGCS_STOR_SIZE
backup_lv_size = database_storage + cgcs_lv_size + \
constants.BACKUP_OVERHEAD
elif disk_size >= constants.MINIMUM_DISK_SIZE:
LOG.debug("Disk size : %s ... small disk defaults" % disk_size)
# Due to the small size of the disk we can't provide the
# proper amount of backup space which is (database + cgcs_lv
# + BACKUP_OVERHEAD) so we are using a smaller default.
backup_lv_size = constants.DEFAULT_SMALL_BACKUP_STOR_SIZE
else:
LOG.info("Disk size : %s ... disk too small" % disk_size)
raise exception.SysinvException("Disk size requirements not met.")
return backup_lv_size
def get_cgts_vg_free_space():
"""Determine free space in cgts-vg"""

View File

@ -3302,6 +3302,61 @@ class ConductorManager(service.PeriodicService):
return
def create_host_filesystems(self, context,
ihost_uuid, fs_dict_array):
"""Create a filesystems for an ihost with the supplied data.
This method allows records for filesystems for ihost to be
created.
:param context: an admin context
:param ihost_uuid: ihost uuid unique id
:param fs_dict_array: initial values for filesystems group objects
:returns: pass or fail
"""
ihost_uuid.strip()
try:
ihost = self.dbapi.ihost_get(ihost_uuid)
except exception.ServerNotFound:
LOG.exception("Invalid ihost_uuid %s" % ihost_uuid)
return
host_fs_list = self.dbapi.host_fs_get_by_ihost(ihost_uuid)
forihostid = ihost['id']
for fs in fs_dict_array:
fs_dict = {
'forihostid': forihostid,
}
fs_dict.update(fs)
found = False
for host_fs in host_fs_list:
if host_fs.name == fs['name']:
found = True
LOG.debug("Host FS '%s' already exists" % fs['name'])
if host_fs.size != fs['size']:
LOG.info("Host FS uuid: %s changed size from %s to %s",
host_fs.uuid, host_fs.size, fs['size'])
# Update the database
try:
self.dbapi.host_fs_update(host_fs.id, fs_dict)
except Exception:
LOG.exception("Host FS Update failed")
break
if not found:
try:
LOG.info("Creating Host FS:%s:%s %d for host id %d" %
(fs_dict['name'], fs_dict['logical_volume'],
fs_dict['size'], fs_dict['forihostid']))
self.dbapi.host_fs_create(forihostid, fs_dict)
except Exception:
LOG.exception("Host FS Creation failed")
return
def _fill_partition_info(self, db_part, ipart):
db_part_dict = db_part.as_dict()
keys = ['start_mib', 'end_mib', 'size_mib', 'type_name', 'type_guid']
@ -4160,7 +4215,7 @@ class ConductorManager(service.PeriodicService):
@periodic_task.periodic_task(spacing=CONF.conductor.audit_interval)
def _agent_update_request(self, context):
"""
Check DB for inventory objects with an inconsistent state and
Check DB for inventory objects with an inconsistent state and
request an update from sysinv agent.
Currently requesting updates for:
- ipv: if state is not 'provisioned'
@ -4212,6 +4267,9 @@ class ConductorManager(service.PeriodicService):
ilvgs = self.dbapi.ilvg_get_by_ihost(host.uuid)
if not ilvgs:
update_hosts_dict(host.id, constants.LVG_AUDIT_REQUEST)
host_fs = self.dbapi.host_fs_get_by_ihost(host.uuid)
if not host_fs:
update_hosts_dict(host.id, constants.FILESYSTEM_AUDIT_REQUEST)
# Check partitions.
partitions = self.dbapi.partition_get_all()

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
"""
@ -176,6 +176,24 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
self.make_msg('create_controller_filesystems',
rootfs_device=rootfs_device))
def create_host_filesystems(self, context, ihost_uuid, fs_dict_array):
"""Create or update the filesystem for an ihost with the supplied
data.
This method allows records for a filesystem for ihost to be
created, or updated.
:param context: an admin context
:param ihost_uuid: ihost uuid unique id
:param fs_dict_array: initial values for the filesystems
:returns: pass or fail
"""
return self.call(context,
self.make_msg('create_host_filesystems',
ihost_uuid=ihost_uuid,
fs_dict_array=fs_dict_array))
def get_ihost_by_macs(self, context, ihost_macs):
"""Finds ihost db entry based upon the mac list

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -2228,9 +2228,10 @@ class Connection(object):
:param values: A dict containing several items used to identify
and track the controller_fs.
Example:
values = {'name': constants.DEFAULT_DOCKER_STOR_SIZE,
values = {'name': constants.FILESYSTEM_NAME_DOCKER,
'size': 30,
'logical_volume': constants.FILESYSTEM_NAME_LV_DICT,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_DOCKER],
'replicated': False}
:returns: A controller_fs.
"""
@ -4339,3 +4340,86 @@ class Connection(object):
:param uuid: The uuid of an interface network association.
"""
@abc.abstractmethod
def host_fs_create(self, forihostid, values):
"""Create a new filesystem for a host.
:param forihostid: uuid or id of an ihost
:param values: A dict containing several items used to identify
and track the filesystem.
Example:
values = {'name': constants.FILESYSTEM_NAME_DOCKER,
'size': 30,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_DOCKER],
'forihostid': 1}
:returns: A filesystem.
"""
@abc.abstractmethod
def host_fs_get(self, fs_id):
"""Return a filesystem.
:param fs_id: The id or uuid of a filesystem.
:returns: A filesystem.
"""
@abc.abstractmethod
def host_fs_get_all(self, forihostid=None):
"""Return filesystems.
:param forihostid: The id or uuid of an ihost.
:returns: filesystem.
"""
@abc.abstractmethod
def host_fs_get_list(self, limit=None, marker=None,
sort_key=None, sort_dir=None):
"""Return a list of filesystems.
:param limit: Maximum number of filesystems to return.
:param marker: the last item of the previous page; we return the next
result set.
:param sort_key: Attribute by which results should be sorted.
:param sort_dir: direction in which results should be sorted.
(asc, desc)
"""
@abc.abstractmethod
def host_fs_get_by_ihost(self, ihost, limit=None,
marker=None, sort_key=None,
sort_dir=None):
"""List all the filesystems for a given ihost.
:param ihost: The id or uuid of an ihost.
:param marker: the last item of the previous page; we return the next
result set.
:param sort_key: Attribute by which results should be sorted
:param sort_dir: direction in which results should be sorted
(asc, desc)
:returns: A list of filesystems.
"""
@abc.abstractmethod
def host_fs_update(self, fs_id, values):
"""Update properties of a filesystem.
:param fs_id: The id or uuid of an filesystem.
:param values: Dict of values to update. May be a partial list.
Example:
values = {'name': constants.FILESYSTEM_NAME_DOCKER,
'size': 30,
'logical_volume': constants.FILESYSTEM_LV_DICT[
constants.FILESYSTEM_NAME_DOCKER
],
'forihostid': 1}
:returns: A filesystem.
"""
@abc.abstractmethod
def host_fs_destroy(self, fs_id):
"""Destroy a filesystem.
:param fs_id: The id or uuid of a filesystem.
"""

View File

@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
"""SQLAlchemy storage backend."""
@ -148,7 +148,8 @@ def add_identity_filter(query, value,
use_sensorgroupname=False,
use_sensorname=False,
use_cluster_uuid=False,
use_pciaddr=False):
use_pciaddr=False,
use_fsname=False):
"""Adds an identity filter to a query.
Filters results by ID, if supplied value is a valid integer.
@ -189,6 +190,8 @@ def add_identity_filter(query, value,
return query.filter_by(sensorname=value)
elif use_pciaddr:
return query.filter_by(pciaddr=value)
elif use_fsname:
return query.filter_by(name=value)
else:
return query.filter_by(hostname=value)
@ -1121,6 +1124,25 @@ def add_label_filter_by_host(query, hostid):
return query.filter(models.ihost.uuid == hostid)
def add_host_fs_filter(query, value):
"""Adds an fs-specific filter to a query.
:param query: Initial query to add filter to.
:param value: Value for filtering results by.
:return: Modified query.
"""
return add_identity_filter(query, value, use_fsname=True)
def add_host_fs_filter_by_ihost(query, value):
if utils.is_int_like(value):
return query.filter_by(forihostid=value)
else:
query = query.join(models.ihost,
models.HostFs.forihostid == models.ihost.id)
return query.filter(models.ihost.uuid == value)
class Connection(api.Connection):
"""SqlAlchemy connection."""
@ -7934,3 +7956,82 @@ class Connection(api.Connection):
@objects.objectify(objects.interface_datanetwork)
def interface_datanetwork_query(self, values):
return self._interface_datanetwork_query(values)
def _host_fs_get(self, fs_id):
query = model_query(models.HostFs)
query = add_identity_filter(query, fs_id)
try:
result = query.one()
except NoResultFound:
raise exception.FilesystemNotFound(fs_id=fs_id)
return result
@objects.objectify(objects.host_fs)
def host_fs_create(self, forihostid, values):
if not values.get('uuid'):
values['uuid'] = uuidutils.generate_uuid()
values['forihostid'] = int(forihostid)
fs = models.HostFs()
fs.update(values)
with _session_for_write() as session:
try:
session.add(fs)
session.flush()
except db_exc.DBDuplicateEntry:
raise exception.FilesystemAlreadyExists(
name=values['name'], host=forihostid)
return self._host_fs_get(values['uuid'])
@objects.objectify(objects.host_fs)
def host_fs_get_all(self, forihostid=None):
query = model_query(models.HostFs, read_deleted="no")
if forihostid:
query = query.filter_by(forihostid=forihostid)
return query.all()
@objects.objectify(objects.host_fs)
def host_fs_get(self, fs_id):
return self._host_fs_get(fs_id)
@objects.objectify(objects.host_fs)
def host_fs_get_list(self, limit=None, marker=None,
sort_key=None, sort_dir=None):
return _paginate_query(models.HostFs, limit, marker,
sort_key, sort_dir)
@objects.objectify(objects.host_fs)
def host_fs_get_by_ihost(self, ihost, limit=None, marker=None,
sort_key=None, sort_dir=None):
query = model_query(models.HostFs)
query = add_host_fs_filter_by_ihost(query, ihost)
return _paginate_query(models.HostFs, limit, marker,
sort_key, sort_dir, query)
@objects.objectify(objects.host_fs)
def host_fs_update(self, fs_id, values):
with _session_for_write() as session:
query = model_query(models.HostFs, read_deleted="no",
session=session)
query = add_host_fs_filter(query, fs_id)
count = query.update(values, synchronize_session='fetch')
if count != 1:
raise exception.FilesystemNotFound(fs_id=fs_id)
return query.one()
def host_fs_destroy(self, fs_id):
with _session_for_write() as session:
# Delete physically since it has unique columns
if uuidutils.is_uuid_like(fs_id):
model_query(models.HostFs, read_deleted="no",
session=session).\
filter_by(uuid=fs_id).\
delete()
else:
model_query(models.HostFs, read_deleted="no").\
filter_by(id=fs_id).\
delete()

View File

@ -0,0 +1,61 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from sqlalchemy import DateTime, String, Integer
from sqlalchemy import Column, MetaData, Table, ForeignKey
from sysinv.openstack.common import log
ENGINE = 'InnoDB'
CHARSET = 'utf8'
LOG = log.getLogger(__name__)
def upgrade(migrate_engine):
"""
This database upgrade creates a new host_fs table for storing
filesystem info for a host.
"""
meta = MetaData()
meta.bind = migrate_engine
Table('i_host',
meta,
Column('id', Integer, primary_key=True, nullable=False),
mysql_engine=ENGINE, mysql_charset=CHARSET, autoload=True)
# Define and create the host_fs table.
fs_app = Table(
'host_fs',
meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('deleted_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), unique=True),
Column('name', String(255)),
Column('size', Integer),
Column('logical_volume', String(64)),
Column('forihostid', Integer,
ForeignKey('i_host.id', ondelete='CASCADE')),
mysql_engine=ENGINE,
mysql_charset=CHARSET,
)
fs_app.create()
def downgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
# Downgrade is unsupported in this release.
raise NotImplementedError('SysInv database downgrade is unsupported.')

View File

@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -1721,3 +1721,17 @@ class KubeAppReleases(Base):
app_id = Column(Integer, ForeignKey('kube_app.id', ondelete='CASCADE'))
kube_app = relationship("KubeApp", lazy="joined", join_depth=1)
UniqueConstraint('release', 'namespace', 'app_id', name='u_app_release_namespace')
class HostFs(Base):
__tablename__ = 'host_fs'
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
name = Column(String(64))
size = Column(Integer)
logical_volume = Column(String(64))
forihostid = Column(Integer, ForeignKey('i_host.id', ondelete='CASCADE'))
host = relationship("ihost", lazy="joined", join_depth=1)

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2018 Wind River Systems, Inc.
# Copyright (c) 2013-2019 Wind River Systems, Inc.
#
@ -88,6 +88,7 @@ from sysinv.objects import storage_file
from sysinv.objects import storage_external
from sysinv.objects import storage_tier
from sysinv.objects import storage_ceph_external
from sysinv.objects import host_fs
def objectify(klass):
@ -185,6 +186,7 @@ label = label.Label
kube_app = kube_app.KubeApp
kube_app_releases = kube_app_releases.KubeAppReleases
datanetwork = datanetwork.DataNetwork
host_fs = host_fs.HostFS
__all__ = (system,
cluster,
@ -254,6 +256,7 @@ __all__ = (system,
kube_app_releases,
datanetwork,
interface_network,
host_fs,
# alias objects for RPC compatibility
ihost,
ilvg,

View File

@ -0,0 +1,38 @@
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# coding=utf-8
#
from sysinv.db import api as db_api
from sysinv.objects import base
from sysinv.objects import utils
class HostFS(base.SysinvObject):
dbapi = db_api.get_instance()
fields = {
'id': int,
'uuid': utils.str_or_none,
'name': utils.str_or_none,
'size': utils.int_or_none,
'logical_volume': utils.str_or_none,
'forihostid': int,
'ihost_uuid': utils.str_or_none,
}
_foreign_fields = {'ihost_uuid': 'host:uuid'}
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid):
return cls.dbapi.host_fs_get(uuid)
def save_changes(self, context, updates):
self.dbapi.host_fs_update(self.uuid, updates)