Source code for dyn.tm.services.dsf

# -*- coding: utf-8 -*-
"""This module contains wrappers for interfacing with every element of a Traffic
Director (DSF) service.
"""
import logging
from ..utils import APIList, Active
from ..errors import DynectInvalidArgumentError
from ..records import *
from ..session import DynectSession
from ...compat import force_unicode

__author__ = 'jnappi'
__all__ = ['get_all_dsf_services', 'get_all_dsf_monitors', 'DSFARecord',
           'DSFAAAARecord', 'DSFCERTRecord', 'DSFCNAMERecord', 'DSFDHCIDRecord',
           'DSFDNAMERecord', 'DSFDNSKEYRecord', 'DSFDSRecord', 'DSFKEYRecord',
           'DSFKXRecord', 'DSFLOCRecord', 'DSFIPSECKEYRecord', 'DSFMXRecord',
           'DSFNAPTRRecord', 'DSFPTRRecord', 'DSFPXRecord', 'DSFNSAPRecord',
           'DSFRPRecord', 'DSFNSRecord', 'DSFSPFRecord', 'DSFSRVRecord',
           'DSFTXTRecord', 'DSFRecordSet', 'DSFFailoverChain',
           'DSFResponsePool', 'DSFRuleset', 'DSFMonitorEndpoint', 'DSFMonitor',
           'TrafficDirector']


[docs]def get_all_dsf_services(): """:return: A ``list`` of :class:`TrafficDirector` Services""" uri = '/DSF/' api_args = {'detail': 'Y'} response = DynectSession.get_session().execute(uri, 'GET', api_args) directors = [] for dsf in response['data']: directors.append(TrafficDirector(None, api=False, **dsf)) return directors
[docs]def get_all_dsf_monitors(): """:return: A ``list`` of :class:`DSFMonitor` Services""" uri = '/DSFMonitor/' api_args = {'detail': 'Y'} response = DynectSession.get_session().execute(uri, 'GET', api_args) mons = [] for dsf in response['data']: mons.append(DSFMonitor(api=False, **dsf)) return mons
class _DSFRecord(object): """docstring for _DSFRecord""" def __init__(self, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`_DSFRecord` object. :param label: A unique label for this :class:`DSFRecord` :param weight: Weight for this :class:`DSFRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ # super(_DSFRecord, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self.valid_automation = ('auto', 'auto_down', 'manual') self._label = label self._weight = weight if automation not in self.valid_automation: raise DynectInvalidArgumentError('automation', automation, self.valid_automation) self._automation = automation self._endpoints = endpoints self._endpoint_up_count = endpoint_up_count self._eligible = eligible self._dsf_id = self._record_set_id = self.uri = None for key, val in kwargs.items(): setattr(self, '_' + key, val) def _post(self, dsf_id, record_set_id): """Create a new :class:`DSFRecord` on the DynECT System :param dsf_id: The unique system id for the DSF service associated with this :class:`DSFRecord` :param record_set_id: The unique system id for the record set associated with this :class:`DSFRecord` """ self._dsf_id = dsf_id self._record_set_id = record_set_id self.uri = '/DSFRecord/{}/{}/'.format(self._dsf_id, self._record_set_id) api_args = {} for key, val in self.__dict__.items(): if val is not None and not hasattr(val, '__call__') and \ key.startswith('_'): if key != '_dsf_id' and key != '_record_set_id': api_args[key[1:]] = val response = DynectSession.get_session().execute(self.uri, 'POST', api_args) self._build(response['data']) def _get(self, dsf_id, record_set_id): """Get an existing :class:`DSFRecord` from the DynECT System :param dsf_id: The unique system id for the DSF service associated with this :class:`DSFRecord` :param record_set_id: The unique system id for the record set associated with this :class:`DSFRecord` """ self._dsf_id = dsf_id self._record_set_id = record_set_id self.uri = '/DSFRecord/{}/{}/'.format(self._dsf_id, self._record_set_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) self._build(response['data']) def _build(self, data): """Private build method :param data: API Response data """ for key, val in data.items(): if key == 'rdata': pass else: setattr(self, '_' + key, val) @property def dsf_id(self): """The unique system id for the DSF service associated with this :class:`DSFRecord` """ return self._dsf_id @dsf_id.setter def dsf_id(self, value): pass @property def record_set_id(self): """The unique system id for the record set associated with this :class:`DSFRecord` """ return self._record_set_id @record_set_id.setter def record_set_id(self, value): pass @property def label(self): """A unique label for this :class:`DSFRecord`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def weight(self): """Weight for this :class:`DSFRecord`""" return self._weight @weight.setter def weight(self, value): self._weight = value api_args = {'weight': self._weight} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def automation(self): """Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' """ return self._automation @automation.setter def automation(self, value): self._automation = value api_args = {'automation': self._automation} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def endpoints(self): """Endpoints are used to determine status, torpidity, and eligible in response to monitor data """ return self._endpoints @endpoints.setter def endpoints(self, value): self._endpoints = value api_args = {'endpoints': self._endpoints} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def endpoint_up_count(self): """Number of endpoints that must be up for the Record status to be 'up' """ return self._endpoint_up_count @endpoint_up_count.setter def endpoint_up_count(self, value): self._endpoint_up_count = value api_args = {'endpoint_up_count': self._endpoint_up_count} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def eligible(self): """Indicates whether or not the Record can be served""" return self._eligible @eligible.setter def eligible(self, value): self._eligible = value api_args = {'eligible': self._eligible} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) def to_json(self): """Convert this DSFRecord to a json blob""" json = {'label': self._label, 'weight': self._weight, 'automation': self._automation, 'endpoints': self._endpoints, 'eligible': self._eligible, 'endpoint_up_count': self._endpoint_up_count} json_blob = {x: json[x] for x in json if json[x] is not None} if hasattr(self, '_record_type'): # label = self._record_type.split('Record')[0].lower() + '_rdata' # We don't need to worry about rdata() throwing an error since if # we have a record type, then we know we're a subclass of a # DNSRecord rdata = self.rdata() outer_key = list(rdata.keys())[0] inner_data = rdata[outer_key] real_data = {x: inner_data[x] for x in inner_data if x not in json_blob and x not in self.__dict__ and x[1:] not in self.__dict__ and inner_data[x] is not None} json_blob['rdata'] = {outer_key: real_data} return json_blob def delete(self): """Delete this :class:`DSFRecord`""" api_args = {'publish': 'Y'} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
[docs]class DSFARecord(_DSFRecord, ARecord): """An :class:`ARecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, address, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFARecord` object :param address: IPv4 address for the record :param ttl: TTL for this record :param label: A unique label for this :class:`DSFARecord` :param weight: Weight for this :class:`DSFARecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ ARecord.__init__(self, None, None, address=address, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFAAAARecord(_DSFRecord, AAAARecord): """An :class:`AAAARecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, address, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFAAAARecord` object :param address: IPv6 address for the record :param ttl: TTL for this record :param label: A unique label for this :class:`DSFAAAARecord` :param weight: Weight for this :class:`DSFAAAARecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ AAAARecord.__init__(self, None, None, address=address, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFCERTRecord(_DSFRecord, CERTRecord): """An :class:`CERTRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, format, tag, algorithm, certificate, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFCERTRecord` object :param format: Numeric value for the certificate type :param tag: Numeric value for the public key certificate :param algorithm: Public key algorithm number used to generate the certificate :param certificate: The public key certificate :param ttl: TTL for this record :param label: A unique label for this :class:`DSFCERTRecord` :param weight: Weight for this :class:`DSFCERTRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ CERTRecord.__init__(self, None, None, format=format, tag=tag, algorithm=algorithm, certificate=certificate, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFCNAMERecord(_DSFRecord, CNAMERecord): """An :class:`CNAMERecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, cname, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFCNAMERecord` object :param cname: Hostname :param ttl: TTL for this record :param label: A unique label for this :class:`DSFCNAMERecord` :param weight: Weight for this :class:`DSFCNAMERecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ CNAMERecord.__init__(self, None, None, cname=cname, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFDHCIDRecord(_DSFRecord, DHCIDRecord): """An :class:`DHCIDRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, digest, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFDHCIDRecord` object :param digest: Base-64 encoded digest of DHCP data :param ttl: TTL for this record :param label: A unique label for this :class:`DSFDHCIDRecord` :param weight: Weight for this :class:`DSFDHCIDRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ DHCIDRecord.__init__(self, None, None, digest=digest, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFDNAMERecord(_DSFRecord, DNAMERecord): """An :class:`DNAMERecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, dname, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFDNAMERecord` object :param dname: Target Hostname :param ttl: TTL for this record :param label: A unique label for this :class:`DSFDNAMERecord` :param weight: Weight for this :class:`DSFDNAMERecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ DNAMERecord.__init__(self, None, None, dname=dname, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFDNSKEYRecord(_DSFRecord, DNSKEYRecord): """An :class:`DNSKEYRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, protocol, public_key, algorithm=5, flags=256, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFDNSKEYRecord` object :param protocol: Numeric value for protocol :param public_key: The public key for the DNSSEC signed zone :param algorithm: Numeric value representing the public key encryption algorithm which will sign the zone. Must be one of 1 (RSA-MD5), 2 (Diffie-Hellman), 3 (DSA/SHA-1), 4 (Elliptic Curve), or 5 (RSA-SHA-1) :param flags: Numeric value confirming this is the zone's DNSKEY :param ttl: TTL for this record :param label: A unique label for this :class:`DSFDNSKEYRecord` :param weight: Weight for this :class:`DSFDNSKEYRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ DNSKEYRecord.__init__(self, None, None, protocol=protocol, public_key=public_key, algorithm=algorithm, flags=flags, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFDSRecord(_DSFRecord, DSRecord): """An :class:`DSRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, digest, keytag, algorithm=5, digtype=1, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFDSRecord` object :param digest: The digest in hexadecimal form. 20-byte, hexadecimal-encoded, one-way hash of the DNSKEY record surrounded by parenthesis characters '(' & ')' :param keytag: The digest mechanism to use to verify the digest :param algorithm: Numeric value representing the public key encryption algorithm which will sign the zone. Must be one of 1 (RSA-MD5), 2 (Diffie-Hellman), 3 (DSA/SHA-1), 4 (Elliptic Curve), or 5 (RSA-SHA-1) :param digtype: the digest mechanism to use to verify the digest. Valid values are SHA1, SHA256 :param ttl: TTL for this record :param label: A unique label for this :class:`DSFDSRecord` :param weight: Weight for this :class:`DSFDSRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ DSRecord.__init__(self, None, None, digest=digest, keytag=keytag, algorithm=algorithm, digtype=digtype, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFKEYRecord(_DSFRecord, KEYRecord): """An :class:`KEYRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, algorithm, flags, protocol, public_key, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFKEYRecord` object :param algorithm: Numeric value representing the public key encryption algorithm which will sign the zone. Must be one of 1 (RSA-MD5), 2 (Diffie-Hellman), 3 (DSA/SHA-1), 4 (Elliptic Curve), or 5 (RSA-SHA-1) :param flags: See RFC 2535 for information on KEY record flags :param protocol: Numeric identifier of the protocol for this KEY record :param public_key: The public key for this record :param ttl: TTL for this record :param label: A unique label for this :class:`DSFKEYRecord` :param weight: Weight for this :class:`DSFKEYRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ KEYRecord.__init__(self, None, None, algorithm=algorithm, flags=flags, protocol=protocol, public_key=public_key, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFKXRecord(_DSFRecord, KXRecord): """An :class:`KXRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, exchange, preference, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFKXRecord` object :param exchange: Hostname that will act as the Key Exchanger. The hostname must have a :class:`CNAMERecord`, an :class:`ARecord` and/or an :class:`AAAARecord` associated with it :param preference: Numeric value for priority usage. Lower value takes precedence over higher value where two records of the same type exist on the zone/node :param ttl: TTL for this record :param label: A unique label for this :class:`DSFKXRecord` :param weight: Weight for this :class:`DSFKXRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ KXRecord.__init__(self, None, None, exchange=exchange, preference=preference, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFLOCRecord(_DSFRecord, LOCRecord): """An :class:`LOCRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, altitude, latitude, longitude, horiz_pre=10000, size=1, vert_pre=10, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFLOCRecord` object :param altitude: Measured in meters above sea level :param horiz_pre: :param latitude: Measured in degrees, minutes, and seconds with N/S indicator for North and South :param longitude: Measured in degrees, minutes, and seconds with E/W indicator for East and West :param size: :param version: :param vert_pre: :param ttl: TTL for this record :param label: A unique label for this :class:`DSFLOCRecord` :param weight: Weight for this :class:`DSFLOCRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ LOCRecord.__init__(self, None, None, altitude=altitude, latitude=latitude, longitude=longitude, horiz_pre=horiz_pre, size=size, vert_pre=vert_pre, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFIPSECKEYRecord(_DSFRecord, IPSECKEYRecord): """An :class:`IPSECKEYRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, precedence, gatetype, algorithm, gateway, public_key, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFIPSECKEYRecord` object :param precedence: Indicates priority among multiple IPSECKEYS. Lower numbers are higher priority :param gatetype: Gateway type. Must be one of 0, 1, 2, or 3 :param algorithm: Public key's cryptographic algorithm and format. Must be one of 0, 1, or 2 :param gateway: Gateway used to create IPsec tunnel. Based on Gateway type :param public_key: Base64 encoding of the public key. Whitespace is allowed :param ttl: TTL for this record :param label: A unique label for this :class:`DSFIPSECKEYRecord` :param weight: Weight for this :class:`DSFIPSECKEYRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ IPSECKEYRecord.__init__(self, None, None, precedence=precedence, gatetype=gatetype, algorithm=algorithm, gateway=gateway, public_key=public_key, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFMXRecord(_DSFRecord, MXRecord): """An :class:`MXRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, exchange, preference=10, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFMXRecord` object :param exchange: Hostname of the server responsible for accepting mail messages in the zone :param preference: Numeric value for priority usage. Lower value takes precedence over higher value where two records of the same type exist on the zone/node. :param ttl: TTL for this record :param label: A unique label for this :class:`DSFMXRecord` :param weight: Weight for this :class:`DSFMXRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ MXRecord.__init__(self, None, None, exchange=exchange, preference=preference, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFNAPTRRecord(_DSFRecord, NAPTRRecord): """An :class:`NAPTRRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, order, preference, services, regexp, replacement, flags='U', ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFNAPTRRecord` object :param order: Indicates the required priority for processing NAPTR records. Lowest value is used first. :param preference: Indicates priority where two or more NAPTR records have identical order values. Lowest value is used first. :param services: Always starts with "e2u+" (E.164 to URI). After the e2u+ there is a string that defines the type and optionally the subtype of the URI where this :class:`NAPTRRecord` points. :param regexp: The NAPTR record accepts regular expressions :param replacement: The next domain name to find. Only applies if this :class:`NAPTRRecord` is non-terminal. :param flags: Should be the letter "U". This indicates that this NAPTR record terminal :param ttl: TTL for this record :param label: A unique label for this :class:`DSFNAPTRRecord` :param weight: Weight for this :class:`DSFNAPTRRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ NAPTRRecord.__init__(self, None, None, order=order, preference=preference, services=services, regexp=regexp, replacement=replacement, flags=flags, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFPTRRecord(_DSFRecord, PTRRecord): """An :class:`PTRRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, ptrdname, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFPTRRecord` object :param ptrdname: The hostname where the IP address should be directed :param ttl: TTL for this record :param label: A unique label for this :class:`DSFPTRRecord` :param weight: Weight for this :class:`DSFPTRRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ PTRRecord.__init__(self, None, None, ptrdname=ptrdname, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFPXRecord(_DSFRecord, PXRecord): """An :class:`PXRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, preference, map822, mapx400, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFPXRecord` object :param preference: Sets priority for processing records of the same type. Lowest value is processed first. :param map822: mail hostname :param mapx400: The domain name derived from the X.400 part of MCGAM :param ttl: TTL for this record :param label: A unique label for this :class:`DSFPXRecord` :param weight: Weight for this :class:`DSFPXRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ PXRecord.__init__(self, None, None, preference=preference, map822=map822, mapx400=mapx400, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFNSAPRecord(_DSFRecord, NSAPRecord): """An :class:`NSAPRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, nsap, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFNSAPRecord` object :param nsap: Hex-encoded NSAP identifier :param ttl: TTL for this record :param label: A unique label for this :class:`DSFNSAPRecord` :param weight: Weight for this :class:`DSFNSAPRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ NSAPRecord.__init__(self, None, None, nsap=nsap, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFRPRecord(_DSFRecord, RPRecord): """An :class:`RPRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, mbox, txtdname, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFRPRecord` object :param mbox: Email address of the Responsible Person. :param txtdname: Hostname where a TXT record exists with more information on the responsible person. :param ttl: TTL for this record :param label: A unique label for this :class:`DSFRPRecord` :param weight: Weight for this :class:`DSFRPRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ RPRecord.__init__(self, None, None, mbox=mbox, txtdname=txtdname, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFNSRecord(_DSFRecord, NSRecord): """An :class:`NSRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, nsdname, service_class='', ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFNSRecord` object :param nsdname: Hostname of the authoritative Nameserver for the zone :param service_class: Hostname of the authoritative Nameserver for the zone :param ttl: TTL for this record :param label: A unique label for this :class:`DSFNSRecord` :param weight: Weight for this :class:`DSFNSRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ NSRecord.__init__(self, None, None, nsdname=nsdname, service_class=service_class, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFSPFRecord(_DSFRecord, SPFRecord): """An :class:`SPFRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, txtdata, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFSPFRecord` object :param txtdata: Free text containing SPF record information :param ttl: TTL for this record :param label: A unique label for this :class:`DSFSPFRecord` :param weight: Weight for this :class:`DSFSPFRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ SPFRecord.__init__(self, None, None, txtdata=txtdata, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFSRVRecord(_DSFRecord, SRVRecord): """An :class:`SRVRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, port, priority, target, rr_weight, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFSRVRecord` object :param port: Indicates the port where the service is running :param priority: Numeric value for priority usage. Lower value takes precedence over higher value where two records of the same type exist on the zone/node :param target: The domain name of a host where the service is running on the specified port :param rr_weight: Secondary prioritizing of records to serve. Records of equal priority should be served based on their weight. Higher values are served more often :param ttl: TTL for this record :param label: A unique label for this :class:`DSFSRVRecord` :param weight: Weight for this :class:`DSFSRVRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ SRVRecord.__init__(self, None, None, port=port, priority=priority, target=target, weight=rr_weight, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFTXTRecord(_DSFRecord, TXTRecord): """An :class:`TXTRecord` object which is able to store additional data for use by a :class:`TrafficDirector` service. """
[docs] def __init__(self, txtdata, ttl=0, label=None, weight=1, automation='auto', endpoints=None, endpoint_up_count=None, eligible=True, **kwargs): """Create a :class:`DSFTXTRecord` object :param txtdata: Plain text data to be served by this :class:`DSFTXTRecord` :param ttl: TTL for this record :param label: A unique label for this :class:`DSFTXTRecord` :param weight: Weight for this :class:`DSFTXTRecord` :param automation: Defines how eligible can be changed in response to monitoring. Must be one of 'auto', 'auto_down', or 'manual' :param endpoints: Endpoints are used to determine status, torpidity, and eligible in response to monitor data :param endpoint_up_count: Number of endpoints that must be up for the Record status to be 'up' :param eligible: Indicates whether or not the Record can be served """ TXTRecord.__init__(self, None, None, txtdata=txtdata, ttl=ttl, create=False) _DSFRecord.__init__(self, label, weight, automation, endpoints, endpoint_up_count, eligible, **kwargs)
[docs]class DSFRecordSet(object): """A Collection of DSFRecord Type objects belonging to a :class:`DSFFailoverChain` """
[docs] def __init__(self, rdata_class, label=None, ttl=None, automation=None, serve_count=None, fail_count=None, trouble_count=None, eligible=None, dsf_monitor_id=None, records=None, **kwargs): """Create a new :class:`DSFRecordSet` object :param rdata_class: The type of rdata represented by this :class:`DSFRecordSet` :param label: A unique label for this :class:`DSFRecordSet` :param ttl: Default TTL for :class:`DSFRecord`'s within this :class:`DSFRecordSet` :param automation: Defines how eligible can be changed in response to monitoring :param serve_count: How many Records to serve out of this :class:`DSFRecordSet` :param fail_count: The number of Records that must not be okay before this :class:`DSFRecordSet` becomes ineligible. :param trouble_count: The number of Records that must not be okay before this :class:`DSFRecordSet` becomes in trouble. :param eligible: Indicates whether or not this :class:`DSFRecordSet` can be served. :param dsf_monitor_id: The unique system id of the DSF Monitor attached to this :class:`DSFRecordSet` :param records: A list of :class:`DSFRecord`'s within this :class:`DSFRecordSet` :param kwargs: Used for manipulating additional data to be speicified by the creation of other system objects. """ super(DSFRecordSet, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self._label = label self._rdata_class = rdata_class self._ttl = ttl self._automation = automation self._serve_count = serve_count self._fail_count = fail_count self._trouble_count = trouble_count self._eligible = eligible self._dsf_monitor_id = dsf_monitor_id if records is not None and len(records) > 0 and isinstance(records[0], dict): self._records = [] for record in records: constructors = {'a': DSFARecord, 'aaaa': DSFAAAARecord, 'cert': DSFCERTRecord, 'cname': DSFCNAMERecord, 'dhcid': DSFDHCIDRecord, 'dname': DSFDNAMERecord, 'dnskey': DSFDNSKEYRecord, 'ds': DSFDSRecord, 'key': DSFKEYRecord, 'kx': DSFKXRecord, 'loc': DSFLOCRecord, 'ipseckey': DSFIPSECKEYRecord, 'mx': DSFMXRecord, 'naptr': DSFNAPTRRecord, 'ptr': DSFPTRRecord, 'px': DSFPXRecord, 'nsap': DSFNSAPRecord, 'rp': DSFRPRecord, 'ns': DSFNSRecord, 'spf': DSFSPFRecord, 'srv': DSFSRVRecord, 'txt': DSFTXTRecord} rec_type = record['rdata_class'].lower() constructor = constructors[rec_type] rdata_key = 'rdata_{}'.format(rec_type) kws = ('ttl', 'label', 'weight', 'automation', 'endpoints', 'endpoint_up_count', 'eligible', 'dsf_record_id', 'dsf_record_set_id', 'status', 'torpidity') for data in record['rdata']: record_data = data['data'][rdata_key] for kw in kws: record_data[kw] = record[kw] self._records.append(constructor(**record_data)) else: self._records = records or [] self.uri = self._master_line = self._rdata = self._status = None self._service_id = self._dsf_record_set_id = None for key, val in kwargs.items(): if key != 'records': setattr(self, '_' + key, val) # If dsf_id and dsf_response_pool_id were specified in kwargs if self._service_id is not None and self._dsf_record_set_id is not None: self.uri = '/DSFRecordSet/{}/{}/'.format(self._service_id, self._dsf_record_set_id)
def _post(self, dsf_id): """Create a new :class:`DSFRecordSet` on the DynECT System :param dsf_id: The unique system id of the DSF service this :class:`DSFRecordSet` is attached to """ self._service_id = dsf_id uri = '/DSFRecordSet/{}/'.format(self._service_id) api_args = {} for key, val in self.__dict__.items(): if key == 'records': api_args['records'] = [record.to_json() for record in val] elif val is not None and not hasattr(val, '__call__') and \ key.startswith('_'): api_args[key[1:]] = val response = DynectSession.get_session().execute(uri, 'POST', api_args) self._build(response['data']) self.uri = '/DSFRecordSet/{}/{}/'.format(self._service_id, self._dsf_record_set_id) def _get(self, dsf_id, dsf_record_set_id): """Get an existing :class:`DSFRecordSet` from the DynECT System :param dsf_id: The unique system id of the DSF service this :class:`DSFRecordSet` is attached to :param dsf_record_set_id: The unique system id of the DSF Record Set this :class:`DSFRecordSet` is attached to """ self._service_id = dsf_id self._dsf_record_set_id = dsf_record_set_id self.uri = '/DSFRecordSet/{}/{}/'.format(self._service_id, self._dsf_record_set_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) self._build(response['data']) def _build(self, data): """Private build method""" for key, val in data.items(): if key != 'records': setattr(self, '_' + key, val) @property def records(self): """The list of DSFRecord types that are stored in this :class:`DSFRecordSet` """ return self._records @records.setter def records(self, value): pass @property def status(self): """The current status of this :class:`DSFRecordSet`""" self._get(self._service_id, self._dsf_record_set_id) return self._status @status.setter def status(self, value): pass @property def label(self): """A unique label for this :class:`DSFRecordSet`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def rdata_class(self): """The rdata property is a read-only attribute""" return self._rdata_class @rdata_class.setter def rdata_class(self, value): pass @property def ttl(self): """Default TTL for :class:`DSFRecord`'s within this :class:`DSFRecordSet`""" return self._ttl @ttl.setter def ttl(self, value): self._ttl = value api_args = {'ttl': self._ttl} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def automation(self): """Defines how eligible can be changed in response to monitoring""" return self._automation @automation.setter def automation(self, value): self._automation = value api_args = {'automation': self._automation} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def serve_count(self): """How many Records to serve out of this :class:`DSFRecordSet`""" return self._serve_count @serve_count.setter def serve_count(self, value): self._serve_count = value api_args = {'serve_count': self._serve_count} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def fail_count(self): """The number of Records that must not be okay before this :class:`DSFRecordSet` becomes ineligible. """ return self._fail_count @fail_count.setter def fail_count(self, value): self._fail_count = value api_args = {'fail_count': self._fail_count} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def trouble_count(self): """The number of Records that must not be okay before this :class:`DSFRecordSet` becomes in trouble. """ return self._trouble_count @trouble_count.setter def trouble_count(self, value): self._trouble_count = value api_args = {'trouble_count': self._trouble_count} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def eligible(self): """Indicates whether or not this :class:`DSFRecordSet` can be served.""" return self._eligible @eligible.setter def eligible(self, value): self._eligible = value api_args = {'eligible': self._eligible} if self._master_line: api_args['master_line'] = self._master_line else: api_args['rdata'] = self._rdata response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) @property def dsf_monitor_id(self): """The unique system id of the DSF Monitor attached to this :class:`DSFRecordSet` """ return self._dsf_monitor_id @dsf_monitor_id.setter def dsf_monitor_id(self, value): self._dsf_monitor_id = value api_args = {'dsf_monitor_id': self._dsf_monitor_id} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data'])
[docs] def to_json(self): """Convert this :class:`DSFRecordSet` to a JSON blob""" json_blob = {'rdata_class': self._rdata_class} if self._label: json_blob['label'] = self._label if self._ttl: json_blob['ttl'] = self._ttl if self._automation: json_blob['automation'] = self._automation if self._serve_count: json_blob['serve_count'] = self._serve_count if self._fail_count: json_blob['fail_count'] = self._fail_count if self._trouble_count: json_blob['trouble_count'] = self._trouble_count if self._eligible: json_blob['eligible'] = self._eligible if self._dsf_monitor_id: json_blob['dsf_monitor_id'] = self._dsf_monitor_id if self._records: json_blob['records'] = [rec.to_json() for rec in self._records] else: json_blob['records'] = [] return json_blob
[docs] def delete(self): """Delete this :class:`DSFRecordSet` from the Dynect System""" api_args = {'publish': 'Y'} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
[docs]class DSFFailoverChain(object): """docstring for DSFFailoverChain"""
[docs] def __init__(self, label=None, core=None, record_sets=None, **kwargs): """Create a :class:`DSFFailoverChain` object :param label: A unique label for this :class:`DSFFailoverChain` :param core: Indicates whether or not the contained :class:`DSFRecordSets` are core record sets :param record_sets: A list of :class:`DSFRecordSet`'s for this :class:`DSFFailoverChain` """ super(DSFFailoverChain, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self._label = label self._core = core if isinstance(record_sets, list) and len(record_sets) > 0 and \ isinstance(record_sets[0], dict): # Clear record sets self._record_sets = [] # Create new record set objects for record_set in record_sets: if 'service_id' in record_set and \ record_set['service_id'] == '': record_set['service_id'] = kwargs['service_id'] self._record_sets.append(DSFRecordSet(**record_set)) else: self._record_sets = record_sets self._dsf_id = self._dsf_response_pool_id = self.uri = None for key, val in kwargs.items(): setattr(self, '_' + key, val) # If dsf_id and dsf_response_pool_id were specified in kwargs if self._dsf_id is not None and self._dsf_response_pool_id is not None: r_pid = self._dsf_response_pool_id self.uri = '/DSFRecordSetFailoverChain/{}/{}/'.format(self._dsf_id, r_pid)
def _post(self, dsf_id, dsf_response_pool_id): """Create a new :class:`DSFFailoverChain` on the Dynect System :param dsf_id: The unique system id of the DSF service this :class:`DSFFailoverChain` is attached to :param dsf_response_pool_id: The unique system is of the DSF response pool this :class:`DSFFailoverChain` is attached to """ self._dsf_id = dsf_id self._dsf_response_pool_id = dsf_response_pool_id self.uri = '/DSFRecordSetFailoverChain/{}/{}/'.format(self._dsf_id, self._dsf_response_pool_id) api_args = {'publish': 'Y'} if self._label: api_args['label'] = self._label if self._core: api_args['core'] = self._core if self._record_sets: api_args['record_sets'] = self._record_sets.to_json() response = DynectSession.get_session().execute(self.uri, 'POST', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) def _get(self, dsf_id, dsf_response_pool_id): """Retrieve an existing :class:`DSFFailoverChain` from the Dynect System :param dsf_id: The unique system id of the DSF service this :class:`DSFFailoverChain` is attached to :param dsf_response_pool_id: The unique system is of the DSF response pool this :class:`DSFFailoverChain` is attached to """ self._dsf_id = dsf_id self._dsf_response_pool_id = dsf_response_pool_id self.uri = '/DSFRecordSetFailoverChain/{}/{}/'.format(self._dsf_id, self._dsf_response_pool_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def label(self): """A unique label for this :class:`DSFFailoverChain`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def core(self): """Indicates whether or not the contained :class:`DSFRecordSet`'s are core record sets. """ return self._core @core.setter def core(self, value): self._core = value api_args = {'core': self._core} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def record_sets(self): """A list of hashes to create a new :class:`DSFRecordSet` or specify/update an existing :class:`DSFRecordSet` """ return self._record_sets @record_sets.setter def record_sets(self, value): pass
[docs] def to_json(self): """Convert this :class:`DSFFailoverChain` to a JSON blob""" json_blob = {} if self._label: json_blob['label'] = self._label if self._core: json_blob['core'] = self._core if self.record_sets: json_blob['record_sets'] = [rs.to_json() for rs in self.record_sets] return json_blob
[docs] def delete(self): """Delete this :class:`DSFFailoverChain` from the Dynect System""" api_args = {'publish': 'Y'} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
[docs]class DSFResponsePool(object): """docstring for DSFResponsePool"""
[docs] def __init__(self, label, core_set_count=1, eligible=True, automation='auto', dsf_ruleset_id=None, index=None, rs_chains=None, **kwargs): """Create a :class:`DSFResponsePool` object :param label: A unique label for this :class:`DSFResponsePool` :param core_set_count: If fewer than this number of core record sets are eligible, status will be set to fail :param eligible: Indicates whether or not the :class:`DSFResponsePool` can be served :param automation: Defines how eligible can be changed in response to monitoring :param dsf_ruleset_id: Unique system id of the Ruleset this :class:`DSFResponsePool` is attached to :param index: When specified with dsf_ruleset_id, indicates the position of the :class:`DSFResponsePool` :param rs_chains: A list of :class:`DSFFailoverChain` that are defined for this :class:`DSFResponsePool` """ super(DSFResponsePool, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self._label = label self._core_set_count = core_set_count self._eligible = eligible self._automation = automation self._dsf_ruleset_id = dsf_ruleset_id self._index = index if isinstance(rs_chains, list) and len(rs_chains) > 0 and \ isinstance(rs_chains[0], dict): # Clear Failover Chains self._rs_chains = [] # Create a new FO Chain for each entry returned from API for chain in rs_chains: self._rs_chains.append(DSFFailoverChain(**chain)) else: self._rs_chains = rs_chains self._dsf_id = self._dsf_response_pool_id = self.uri = None for key, val in kwargs.items(): setattr(self, '_' + key, val) # If dsf_id and dsf_response_pool_id were specified in kwargs if self._dsf_id is not None and self._dsf_response_pool_id is not None: r_pid = self._dsf_response_pool_id self.uri = '/DSFResponsePool/{}/{}/'.format(self._dsf_id, r_pid)
def _post(self, dsf_id): """Create a new :class:`DSFResponsePool` on the DynECT System :param dsf_id: the id of the DSF service this :class:`DSFResponsePool` is attached to """ self._dsf_id = dsf_id uri = '/DSFResponsePool/{}/'.format(self._dsf_id) api_args = {'publish': 'Y', 'label': self._label, 'core_set_count': self._core_set_count, 'eligible': self._eligible, 'automation': self._automation} if self._dsf_ruleset_id: api_args['dsf_ruleset_id'] = self._dsf_ruleset_id if self._index: api_args['index'] = self._index if self._rs_chains: api_args['rs_chains'] = self._rs_chains response = DynectSession.get_session().execute(uri, 'POST', api_args) for key, val in response['data'].items(): if key != 'rs_chains': setattr(self, '_' + key, val) self.uri = '/DSFResponsePool/{}/{}/'.format(self._dsf_id, self._dsf_response_pool_id) def _get(self, dsf_id, dsf_response_pool_id): """Get an existing :class:`DSFResponsePool` from the DynECT System :param dsf_id: the id of the DSF service this :class:`DSFResponsePool` is attached to :param dsf_response_pool_id: the id of this :class:`DSFResponsePool` """ self._dsf_id = dsf_id self._dsf_response_pool_id = dsf_response_pool_id self.uri = '/DSFResponsePool/{}/{}/'.format(self._dsf_id, self._dsf_response_pool_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): if key != 'rs_chains': setattr(self, '_' + key, val) @property def label(self): """A unique label for this :class:`DSFResponsePool`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def core_set_count(self): """If fewer than this number of core record sets are eligible, status will be set to fail """ return self._core_set_count @core_set_count.setter def core_set_count(self, value): self._core_set_count = value api_args = {'core_set_count': self._core_set_count} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def eligible(self): """Indicates whether or not the :class:`DSFResponsePool` can be served """ return self._eligible @eligible.setter def eligible(self, value): self._eligible = value api_args = {'eligible': self._eligible} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def automation(self): """Defines how eligible can be changed in response to monitoring""" return self._automation @automation.setter def automation(self, value): self._automation = value api_args = {'automation': self._automation} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def dsf_ruleset_id(self): """Unique system id of the Ruleset this :class:`DSFResponsePool` is attached to """ return self._dsf_ruleset_id @dsf_ruleset_id.setter def dsf_ruleset_id(self, value): self._dsf_ruleset_id = value api_args = {'dsf_ruleset_id': self._dsf_ruleset_id} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def rs_chains(self): """A list of :class:`DSFFailoverChain` that are defined for this :class:`DSFResponsePool` """ return self._rs_chains @rs_chains.setter def rs_chains(self, value): pass
[docs] def to_json(self): """Convert this :class:`DSFResponsePool` to a JSON blob""" rs_json = [rs.to_json() for rs in self._rs_chains] json_blob = {'label': self._label, 'eligible': self._eligible, 'core_set_count': self._core_set_count, 'automation': self._automation, 'rs_chains': rs_json} if self._index: json_blob['index'] = self._index if self._dsf_ruleset_id: json_blob['dsf_ruleset_id'] = self._dsf_ruleset_id return json_blob
[docs] def delete(self): """Delete this :class:`DSFResponsePool` from the DynECT System""" api_args = {'publish': 'Y'} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
[docs]class DSFRuleset(object): """docstring for DSFRuleset"""
[docs] def __init__(self, label, criteria_type, response_pools, criteria=None, **kwargs): """Create a :class:`DSFRuleset` object :param label: A unique label for this :class:`DSFRuleset` :param criteria_type: A set of rules describing what traffic is applied to the :class:`DSFRuleset` :param criteria: Varied depending on the specified criteria_type :param response_pools: A list of :class:`DSFResponsePool`'s for this :class:`DSFRuleset` """ super(DSFRuleset, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self.valid_criteria_types = ('always', 'geoip') self.valid_criteria = {'always': (), 'geoip': ()} self._label = label self._criteria_type = criteria_type self._criteria = criteria if isinstance(response_pools, list) and len(response_pools) > 0 and \ isinstance(response_pools[0], dict): self._response_pools = [] for pool in response_pools: pool = {x: pool[x] for x in pool if x != 'rulesets'} self._response_pools.append(DSFResponsePool(**pool)) else: self._response_pools = response_pools self._service_id = self._dsf_ruleset_id = self.uri = None for key, val in kwargs.items(): setattr(self, '_' + key, val) # If dsf_id and dsf_ruleset_id were specified in kwargs if self._service_id is not None and self._dsf_ruleset_id is not None: self.uri = '/DSFRuleset/{}/{}/'.format(self._service_id, self._dsf_ruleset_id)
def _post(self, dsf_id): """Create a new :class:`DSFRuleset` on the DynECT System :param dsf_id: the id of the DSF service this :class:`DSFRuleset` is attached to """ self._service_id = dsf_id uri = '/DSFRuleset/{}/'.format(self._service_id) api_args = {'publish': 'Y', 'label': self._label, 'criteria_type': self._criteria_type, 'criteria': self._criteria} response = DynectSession.get_session().execute(uri, 'POST', api_args) for key, val in response['data'].items(): if key != 'rs_chains': setattr(self, '_' + key, val) self.uri = '/DSFRuleset/{}/{}/'.format(self._service_id, self._dsf_ruleset_id) def _get(self, dsf_id, dsf_ruleset_id): """Get an existing :class:`DSFRuleset` from the DynECT System :param dsf_id: the id of the DSF service this :class:`DSFRuleset` is attached to :param dsf_ruleset_id: The unique system id of this :class:`DSFRuleset` """ self._service_id = dsf_id self._dsf_ruleset_id = dsf_ruleset_id self.uri = '/DSFRuleset/{}/{}/'.format(self._service_id, self._dsf_ruleset_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): if key != 'rs_chains': setattr(self, '_' + key, val) @property def label(self): """A unique label for this :class:`DSFRuleset`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def criteria_type(self): """A set of rules describing what traffic is applied to the :class:`DSFRuleset` """ return self._criteria_type @criteria_type.setter def criteria_type(self, value): self._criteria_type = value api_args = {'criteria_type': self._criteria_type} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def criteria(self): """The criteria rules, will be varied depending on the specified criteria_type """ return self._criteria @criteria.setter def criteria(self, value): self._criteria = value api_args = {'criteria': self._criteria} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): if key != 'record_sets': setattr(self, '_' + key, val) @property def response_pools(self): """A list of :class:`DSFResponsePool`'s for this :class:`DSFRuleset`""" return self._response_pools @response_pools.setter def response_pools(self, value): pass @property def _json(self): """JSON-ified version of this DSFRuleset Object""" pool_json = [pool.to_json() for pool in self._response_pools] json_blob = {'label': self._label, 'criteria_type': self._criteria_type, 'criteria': self._criteria, 'response_pools': pool_json} return json_blob
[docs] def delete(self): """Remove this :class:`DSFRuleset` from it's associated :class:`TrafficDirector` Service """ api_args = {'publish': 'Y'} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
class DSFMonitorEndpoint(object): """An Endpoint object to be passed to a :class:`DSFMonitor`""" def __init__(self, address, label, active='Y', site_prefs=None): """Create a :class:`DSFMonitorEndpoint` object :param address: The address to monitor. :param label: A label to identify this :class:`DSFMonitorEndpoint`. :param active: Indicates whether or not this :class:`DSFMonitorEndpoint` endpoint is active. Must be one of True, False, 'Y', or 'N' :param site_prefs: A ``list`` of site codes from which this :class:`DSFMonitorEndpoint` will be monitored """ self._address = address self._label = label self._active = Active(active) self._site_prefs = site_prefs self._monitor = None def _update(self, api_args): """Update this :class:`DSFMonitorEndpoint` with the provided api_args :param api_args: arguments to pass to the API via PUT """ if self._monitor is not None: full_list = self._monitor.endpoints args_list = [] for endpoint in full_list: if id(endpoint) == id(self): args_list.append(api_args) else: args_list.append(endpoint._json) api_args = {'endpoints': args_list} self._monitor._update(api_args) @property def _json(self): """Get the JSON representation of this :class:`DSFMonitorEndpoint` object """ json_blob = {'address': self._address, 'label': self._label, 'active': str(self._active), 'site_prefs': self._site_prefs} return {x: json_blob[x] for x in json_blob if json_blob[x] is not None} @property def active(self): """Indicates if this :class:`DSFMonitorEndpoint` is active. When updating valid arguments are 'Y' or True to activate, or 'N' or False to deactivate. :returns: An :class:`Active` object representing the current state of this :class:`DSFMonitorEndpoint` """ return self._active @active.setter def active(self, value): valid_input = ('Y', 'N', True, False) if value not in valid_input: raise DynectInvalidArgumentError('active', value, valid_input) api_args = self._json api_args['active'] = value self._update(api_args) @property def label(self): return self._label @label.setter def label(self, value): api_args = self._json api_args['label'] = value self._update(api_args) @property def address(self): return self._address @address.setter def address(self, value): api_args = self._json api_args['address'] = value self._update(api_args) @property def site_prefs(self): return self._site_prefs @site_prefs.setter def site_prefs(self, value): api_args = self._json api_args['site_prefs'] = value self._update(api_args)
[docs]class DSFMonitor(object): """A Monitor for a :class:`TrafficDirector` Service"""
[docs] def __init__(self, *args, **kwargs): """Create a new :class:`DSFMonitor` object :param label: A unique label to identify this :class:`DSFMonitor` :param protocol: The protocol to monitor. Must be one of 'HTTP', 'HTTPS', 'PING', 'SMTP', or 'TCP' :param response_count: The number of responses to determine whether or not the endpoint is 'up' or 'down' :param probe_interval: How often to run this :class:`DSFMonitor` :param retries: How many retries this :class:`DSFMonitor` should attempt on failure before giving up. :param active: Indicates if this :class:`DSFMonitor` is active :param options: Additional options pertaining to this :class:`DSFMonitor` :param endpoints: A List of :class:`DSFMonitorEndpoint`'s that are associated with this :class:`DSFMonitor` """ super(DSFMonitor, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self.uri = None self._monitor_id = None self._label = self._protocol = self._response_count = None self._probe_interval = self._retries = self._active = None self._options = self._dsf_monitor_id = self._timeout = self._port = None self._path = self._host = self._header = self._expected = None self._endpoints = [] if 'api' in kwargs: del kwargs['api'] for key, val in kwargs.items(): setattr(self, '_' + key, val) self.uri = '/DSFMonitor/{}/'.format(self._dsf_monitor_id) elif len(args) + len(kwargs) == 1: self._get(*args, **kwargs) else: self._post(*args, **kwargs)
def _get(self, monitor_id): """Get an existing :class:`DSFMonitor` from the DynECT System""" self._monitor_id = monitor_id self.uri = '/DSFMonitor/{}/'.format(self._monitor_id) api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) self._build(response['data']) def _post(self, label, protocol, response_count, probe_interval, retries, active='Y', timeout=None, port=None, path=None, host=None, header=None, expected=None, endpoints=None): """Create a new :class:`DSFMonitor` on the DynECT System""" uri = '/DSFMonitor/' self._label = label self._protocol = protocol self._response_count = response_count self._probe_interval = probe_interval self._retries = retries self._active = Active(active) self._options = {} if timeout: self._timeout = timeout self._options['timeout'] = timeout if port: self._port = port self._options['port'] = port if path: self._path = path self._options['path'] = path if host: self._host = host self._options['host'] = host if header: self._header = header self._options['header'] = header if expected: self._expected = expected self._options['expected'] = expected self._endpoints = endpoints api_args = {'label': self._label, 'protocol': self._protocol, 'response_count': self._response_count, 'probe_interval': self._probe_interval, 'retries': self._retries, 'active': str(self._active), 'options': self._options} if self._endpoints is not None: api_args['endpoints'] = [x._json for x in self._endpoints] response = DynectSession.get_session().execute(uri, 'POST', api_args) self._build(response['data']) self.uri = '/DSFMonitor/{}/'.format(self._dsf_monitor_id) def _update(self, api_args): """Private Update method""" response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data']) def _build(self, data): """Update this object based on the information passed in via data :param data: The ``['data']`` field from an API JSON response """ for key, val in data.items(): if key == 'endpoints': self._endpoints = [] for endpoint in val: ep = DSFMonitorEndpoint(**endpoint) ep._monitor = self self._endpoints.append(ep) elif key == 'options': for opt_key, opt_val in val.items(): setattr(self, '_' + opt_key, opt_val) elif key == 'active': self._active = Active(val) else: setattr(self, '_' + key, val) @property def dsf_monitor_id(self): """The unique system id of this :class:`DSFMonitor`""" return self._dsf_monitor_id @dsf_monitor_id.setter def dsf_monitor_id(self, value): pass @property def label(self): """A unique label to identify this :class:`DSFMonitor`""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} self._update(api_args) @property def protocol(self): """The protocol to monitor. Must be one of 'HTTP', 'HTTPS', 'PING', 'SMTP', or 'TCP' """ return self._protocol @protocol.setter def protocol(self, value): self._protocol = value api_args = {'protocol': self._protocol} self._update(api_args) @property def response_count(self): """The number of responses to determine whether or not the endpoint is 'up' or 'down' """ return self._response_count @response_count.setter def response_count(self, value): self._response_count = value api_args = {'response_count': self._response_count} self._update(api_args) @property def probe_interval(self): """How often to run this :class:`DSFMonitor`""" return self._probe_interval @probe_interval.setter def probe_interval(self, value): self._probe_interval = value api_args = {'probe_interval': self._probe_interval} self._update(api_args) @property def retries(self): """How many retries this :class:`DSFMonitor` should attempt on failure before giving up. """ return self._retries @retries.setter def retries(self, value): self._retries = value api_args = {'retries': self._retries} self._update(api_args) @property def active(self): """Returns whether or not this :class:`DSFMonitor` is active. Will return either 'Y' or 'N' """ return self._active @active.setter def active(self, value): self._active = value api_args = {'active': self._active} self._update(api_args) @property def endpoints(self): """A list of the endpoints (and their statuses) that this :class:`DSFMonitor` is currently monitoring. """ self._get(self.dsf_monitor_id) return self._endpoints @endpoints.setter def endpoints(self, value): pass @property def options(self): """Additional options pertaining to this :class:`DSFMonitor`""" return self._options @options.setter def options(self, value): self._options = value api_args = {'options': self._options} self._update(api_args)
[docs] def delete(self): """Delete an existing :class:`DSFMonitor` from the DynECT System""" api_args = {} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
[docs]class TrafficDirector(object): """Traffic Director is a DNS based traffic routing and load balancing service that is Geolocation aware and can support failover by monitoring endpoints. """
[docs] def __init__(self, *args, **kwargs): """Create a :class:`TrafficDirector` object :param label: A unique label for this :class:`TrafficDirector` service :param ttl: The default TTL to be used across this service :param publish: If Y, service will be published on creation :param nodes: A list of zone, FQDN pairs in a hash that are to be linked to this :class:`TrafficDirector` service: :param notifiers: A list of names of notifiers associated with this :class:`TrafficDirector` service :param rulesets: A list of :class:`DSFRulesets` that are defined for this :class:`TrafficDirector` service """ super(TrafficDirector, self).__init__() self.logger = logging.getLogger(str(self.__class__)) self._label = self._ttl = self._publish = self._response_pools = None self._record_sets = self.uri = self._service_id = None self._notifiers = APIList(DynectSession.get_session, 'notifiers') self._nodes = APIList(DynectSession.get_session, 'nodes') self._rulesets = APIList(DynectSession.get_session, 'rulesets') if 'api' in kwargs: del kwargs['api'] self._build(kwargs) elif len(args) + len(kwargs) == 1: self._get(*args, **kwargs) else: self._post(*args, **kwargs) self.uri = '/DSF/{}/'.format(self._service_id) self._notifiers.uri = self._nodes.uri = self._rulesets.uri = self.uri
def _post(self, label, ttl=None, publish='Y', nodes=None, notifiers=None, rulesets=None): """Create a new :class:`TrafficDirector` on the DynECT System""" uri = '/DSF/' self._label = label self._ttl = ttl self._nodes = nodes self._notifiers = notifiers self._rulesets = rulesets api_args = {'label': self._label, 'publish': publish} if ttl: api_args['ttl'] = self._ttl if nodes: api_args['nodes'] = self._nodes if notifiers: if isinstance(notifiers[0], dict): api_args['notifiers'] = notifiers else: # notifiers is a list of Notifier objects api_args['notifiers'] = [{'notifier_id': x.notifier_id} for x in self._notifiers] if rulesets: api_args['rulesets'] = [rule._json for rule in self._rulesets] response = DynectSession.get_session().execute(uri, 'POST', api_args) self.uri = '/DSF/{}/'.format(response['data']['service_id']) self._build(response['data']) def _build(self, data): for key, val in data.items(): if key == 'notifiers': # Don't do anything special with these dicts for now self._notifiers = APIList(DynectSession.get_session, 'notifiers', None, val) elif key == 'rulesets': # Clear Rulesets self._rulesets = APIList(DynectSession.get_session, 'rulesets') self._rulesets.uri = None # For each Ruleset returned, create a new DSFRuleset object for ruleset in val: self._rulesets.append(DSFRuleset(**ruleset)) elif key == 'nodes': # Don't do anything special with these dicts for now self._nodes = APIList(DynectSession.get_session, 'nodes', None, val) else: setattr(self, '_' + key, val) self.uri = '/DSF/{}/'.format(self._service_id) self._notifiers.uri = self._nodes.uri = self._rulesets.uri = self.uri def _get(self, service_id): """Get an existing :class:`TrafficDirector` from the DynECT System""" self._service_id = service_id self.uri = '/DSF/{}/'.format(self._service_id) api_args = {'pending_changes': 'Y'} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) self._build(response['data']) def _update(self, api_args): """Private update method""" if 'publish' not in api_args: api_args['publish'] = 'Y' response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data'])
[docs] def revert_changes(self): """Clears the changeset for this service and reverts all non-published changes to their original state """ api_args = {'revert': True} self._update(api_args)
[docs] def add_notifier(self, notifier_id, publish='Y'): """Links the Notifier with the specified id to this Traffic Director service """ api_args = {'add_notifier': True, 'notifier_id': notifier_id, 'publish': publish} self._update(api_args)
[docs] def remove_orphans(self): """Remove Record Set Chains which are no longer referenced by a :class:`DSFResponsePool` """ api_args = {'remove_orphans': 'Y'} self._update(api_args)
@property def service_id(self): """The unique System id of this DSF Service""" return self._service_id @service_id.setter def service_id(self, value): pass @property def records(self): """A list of this :class:`TrafficDirector` Services' DSFRecords""" return [record for ruleset in self._rulesets for response_pool in ruleset.response_pools for rs_chains in response_pool.rs_chains for record_set in rs_chains.record_sets for record in record_set.records] @records.setter def records(self, value): pass @property def record_sets(self): """A list of this :class:`TrafficDirector` Services :class:`DSFRecordSet`'s """ return [record_set for ruleset in self._rulesets for response_pool in ruleset.response_pools for rs_chains in response_pool.rs_chains for record_set in rs_chains.record_sets] @record_sets.setter def record_sets(self, value): pass @property def response_pools(self): """A list of this :class:`TrafficDirector` Services :class:`DSFResponsePool`'s """ return [response_pool for ruleset in self._rulesets for response_pool in ruleset.response_pools] @response_pools.setter def response_pools(self, value): pass @property def rs_chains(self): """A list of this :class:`TrafficDirector` Services :class:`DSFFailoverChain`'s """ return [rs_chains for ruleset in self._rulesets for response_pool in ruleset.response_pools for rs_chains in response_pool.rs_chains] @rs_chains.setter def rs_chains(self, value): pass @property def notifiers(self): """A list of names of notifiers associated with this :class:`TrafficDirector` service """ return self._notifiers @notifiers.setter def notifiers(self, value): if isinstance(value, list) and not isinstance(value, APIList): self._notifiers = APIList(DynectSession.get_session, 'notifiers', None, value) elif isinstance(value, APIList): self._notifiers = value self._notifiers.uri = self.uri @property def rulesets(self): """A list of :class:`DSFRulesets` that are defined for this :class:`TrafficDirector` service """ return self._rulesets @rulesets.setter def rulesets(self, value): if isinstance(value, list) and not isinstance(value, APIList): self._rulesets = APIList(DynectSession.get_session, 'rulesets', None, value) elif isinstance(value, APIList): self._rulesets = value self._rulesets.uri = self.uri @property def nodes(self): """A list of zone, FQDN pairs in a hash that are linked, or to be linked to this :class:`TrafficDirector` service""" return self._nodes @nodes.setter def nodes(self, value): if isinstance(value, list) and not isinstance(value, APIList): self._nodes = APIList(DynectSession.get_session, 'nodes', None, value) elif isinstance(value, APIList): self._nodes = value self._nodes.uri = self.uri @property def label(self): """A unique label for this :class:`TrafficDirector` service""" return self._label @label.setter def label(self, value): self._label = value api_args = {'label': self._label} self._update(api_args) @property def ttl(self): """The default TTL to be used across this service""" if not isinstance(self._ttl, int): self._ttl = int(self._ttl) return self._ttl @ttl.setter def ttl(self, value): self._ttl = value api_args = {'ttl': self._ttl} self._update(api_args)
[docs] def delete(self): """Delete this :class:`TrafficDirector` from the DynECT System""" api_args = {} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
def __str__(self): """str override""" return force_unicode('<TrafficDirector>: {}').format(self._service_id) __repr__ = __unicode__ = __str__ def __bytes__(self): """bytes override""" return bytes(self.__str__())