Files
ironic/ironic/db/sqlalchemy/models.py
T
Grzegorz Grasza ebfc4fe4c4 Add version column
This extends versioned objects and uses the object's
convert_to_version() to perform conversions between different
versions of the object. This conversion is only done at the
"boundaries" of the api and conductor services. That is, when
reading/writing to the database and when serializing/deserializing
(for RPC). Internally, the services deal with the latest versions
of the objects.

Version column is introduced to make sure reading the DB object
versions happens transparently for the developer. An exception
is raised in case of a version compatibility error.

The version column is null at first and will be filled with the
appropriate versions by a data migration script in a following patch.

Change-Id: I34629a5cbab7ff3f246ea19c0cb766badc7061db
Partial-Bug: #1526283
Co-Authored-By: Ruby Loo <ruby.loo@intel.com>
2017-06-06 15:34:37 -04:00

280 lines
10 KiB
Python

# -*- encoding: utf-8 -*-
#
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# 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.
"""
SQLAlchemy models for baremetal data.
"""
from os import path
from oslo_db import options as db_options
from oslo_db.sqlalchemy import models
from oslo_db.sqlalchemy import types as db_types
import six.moves.urllib.parse as urlparse
from sqlalchemy import Boolean, Column, DateTime, Index
from sqlalchemy import ForeignKey, Integer
from sqlalchemy import schema, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm
from ironic.conf import CONF
_DEFAULT_SQL_CONNECTION = 'sqlite:///' + path.join('$state_path',
'ironic.sqlite')
db_options.set_defaults(CONF, connection=_DEFAULT_SQL_CONNECTION)
def table_args():
engine_name = urlparse.urlparse(CONF.database.connection).scheme
if engine_name == 'mysql':
return {'mysql_engine': CONF.database.mysql_engine,
'mysql_charset': "utf8"}
return None
class IronicBase(models.TimestampMixin,
models.ModelBase):
metadata = None
version = Column(String(15), nullable=True)
def as_dict(self):
d = {}
for c in self.__table__.columns:
d[c.name] = self[c.name]
return d
Base = declarative_base(cls=IronicBase)
class Chassis(Base):
"""Represents a hardware chassis."""
__tablename__ = 'chassis'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_chassis0uuid'),
table_args()
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
extra = Column(db_types.JsonEncodedDict)
description = Column(String(255), nullable=True)
class Conductor(Base):
"""Represents a conductor service entry."""
__tablename__ = 'conductors'
__table_args__ = (
schema.UniqueConstraint('hostname', name='uniq_conductors0hostname'),
table_args()
)
id = Column(Integer, primary_key=True)
hostname = Column(String(255), nullable=False)
drivers = Column(db_types.JsonEncodedList)
online = Column(Boolean, default=True)
class ConductorHardwareInterfaces(Base):
"""Internal table used to track what is loaded on each conductor."""
__tablename__ = 'conductor_hardware_interfaces'
__table_args__ = (
schema.UniqueConstraint(
'conductor_id',
'hardware_type',
'interface_type',
'interface_name',
name='uniq_conductorhardwareinterfaces0'),
table_args())
id = Column(Integer, primary_key=True)
conductor_id = Column(Integer, ForeignKey('conductors.id'), nullable=False)
hardware_type = Column(String(255), nullable=False)
interface_type = Column(String(16), nullable=False)
interface_name = Column(String(255), nullable=False)
default = Column(Boolean, default=False, nullable=False)
class Node(Base):
"""Represents a bare metal node."""
__tablename__ = 'nodes'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_nodes0uuid'),
schema.UniqueConstraint('instance_uuid',
name='uniq_nodes0instance_uuid'),
schema.UniqueConstraint('name', name='uniq_nodes0name'),
table_args())
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
# NOTE(deva): we store instance_uuid directly on the node so that we can
# filter on it more efficiently, even though it is
# user-settable, and would otherwise be in node.properties.
instance_uuid = Column(String(36), nullable=True)
name = Column(String(255), nullable=True)
chassis_id = Column(Integer, ForeignKey('chassis.id'), nullable=True)
power_state = Column(String(15), nullable=True)
target_power_state = Column(String(15), nullable=True)
provision_state = Column(String(15), nullable=True)
target_provision_state = Column(String(15), nullable=True)
provision_updated_at = Column(DateTime, nullable=True)
last_error = Column(Text, nullable=True)
instance_info = Column(db_types.JsonEncodedDict)
properties = Column(db_types.JsonEncodedDict)
driver = Column(String(255))
driver_info = Column(db_types.JsonEncodedDict)
driver_internal_info = Column(db_types.JsonEncodedDict)
clean_step = Column(db_types.JsonEncodedDict)
resource_class = Column(String(80), nullable=True)
raid_config = Column(db_types.JsonEncodedDict)
target_raid_config = Column(db_types.JsonEncodedDict)
# NOTE(deva): this is the host name of the conductor which has
# acquired a TaskManager lock on the node.
# We should use an INT FK (conductors.id) in the future.
reservation = Column(String(255), nullable=True)
# NOTE(deva): this is the id of the last conductor which prepared local
# state for the node (eg, a PXE config file).
# When affinity and the hash ring's mapping do not match,
# this indicates that a conductor should rebuild local state.
conductor_affinity = Column(Integer,
ForeignKey('conductors.id',
name='nodes_conductor_affinity_fk'),
nullable=True)
maintenance = Column(Boolean, default=False)
maintenance_reason = Column(Text, nullable=True)
console_enabled = Column(Boolean, default=False)
inspection_finished_at = Column(DateTime, nullable=True)
inspection_started_at = Column(DateTime, nullable=True)
extra = Column(db_types.JsonEncodedDict)
boot_interface = Column(String(255), nullable=True)
console_interface = Column(String(255), nullable=True)
deploy_interface = Column(String(255), nullable=True)
inspect_interface = Column(String(255), nullable=True)
management_interface = Column(String(255), nullable=True)
network_interface = Column(String(255), nullable=True)
raid_interface = Column(String(255), nullable=True)
storage_interface = Column(String(255), nullable=True)
power_interface = Column(String(255), nullable=True)
vendor_interface = Column(String(255), nullable=True)
class Port(Base):
"""Represents a network port of a bare metal node."""
__tablename__ = 'ports'
__table_args__ = (
schema.UniqueConstraint('address', name='uniq_ports0address'),
schema.UniqueConstraint('uuid', name='uniq_ports0uuid'),
table_args())
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
address = Column(String(18))
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
extra = Column(db_types.JsonEncodedDict)
local_link_connection = Column(db_types.JsonEncodedDict)
portgroup_id = Column(Integer, ForeignKey('portgroups.id'), nullable=True)
pxe_enabled = Column(Boolean, default=True)
internal_info = Column(db_types.JsonEncodedDict)
physical_network = Column(String(64), nullable=True)
class Portgroup(Base):
"""Represents a group of network ports of a bare metal node."""
__tablename__ = 'portgroups'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_portgroups0uuid'),
schema.UniqueConstraint('address', name='uniq_portgroups0address'),
schema.UniqueConstraint('name', name='uniq_portgroups0name'),
table_args())
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
name = Column(String(255), nullable=True)
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
address = Column(String(18))
extra = Column(db_types.JsonEncodedDict)
internal_info = Column(db_types.JsonEncodedDict)
standalone_ports_supported = Column(Boolean, default=True)
mode = Column(String(255))
properties = Column(db_types.JsonEncodedDict)
class NodeTag(Base):
"""Represents a tag of a bare metal node."""
__tablename__ = 'node_tags'
__table_args__ = (
Index('node_tags_idx', 'tag'),
table_args())
node_id = Column(Integer, ForeignKey('nodes.id'),
primary_key=True, nullable=False)
tag = Column(String(255), primary_key=True, nullable=False)
node = orm.relationship(
"Node",
backref='tags',
primaryjoin='and_(NodeTag.node_id == Node.id)',
foreign_keys=node_id
)
class VolumeConnector(Base):
"""Represents a volume connector of a bare metal node."""
__tablename__ = 'volume_connectors'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_volumeconnectors0uuid'),
schema.UniqueConstraint(
'type',
'connector_id',
name='uniq_volumeconnectors0type0connector_id'),
table_args())
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
type = Column(String(32))
connector_id = Column(String(255))
extra = Column(db_types.JsonEncodedDict)
class VolumeTarget(Base):
"""Represents a volume target of a bare metal node."""
__tablename__ = 'volume_targets'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_volumetargets0uuid'),
schema.UniqueConstraint('node_id',
'boot_index',
name='uniq_volumetargets0node_id0boot_index'),
table_args())
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=True)
volume_type = Column(String(64))
properties = Column(db_types.JsonEncodedDict)
boot_index = Column(Integer)
volume_id = Column(String(36))
extra = Column(db_types.JsonEncodedDict)