Pool Manager - Central/Storage Changes
domains table changes: - Added 'ERROR' to status column - Set status column default to 'PENDING' - Added action column ('CREATE', 'DELETE', 'UPDATE', 'NONE') with a default of 'CREATE' records table changes: - Added 'ERROR' to status column - Set status column default to 'PENDING' - Added serial column with a default of 1 - Added action column ('CREATE', 'DELETE', 'UPDATE', 'NONE') with a default of 'CREATE' Other modifications: - Modified domain object to reflect new attribute (action) - Modified record object to reflect new attributes (serial, action) - Ensured central service continues to work by setting status of domain and record to 'ACTIVE' - Added update_status method to central service Change-Id: I893f8e7834de4c6ccf3ad587af65a7eee24415b3 Partially-implements: blueprint server-pools-service
This commit is contained in:
parent
2f15b33128
commit
f5f743e8af
@ -42,14 +42,15 @@ class CentralAPI(object):
|
||||
3.3 - Add methods for blacklisted domains
|
||||
4.0 - Create methods now accept designate objects
|
||||
4.1 - Add methods for server pools
|
||||
4.2 - Add methods for pool manager integration
|
||||
"""
|
||||
RPC_API_VERSION = '4.1'
|
||||
RPC_API_VERSION = '4.2'
|
||||
|
||||
def __init__(self, topic=None):
|
||||
topic = topic if topic else cfg.CONF.central_topic
|
||||
|
||||
target = messaging.Target(topic=topic, version=self.RPC_API_VERSION)
|
||||
self.client = rpc.get_client(target, version_cap='4.1')
|
||||
self.client = rpc.get_client(target, version_cap='4.2')
|
||||
|
||||
# Misc Methods
|
||||
def get_absolute_limits(self, context):
|
||||
@ -376,8 +377,7 @@ class CentralAPI(object):
|
||||
def create_pool(self, context, pool):
|
||||
LOG.info(_LI("create_pool: Calling central's create_pool."))
|
||||
cctxt = self.client.prepare(version='4.1')
|
||||
return cctxt.call(context, 'create_pool',
|
||||
pool=pool)
|
||||
return cctxt.call(context, 'create_pool', pool=pool)
|
||||
|
||||
def find_pools(self, context, criterion=None, marker=None, limit=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
@ -406,3 +406,10 @@ class CentralAPI(object):
|
||||
LOG.info(_LI("delete_pool: Calling central's delete_pool."))
|
||||
cctxt = self.client.prepare(version='4.1')
|
||||
return cctxt.call(context, 'delete_pool', pool_id=pool_id)
|
||||
|
||||
# Pool Manager Integration Methods
|
||||
def update_status(self, context, domain_id, status, serial):
|
||||
LOG.info(_LI("update_status: Calling central's update_status."))
|
||||
cctxt = self.client.prepare(version='4.2')
|
||||
return cctxt.call(context, 'update_status', domain_id=domain_id,
|
||||
status=status, serial=serial)
|
||||
|
@ -70,7 +70,7 @@ def transaction(f):
|
||||
|
||||
|
||||
class Service(service.RPCService):
|
||||
RPC_API_VERSION = '4.1'
|
||||
RPC_API_VERSION = '4.2'
|
||||
|
||||
target = messaging.Target(version=RPC_API_VERSION)
|
||||
|
||||
@ -391,6 +391,7 @@ class Service(service.RPCService):
|
||||
'type': "NS"})
|
||||
# Add new record to recordset
|
||||
ns_record = objects.Record(data=server.name)
|
||||
|
||||
new_record = self.create_record(context, zone['id'],
|
||||
ns['id'], ns_record,
|
||||
increment_serial=False)
|
||||
@ -741,6 +742,12 @@ class Service(service.RPCService):
|
||||
'Please create at least one server'))
|
||||
raise exceptions.NoServersConfigured()
|
||||
|
||||
# TODO(Ron): remove this when integrated with pool manager.
|
||||
# The default status is 'PENDING' for pool manager.
|
||||
# Setting status to 'ACTIVE' for backward compatibility.
|
||||
if cfg.CONF['service:central'].backend_driver != 'pool_manager_proxy':
|
||||
domain.status = 'ACTIVE'
|
||||
|
||||
# Set the serial number
|
||||
domain.serial = utils.increment_serial()
|
||||
|
||||
@ -1146,6 +1153,12 @@ class Service(service.RPCService):
|
||||
# Ensure the tenant has enough quota to continue
|
||||
self._enforce_record_quota(context, domain, recordset)
|
||||
|
||||
# TODO(Ron): remove this when integrated with pool_manager.
|
||||
# The default status is 'PENDING' for pool manager.
|
||||
# Setting status to 'ACTIVE' for backward compatibility.
|
||||
if cfg.CONF['service:central'].backend_driver != 'pool_manager_proxy':
|
||||
record.status = 'ACTIVE'
|
||||
|
||||
created_record = self.storage.create_record(context, domain_id,
|
||||
recordset_id, record)
|
||||
|
||||
@ -1796,3 +1809,51 @@ class Service(service.RPCService):
|
||||
pool = self.storage.delete_pool(context, pool_id)
|
||||
|
||||
self.notifier.info(context, 'dns.pool.delete', pool)
|
||||
|
||||
# Pool Manager Integration
|
||||
def update_status(self, context, domain_id, status, serial):
|
||||
"""
|
||||
:param context: Security context information.
|
||||
:param domain_id: The ID of the designate domain.
|
||||
:param status: The status, 'SUCCESS' or 'ERROR'.
|
||||
:param serial: The consensus serial number for the domain.
|
||||
:return: None
|
||||
"""
|
||||
domain = self.storage.get_domain(context, domain_id)
|
||||
criterion = {
|
||||
'domain_id': domain_id
|
||||
}
|
||||
records = self.storage.find_records(context, criterion=criterion)
|
||||
|
||||
if status == 'SUCCESS':
|
||||
if domain.action in ['CREATE', 'UPDATE'] \
|
||||
and domain.status in ['PENDING', 'ERROR']:
|
||||
domain.action = 'NONE'
|
||||
domain.status = 'ACTIVE'
|
||||
elif domain.action == 'DELETE' \
|
||||
and domain.status in ['PENDING', 'ERROR']:
|
||||
domain.action = 'NONE'
|
||||
domain.status = 'DELETED'
|
||||
for record in records:
|
||||
if record.action in ['CREATE', 'UPDATE'] \
|
||||
and record.status in ['PENDING', 'ERROR'] \
|
||||
and serial >= record.serial:
|
||||
record.action = 'NONE'
|
||||
record.status = 'ACTIVE'
|
||||
elif record.action == 'DELETE' \
|
||||
and record.status in ['PENDING', 'ERROR'] \
|
||||
and serial >= record.serial:
|
||||
record.action = 'NONE'
|
||||
record.status = 'DELETED'
|
||||
self.storage.update_record(context, record)
|
||||
|
||||
elif status == 'ERROR':
|
||||
if domain.status == 'PENDING':
|
||||
domain.status = 'ERROR'
|
||||
for record in records:
|
||||
if record.status == 'PENDING' \
|
||||
and serial >= record.serial:
|
||||
record.status = 'ERROR'
|
||||
self.storage.update_record(context, record)
|
||||
|
||||
self.storage.update_domain(context, domain)
|
||||
|
@ -29,7 +29,8 @@ class Domain(base.DictObjectMixin, base.SoftDeleteObjectMixin,
|
||||
'parent_domain_id': {},
|
||||
'serial': {},
|
||||
'description': {},
|
||||
'status': {}
|
||||
'status': {},
|
||||
'action': {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,9 @@ class Record(base.DictObjectMixin, base.PersistentObjectMixin,
|
||||
'recordset_id': {},
|
||||
'managed_tenant_id': {},
|
||||
'managed_resource_region': {},
|
||||
'managed_extra': {}
|
||||
'managed_extra': {},
|
||||
'action': {},
|
||||
'serial': {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,100 @@
|
||||
# Copyright (c) 2014 eBay Inc.
|
||||
#
|
||||
# Author: Ron Rickard <rrickard@ebaysf.com>
|
||||
#
|
||||
# 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.
|
||||
from sqlalchemy import MetaData, Table, Enum, Column, Integer
|
||||
from migrate.changeset.constraint import UniqueConstraint
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
|
||||
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED', 'ERROR']
|
||||
ACTIONS = ['CREATE', 'DELETE', 'UPDATE', 'NONE']
|
||||
|
||||
# Get associated database tables
|
||||
domains_table = Table('domains', meta, autoload=True)
|
||||
records_table = Table('records', meta, autoload=True)
|
||||
|
||||
# Upgrade the domains table.
|
||||
domains_table.c.status.alter(
|
||||
type=Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
default='PENDING', server_default='PENDING')
|
||||
action_column = Column('action', Enum(name='actions', *ACTIONS),
|
||||
default='CREATE', server_default='CREATE',
|
||||
nullable=False)
|
||||
action_column.create(domains_table)
|
||||
|
||||
# Re-add constraint for sqlite.
|
||||
dialect = migrate_engine.url.get_dialect().name
|
||||
if dialect.startswith('sqlite'):
|
||||
constraint = UniqueConstraint(
|
||||
'name', 'deleted', name='unique_domain_name', table=domains_table)
|
||||
constraint.create()
|
||||
|
||||
# Upgrade the records table.
|
||||
records_table.c.status.alter(
|
||||
type=Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
default='PENDING', server_default='PENDING')
|
||||
action_column = Column('action', Enum(name='actions', *ACTIONS),
|
||||
default='CREATE', server_default='CREATE',
|
||||
nullable=False)
|
||||
action_column.create(records_table)
|
||||
serial_column = Column('serial', Integer(), server_default='1',
|
||||
nullable=False)
|
||||
serial_column.create(records_table)
|
||||
|
||||
# Re-add constraint for sqlite.
|
||||
if dialect.startswith('sqlite'):
|
||||
constraint = UniqueConstraint(
|
||||
'hash', name='unique_record', table=records_table)
|
||||
constraint.create()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
|
||||
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED']
|
||||
|
||||
# Get associated database tables
|
||||
domains_table = Table('domains', meta, autoload=True)
|
||||
records_table = Table('records', meta, autoload=True)
|
||||
|
||||
# Downgrade the domains table.
|
||||
domains_table.c.status.alter(
|
||||
type=Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
default='ACTIVE', server_default='ACTIVE')
|
||||
domains_table.c.action.drop()
|
||||
|
||||
# Re-add constraint for sqlite.
|
||||
dialect = migrate_engine.url.get_dialect().name
|
||||
if dialect.startswith('sqlite'):
|
||||
constraint = UniqueConstraint(
|
||||
'name', 'deleted', name='unique_domain_name', table=domains_table)
|
||||
constraint.create()
|
||||
|
||||
# Downgrade the records table.
|
||||
records_table.c.status.alter(
|
||||
type=Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
default='ACTIVE', server_default='ACTIVE')
|
||||
records_table.c.action.drop()
|
||||
records_table.c.serial.drop()
|
||||
|
||||
# Re-add constraint for sqlite.
|
||||
if dialect.startswith('sqlite'):
|
||||
constraint = UniqueConstraint(
|
||||
'hash', name='unique_record', table=records_table)
|
||||
constraint.create()
|
@ -26,13 +26,13 @@ from designate.sqlalchemy.types import UUID
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED']
|
||||
RESOURCE_STATUSES = ['ACTIVE', 'PENDING', 'DELETED', 'ERROR']
|
||||
RECORD_TYPES = ['A', 'AAAA', 'CNAME', 'MX', 'SRV', 'TXT', 'SPF', 'NS', 'PTR',
|
||||
'SSHFP']
|
||||
TSIG_ALGORITHMS = ['hmac-md5', 'hmac-sha1', 'hmac-sha224', 'hmac-sha256',
|
||||
'hmac-sha384', 'hmac-sha512']
|
||||
|
||||
POOL_PROVISIONERS = ['UNMANAGED']
|
||||
ACTIONS = ['ADD', 'DELETE', 'UPDATE', 'NONE']
|
||||
|
||||
metadata = MetaData()
|
||||
|
||||
@ -98,8 +98,10 @@ domains = Table('domains', metadata,
|
||||
Column('minimum', Integer, default=CONF.default_soa_minimum,
|
||||
nullable=False),
|
||||
Column('status', Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
nullable=False, server_default='ACTIVE', default='ACTIVE'),
|
||||
nullable=False, server_default='PENDING', default='PENDING'),
|
||||
Column('parent_domain_id', UUID, default=None, nullable=True),
|
||||
Column('action', Enum(name='actions', *ACTIONS),
|
||||
default='CREATE', server_default='CREATE', nullable=False),
|
||||
|
||||
UniqueConstraint('name', 'deleted', name='unique_domain_name'),
|
||||
ForeignKeyConstraint(['parent_domain_id'],
|
||||
@ -152,8 +154,12 @@ records = Table('records', metadata,
|
||||
Column('managed_resource_id', UUID, default=None, nullable=True),
|
||||
Column('managed_tenant_id', Unicode(36), default=None, nullable=True),
|
||||
Column('status', Enum(name='resource_statuses', *RESOURCE_STATUSES),
|
||||
nullable=False, server_default='ACTIVE', default='ACTIVE'),
|
||||
server_default='PENDING', default='PENDING', nullable=False),
|
||||
Column('action', Enum(name='actions', *ACTIONS),
|
||||
default='CREATE', server_default='CREATE', nullable=False),
|
||||
Column('serial', Integer(), server_default='1', nullable=False),
|
||||
|
||||
UniqueConstraint('hash', name='unique_record'),
|
||||
ForeignKeyConstraint(['domain_id'], ['domains.id'], ondelete='CASCADE'),
|
||||
ForeignKeyConstraint(['recordset_id'], ['recordsets.id'],
|
||||
ondelete='CASCADE'),
|
||||
|
Loading…
Reference in New Issue
Block a user