示例#1
0
 def _build(self, data):
     for key, val in data.items():
         if key == 'pool':
             pass
         elif key == "task_id" and not val:
             self._task_id = None
         elif key == "task_id":
             self._task_id = Task(val)
         else:
             setattr(self, '_' + key, val)
示例#2
0
 def _build(self, data):
     """Build the variables in this object by pulling out the data from data
     """
     for key, val in data.items():
         if key == "task_id" and not val:
             self._task_id = None
         elif key == "task_id":
             self._task_id = Task(val)
         else:
             setattr(self, '_' + key, val)
示例#3
0
 def _build(self, data):
     """Build this object from the data returned in an API response"""
     self._task_id = None
     for key, val in data.items():
         if key == 'monitor':
             self._monitor = HealthMonitor(**val)
         elif key == 'active':
             self._active = Active(val)
         elif key == "task_id" and not val:
             self._task_id = None
         elif key == "task_id":
             self._task_id = Task(val)
         else:
             setattr(self, '_' + key, val)
示例#4
0
文件: gslb.py 项目: Raz71/dyn-python
    def _build(self, data, region=True):
        """Private method which builds the objects fields based on the data
        returned by an API call

        :param data: the data from the JSON respnose
        :param region: Boolean flag specifying whether to rebuild the region
            objects or not
        """
        for key, val in data.items():
            if key == 'region':
                if region:
                    self._region = APIList(DynectSession.get_session, 'region')
                    for region in val:
                        region_code = region.pop('region_code', None)
                        self._region.append(GSLBRegion(self._zone, self._fqdn,
                                                       region_code, **region))
            elif key == 'monitor':
                # We already have the monitor object, no need to rebuild it
                pass
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)
        self._region.uri = self.uri
示例#5
0
文件: gslb.py 项目: Raz71/dyn-python
 def _build(self, data):
     """Build the variables in this object by pulling out the data from data
     """
     for key, val in data.items():
         if key == "task_id" and not val:
             self._task_id = None
         elif key == "task_id":
             self._task_id = Task(val)
         else:
             setattr(self, '_' + key, val)
示例#6
0
    def _build(self, data):
        """Build the neccesary substructures under this :class:`RTTM`"""
        for key, val in data.items():
            if key == 'region':
                self._region = APIList(DynectSession.get_session, 'region')
                for region in val:
                    code = region.pop('region_code', None)
                    pool = region.pop('pool', None)
                    status = region.pop('status', None)

                    r = RTTMRegion(self._zone, self._fqdn, code, pool,
                                   **region)
                    r._status = status
                    self._region.append(r)
            elif key == 'monitor':
                if self._monitor is not None:
                    self._monitor.zone = self._zone
                    self._monitor.fqdn = self._fqdn
                else:
                    proto = val.pop('protocol', None)
                    inter = val.pop('interval', None)
                    self._monitor = Monitor(proto, inter, **val)
            elif key == 'performance_monitor':
                if self._performance_monitor is not None:
                    self._performance_monitor.zone = self._zone
                    self._performance_monitor.fqdn = self._fqdn
                else:
                    proto = val.pop('protocol', None)
                    inter = val.pop('interval', None)
                    self._performance_monitor = PerformanceMonitor(proto,
                                                                   inter,
                                                                   **val)
            elif key == 'notify_events':
                self._notify_events = [item.strip() for item in val.split(',')]
            elif key == 'active':
                self._active = Active(val)
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)
        self._region.uri = self.uri
示例#7
0
文件: gslb.py 项目: Raz71/dyn-python
 def _build(self, data):
     self._pool = []
     for key, val in data.items():
         if key == 'pool':
             for pool in val:
                 if isinstance(pool, dict):
                     self._pool.append(GSLBRegionPoolEntry(
                         self._zone, self._fqdn, self._region_code,
                         **pool)
                     )
                 else:
                     self._pool.append(pool)
         elif key == "task_id" and not val:
             self._task_id = None
         elif key == "task_id":
             self._task_id = Task(val)
         else:
             setattr(self, '_' + key, val)
示例#8
0
class ActiveFailover(object):
    """With Active Failover, we monitor your Primary IP.  If a failover event
    is detected, our system auto switches (hot swaps) to your dedicated back-up
    IP
    """

    def __init__(self, zone, fqdn, *args, **kwargs):
        """Create a new :class:`ActiveFailover` object

        :param zone: The zone to attach this :class:`ActiveFailover` service to
        :param fqdn: The FQDN where this :class:`ActiveFailover` service will
            be attached
        :param address: IPv4 Address or FQDN being monitored by this
            :class:`ActiveFailover` service
        :param failover_mode: Indicates the target failover resource type.
        :param failover_data: The IPv4 Address or CNAME data for the failover
            target
        :param auto_recover: Indicates whether this service should restore its
            original state when the source IPs resume online status
        :param notify_events: A comma separated list of what events trigger
            notifications
        :param syslog_server: The Hostname or IP address of a server to receive
            syslog notifications on monitoring events
        :param syslog_port: The port where the remote syslog server listens
        :param syslog_ident: The ident to use when sending syslog notifications
        :param syslog_facility: The syslog facility to use when sending syslog
            notifications
        :param syslog_delivery: The syslog delivery action type. 'all' will
            deliver notifications no matter what the endpoint state. 'change'
            (default) will deliver only on change in the detected endpoint
            state
        :param monitor: The :class:`HealthMonitor` for this
            :class:`ActiveFailover` service
        :param contact_nickname: Name of contact to receive notifications from
            this :class:`ActiveFailover` service
        :param ttl: Time To Live in seconds of records in the service. Must be
            less than 1/2 of the Health Probe's monitoring interval
        :param syslog_probe_fmt: see below for format:
        :param syslog_status_fmt: see below for format:
            Use the following format for syslog_xxxx_fmt paramaters.
            %hos	hostname
            %tim	current timestamp or monitored interval
            %reg	region code
            %sta	status
            %ser	record serial
            %rda	rdata
            %sit	monitoring site
            %rti	response time
            %msg	message from monitoring
            %adr	address of monitored node
            %med	median value
            %rts	response times (RTTM)
        :param recovery_delay: number of up status polling intervals to
            consider service up
        """
        super(ActiveFailover, self).__init__()
        self.valid_notify_events = ('ip', 'svc', 'nosrv')
        self._zone = zone
        self._fqdn = fqdn
        self._address = self._failover_mode = self._failover_data = None
        self._monitor = self._active = None
        self._contact_nickname = self._auto_recover = None
        self._notify_events = self._syslog_server = self._syslog_port = None
        self._syslog_ident = self._syslog_probe_fmt = None
        self._syslog_status_fmt = self._syslog_facility = self._ttl = None
        self._syslog_delivery = self._recovery_delay = None
        self.uri = '/Failover/{}/{}/'.format(self._zone, self._fqdn)
        self.api_args = {}
        if 'api' in kwargs:
            del kwargs['api']
            self._build(kwargs)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)

    def _get(self):
        """Build an object around an existing DynECT Active Failover Service"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _post(self, address, failover_mode, failover_data, monitor,
              contact_nickname, auto_recover=None, notify_events=None,
              syslog_server=None, syslog_port=None, syslog_ident=None,
              syslog_facility=None, ttl=None, syslog_probe_fmt=None,
              syslog_status_fmt=None, syslog_delivery=None,
              recovery_delay=None):
        """Create a new Active Failover Service on the DynECT System"""
        self._address = address
        self._failover_mode = failover_mode
        self._failover_data = failover_data
        self._monitor = monitor
        self._monitor.zone = self._zone
        self._monitor.fqdn = self._fqdn
        self._contact_nickname = contact_nickname
        self._auto_recover = auto_recover
        self._notify_events = notify_events
        self._syslog_server = syslog_server
        self._syslog_port = syslog_port
        self._syslog_ident = syslog_ident
        self._syslog_facility = syslog_facility
        self._syslog_delivery = syslog_delivery
        self._syslog_probe_fmt = syslog_probe_fmt
        self._syslog_status_fmt = syslog_status_fmt
        self._recovery_delay = recovery_delay
        self._ttl = ttl
        self.api_args = {'address': self._address,
                         'failover_mode': self._failover_mode,
                         'failover_data': self._failover_data,
                         'monitor': self.monitor.to_json(),
                         'contact_nickname': self._contact_nickname}
        if syslog_probe_fmt:
            self.api_args['syslog_probe_fmt'] = self._syslog_probe_fmt
        if syslog_status_fmt:
            self.api_args['syslog_status_fmt'] = self._syslog_status_fmt
        if recovery_delay:
            self.api_args['recovery_delay'] = self._recovery_delay
        if syslog_facility:
            self.api_args['syslog_facility'] = self._syslog_facility
        if syslog_delivery:
            self.api_args['syslog_delivery'] = self._syslog_delivery
        if syslog_ident:
            self.api_args['syslog_ident'] = self._syslog_ident
        if notify_events:
            self.api_args['notify_events'] = self._notify_events
        if syslog_server:
            self.api_args['syslog_server'] = self._syslog_server
        if syslog_port:
            self.api_args['syslog_port'] = self._syslog_port

        response = DynectSession.get_session().execute(self.uri, 'POST',
                                                       self.api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build this object from the data returned in an API response"""
        self._task_id = None
        for key, val in data.items():
            if key == 'monitor':
                self._monitor = HealthMonitor(**val)
            elif key == 'active':
                self._active = Active(val)
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    def _update(self, api_args):
        """Update this :class:`ActiveFailover`, via the API, with the args in
        api_args
        """
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    @property
    def task(self):
        """:class:`Task` for most recent system action
        on this :class:`ActiveFailover`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    @property
    def zone(self):
        """The zone to attach this :class:`ActiveFailover` service to"""
        return self._zone

    @zone.setter
    def zone(self, value):
        pass

    @property
    def fqdn(self):
        """The FQDN where this :class:`ActiveFailover` service will be attached
        """
        return self._fqdn

    @fqdn.setter
    def fqdn(self, value):
        pass

    @property
    def active(self):
        """Return whether or not this :class:`ActiveFailover` service is
        active. When setting directly, rather than using activate/deactivate
        valid arguments are 'Y' or True to activate, or 'N' or False to
        deactivate.

        Note: If your service is already active and you try to activate it,
        nothing will happen. And vice versa for deactivation.

        :returns: An :class:`Active` object representing the current state of
            this :class:`ActiveFailover` Service
        """
        self._get()
        return self._active

    @active.setter
    def active(self, value):
        deactivate = ('N', False)
        activate = ('Y', True)
        if value in deactivate and self.active:
            self.deactivate()
        elif value in activate and not self.active:
            self.activate()

    @property
    def address(self):
        """IPv4 Address or FQDN being monitored by this :class:`ActiveFailover`
        service
        """
        return self._address

    @address.setter
    def address(self, value):
        self._address = value
        api_args = {'address': self._address,
                    'failover_mode': self._failover_mode,
                    'failover_data': self._failover_data,
                    'monitor': self.monitor.to_json(),
                    'contact_nickname': self._contact_nickname}
        self._update(api_args)

    @property
    def failover_mode(self):
        """Indicates the target failover resource type."""
        return self._failover_mode

    @failover_mode.setter
    def failover_mode(self, value):
        self._failover_mode = value
        self.api_args['failover_mode'] = self._failover_mode
        self._update(self.api_args)

    @property
    def failover_data(self):
        """The IPv4 Address or CNAME data for the failover target"""
        return self._failover_data

    @failover_data.setter
    def failover_data(self, value):
        self._failover_data = value
        self.api_args['failover_data'] = self._failover_data
        self._update(self.api_args)

    @property
    def monitor(self):
        """The :class:`HealthMonitor` for this :class:`ActiveFailover` service
        """
        return self._monitor

    @monitor.setter
    def monitor(self, value):
        self._monitor = value
        self.api_args['monitor'] = self._monitor.to_json()
        self._update(self.api_args)

    @property
    def contact_nickname(self):
        """Name of contact to receive notifications from this
        :class:`ActiveFailover` service
        """
        return self._contact_nickname

    @contact_nickname.setter
    def contact_nickname(self, value):
        self._contact_nickname = value
        self.api_args['contact_nickname'] = self._contact_nickname
        self._update(self.api_args)

    @property
    def auto_recover(self):
        """Indicates whether this service should restore its original state
        when the source IPs resume online status
        """
        return self._auto_recover

    @auto_recover.setter
    def auto_recover(self, value):
        self._auto_recover = value
        api_args = self.api_args
        api_args['auto_recover'] = self._auto_recover
        self._update(api_args)

    @property
    def notify_events(self):
        """A comma separated list of what events trigger notifications"""
        return self._notify_events

    @notify_events.setter
    def notify_events(self, value):
        for val in value:
            if val not in self.valid_notify_events:
                raise DynectInvalidArgumentError('notify_events', val,
                                                 self.valid_notify_events)
        value = ','.join(value)
        api_args = self.api_args
        api_args['notify_events'] = value
        self._update(api_args)

    def recover(self):
        """Recover this :class:`ActiveFailover` service"""
        api_args = {'recover': 'Y'}
        self._update(api_args)

    @property
    def syslog_server(self):
        """The Hostname or IP address of a server to receive syslog
        notifications on monitoring events
        """
        self._get()
        return self._syslog_server

    @syslog_server.setter
    def syslog_server(self, value):
        self._syslog_server = value
        api_args = self.api_args
        api_args['syslog_server'] = self._syslog_server
        self._update(api_args)

    @property
    def syslog_port(self):
        """The port where the remote syslog server listens"""
        self._get()
        return self._syslog_port

    @syslog_port.setter
    def syslog_port(self, value):
        self._syslog_port = value
        api_args = self.api_args
        api_args['syslog_port'] = self._syslog_port
        self._update(api_args)

    @property
    def syslog_ident(self):
        """The ident to use when sending syslog notifications"""
        self._get()
        return self._syslog_ident

    @syslog_ident.setter
    def syslog_ident(self, value):
        self._syslog_ident = value
        api_args = self.api_args
        api_args['syslog_ident'] = self._syslog_ident
        self._update(api_args)

    @property
    def syslog_facility(self):
        """The syslog facility to use when sending syslog notifications"""
        self._get()
        return self._syslog_facility

    @syslog_facility.setter
    def syslog_facility(self, value):
        self._syslog_facility = value
        api_args = self.api_args
        api_args['syslog_facility'] = self._syslog_facility
        self._update(api_args)

    @property
    def syslog_delivery(self):
        self._get()
        return self._syslog_delivery

    @syslog_delivery.setter
    def syslog_delivery(self, value):
        api_args = {'syslog_delivery': value}
        self._update(api_args)

    @property
    def syslog_probe_format(self):
        self._get()
        return self._syslog_probe_fmt

    @syslog_probe_format.setter
    def syslog_probe_format(self, value):
        api_args = {'syslog_probe_fmt': value}
        self._update(api_args)

    @property
    def syslog_status_format(self):
        self._get()
        return self._syslog_status_fmt

    @syslog_status_format.setter
    def syslog_status_format(self, value):
        api_args = {'syslog_status_fmt': value}
        self._update(api_args)

    @property
    def recovery_delay(self):
        self._get()
        return self._recovery_delay

    @recovery_delay.setter
    def recovery_delay(self, value):
        api_args = {'recovery_delay': value}
        self._update(api_args)

    @property
    def ttl(self):
        """Time To Live in seconds of records in the service. Must be less than
        1/2 of the Health Probe's monitoring interval
        """
        return self._ttl

    @ttl.setter
    def ttl(self, value):
        self._ttl = value
        api_args = self.api_args
        api_args['ttl'] = self._ttl
        self._update(api_args)

    def activate(self):
        """Activate this :class:`ActiveFailover` service"""
        api_args = {'activate': True}
        self._update(api_args)

    def deactivate(self):
        """Deactivate this :class:`ActiveFailover` service"""
        api_args = {'deactivate': True}
        self._update(api_args)

    def delete(self):
        """Delete this :class:`ActiveFailover` service from the Dynect System
        """
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __str__(self):
        """str override"""
        return force_unicode('<ActiveFailover>: {}').format(self._fqdn)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#9
0
文件: gslb.py 项目: Raz71/dyn-python
class GSLB(object):
    """A Global Server Load Balancing (GSLB) service"""

    def __init__(self, zone, fqdn, *args, **kwargs):
        """Create a :class:`GSLB` object

        :param auto_recover: Indicates whether or not the service should
            automatically come out of failover when the IP addresses resume
            active status or if the service should remain in failover until
            manually reset. Must be 'Y' or 'N'
        :param ttl: Time To Live in seconds of records in the service. Must be
            less than 1/2 of the Health Probe's monitoring interval. Must be
            one of 30, 60, 150, 300, or 450
        :param notify_events: A comma separated list of the events which
            trigger notifications. Must be one of 'ip', 'svc', or 'nosrv'
        :param syslog_server: The Hostname or IP address of a server to receive
            syslog notifications on monitoring events
        :param syslog_port: The port where the remote syslog server listens for
            notifications
        :param syslog_ident: The ident to use when sending syslog notifications
        :param syslog_facility: The syslog facility to use when sending syslog
            notifications. Must be one of 'kern', 'user', 'mail', 'daemon',
            'auth', 'syslog', 'lpr', 'news', 'uucp', 'cron', 'authpriv', 'ftp',
            'ntp', 'security', 'console', 'local0', 'local1', 'local2',
            'local3', 'local4', 'local5', 'local6', or 'local7'
        :param syslog_delivery: The syslog delivery action type. 'all' will
            deliver notifications no matter what the endpoint state. 'change'
            (default) will deliver only on change in the detected endpoint
            state
        :param region: A list of :class:`GSLBRegion`'s
        :param monitor: The health :class:`Monitor` for this service
        :param contact_nickname: Name of contact to receive notifications
        :param syslog_probe_fmt: see below for format:
        :param syslog_status_fmt: see below for format:
            Use the following format for syslog_xxxx_fmt paramaters.
            %hos	hostname
            %tim	current timestamp or monitored interval
            %reg	region code
            %sta	status
            %ser	record serial
            %rda	rdata
            %sit	monitoring site
            %rti	response time
            %msg	message from monitoring
            %adr	address of monitored node
            %med	median value
            %rts	response times (RTTM)
        :param recovery_delay: number of up status polling intervals to
            consider service up
        """

        super(GSLB, self).__init__()
        self.valid_auto_recover = ('Y', 'N')
        self.valid_ttls = (30, 60, 150, 300, 450)
        self.valid_notify_events = ('ip', 'svc', 'nosrv')
        self.valid_syslog_facility = ('kern', 'user', 'mail', 'daemon', 'auth',
                                      'syslog', 'lpr', 'news', 'uucp', 'cron',
                                      'authpriv', 'ftp', 'ntp', 'security',
                                      'console', 'local0', 'local1', 'local2',
                                      'local3', 'local4', 'local5', 'local6',
                                      'local7')
        self._zone = zone
        self._fqdn = fqdn
        self.uri = '/GSLB/{}/{}/'.format(self._zone, self._fqdn)
        self._auto_recover = self._ttl = self._notify_events = None
        self._syslog_server = self._syslog_port = self._syslog_ident = None
        self._syslog_facility = self._monitor = self._contact_nickname = None
        self._syslog_probe_fmt = self._syslog_status_fmt = None
        self._active = self._status = self._syslog_delivery = None
        self._task_id = None
        self._recovery_delay = None
        self._region = APIList(DynectSession.get_session, 'region')
        if 'api' in kwargs:
            del kwargs['api']
            self._build(kwargs)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)
        self._region.uri = self.uri

    def _post(self, contact_nickname, region, auto_recover=None, ttl=None,
              notify_events=None, syslog_server=None, syslog_port=514,
              syslog_ident='dynect', syslog_facility='daemon',
              syslog_probe_fmt=None, syslog_status_fmt=None, monitor=None,
              syslog_delivery='change', recovery_delay=None):
        """Create a new :class:`GSLB` service object on the DynECT System"""
        self._auto_recover = auto_recover
        self._ttl = ttl
        self._notify_events = notify_events
        self._syslog_server = syslog_server
        self._syslog_port = syslog_port
        self._syslog_ident = syslog_ident
        self._syslog_facility = syslog_facility
        self._syslog_delivery = syslog_delivery
        self._syslog_probe_fmt = syslog_probe_fmt
        self._syslog_status_fmt = syslog_status_fmt
        self._recovery_delay = recovery_delay
        self._region += region
        self._monitor = monitor
        self._contact_nickname = contact_nickname
        api_args = {'contact_nickname': self._contact_nickname,
                    'region': [r._json for r in self._region]}
        if auto_recover:
            api_args['auto_recover'] = self._auto_recover
        if ttl:
            api_args['ttl'] = self._ttl
        if notify_events:
            api_args['notify_events'] = self._notify_events
        if syslog_server:
            api_args['syslog_server'] = self._syslog_server
        if syslog_port:
            api_args['syslog_port'] = self._syslog_port
        if syslog_ident:
            api_args['syslog_ident'] = self._syslog_ident
        if syslog_facility:
            api_args['syslog_facility'] = self._syslog_facility
        if syslog_delivery:
            api_args['syslog_delivery'] = self._syslog_delivery
        if syslog_probe_fmt:
            api_args['syslog_probe_fmt'] = self._syslog_probe_fmt
        if syslog_status_fmt:
            api_args['syslog_status_fmt'] = self._syslog_status_fmt
        if recovery_delay:
            api_args['recovery_delay'] = self._recovery_delay
        if monitor:
            api_args['monitor'] = self._monitor.to_json()
            self._monitor.zone = self._zone
            self._monitor.fqdn = self._fqdn
        response = DynectSession.get_session().execute(self.uri, 'POST',
                                                       api_args)
        self._build(response['data'])

    def _get(self):
        """Get an existing :class:`GSLB` service object"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data, region=True):
        """Private method which builds the objects fields based on the data
        returned by an API call

        :param data: the data from the JSON respnose
        :param region: Boolean flag specifying whether to rebuild the region
            objects or not
        """
        for key, val in data.items():
            if key == 'region':
                if region:
                    self._region = APIList(DynectSession.get_session, 'region')
                    for region in val:
                        region_code = region.pop('region_code', None)
                        self._region.append(GSLBRegion(self._zone, self._fqdn,
                                                       region_code, **region))
            elif key == 'monitor':
                # We already have the monitor object, no need to rebuild it
                pass
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)
        self._region.uri = self.uri

    @property
    def task(self):
        """:class:`Task` for most recent system action on this :class:`GSLB`.
        """
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def sync(self):
        """Sync this :class:`GSLB` object with the DynECT System"""
        self._get()

    def activate(self):
        """Activate this :class:`GSLB` service on the DynECT System"""
        api_args = {'activate': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    def deactivate(self):
        """Deactivate this :class:`GSLB` service on the DynECT System"""
        api_args = {'deactivate': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    def recover(self, address=None):
        """Recover the GSLB service on the designated zone node or a specific
        node IP within the service
        """
        api_args = {}
        if address:
            api_args['recoverip'] = True
            api_args['address'] = address
        else:
            api_args['recover'] = True
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def auto_recover(self):
        """Indicates whether or not the service should automatically come out
        of failover when the IP addresses resume active status or if the
        service should remain in failover until manually reset. Must be 'Y' or
        'N'
        """
        return self._auto_recover

    @auto_recover.setter
    def auto_recover(self, value):
        if value not in self.valid_auto_recover:
            raise DynectInvalidArgumentError('auto_recover', value,
                                             self.valid_auto_recover)
        self._auto_recover = value
        api_args = {'auto_recover': self._auto_recover}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def status(self):
        """The current state of the service. Will be one of 'unk', 'ok',
        'trouble', or 'failover'
        """
        api_args = {}
        respnose = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._status = respnose['data']['status']
        return self._status

    @status.setter
    def status(self, value):
        pass

    @property
    def active(self):
        """Indicates if the service is active. When setting directly, rather
        than using activate/deactivate valid arguments are 'Y' or True to
        activate, or 'N' or False to deactivate. Note: If your service is
        already active and you try to activate it, nothing will happen. And
        vice versa for deactivation.

        :returns: An :class:`Active` object representing the current state of
            this :class:`GSLB` Service
        """
        return self._active

    @active.setter
    def active(self, value):
        deactivate = ('N', False)
        activate = ('Y', True)
        if value in deactivate and self.active:
            self.deactivate()
        elif value in activate and not self.active:
            self.activate()

    @property
    def ttl(self):
        """Time To Live in seconds of records in the service. Must be less than
        1/2 of the Health Probe's monitoring interval. Must be one of 30, 60,
        150, 300, or 450
        """
        return self._ttl

    @ttl.setter
    def ttl(self, value):
        if value not in self.valid_ttls:
            raise DynectInvalidArgumentError('ttl', value, self.valid_ttls)
        self._ttl = value
        api_args = {'ttl': self._ttl}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def notify_events(self):
        """A comma separated list of the events which trigger notifications.
        Must be one of 'ip', 'svc', or 'nosrv'
        """
        return self._notify_events

    @notify_events.setter
    def notify_events(self, value):
        if value not in self.valid_notify_events:
            raise DynectInvalidArgumentError('notify_events', value,
                                             self.valid_notify_events)
        self._notify_events = value
        api_args = {'notify_events': self._notify_events}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_server(self):
        """The Hostname or IP address of a server to receive syslog
        notifications on monitoring events
        """
        self._get()
        return self._syslog_server

    @syslog_server.setter
    def syslog_server(self, value):
        self._syslog_server = value
        api_args = {'syslog_server': self._syslog_server}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_port(self):
        """The port where the remote syslog server listens for notifications"""
        self._get()
        return self._syslog_port

    @syslog_port.setter
    def syslog_port(self, value):
        self._syslog_port = value
        api_args = {'syslog_port': self._syslog_port}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_ident(self):
        """The ident to use when sending syslog notifications"""
        self._get()
        return self._syslog_ident

    @syslog_ident.setter
    def syslog_ident(self, value):
        self._syslog_ident = value
        api_args = {'syslog_ident': self._syslog_ident}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_facility(self):
        """The syslog facility to use when sending syslog notifications. Must
        be one of 'kern', 'user', 'mail', 'daemon', 'auth', 'syslog', 'lpr',
        'news', 'uucp', 'cron', 'authpriv', 'ftp', 'ntp', 'security',
        'console', 'local0', 'local1', 'local2', 'local3', 'local4', 'local5',
        'local6', or 'local7'
        """
        self._get()
        return self._syslog_facility

    @syslog_facility.setter
    def syslog_facility(self, value):
        if value not in self.valid_syslog_facility:
            raise DynectInvalidArgumentError('syslog_facility', value,
                                             self.valid_syslog_facility)
        self._syslog_facility = value
        api_args = {'syslog_facility': self._syslog_facility}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_delivery(self):
        self._get()
        return self._syslog_delivery

    @syslog_delivery.setter
    def syslog_delivery(self, value):
        api_args = {'syslog_delivery': value}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_probe_format(self):
        self._get()
        return self._syslog_probe_fmt

    @syslog_probe_format.setter
    def syslog_probe_format(self, value):
        api_args = {'syslog_probe_fmt': value}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def syslog_status_format(self):
        self._get()
        return self._syslog_status_fmt

    @syslog_status_format.setter
    def syslog_status_format(self, value):
        api_args = {'syslog_status_fmt': value}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def recovery_delay(self):
        self._get()
        return self._recovery_delay

    @recovery_delay.setter
    def recovery_delay(self, value):
        api_args = {'recovery_delay': value}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    @property
    def region(self):
        """A list of :class:`GSLBRegion`'s"""
        return self._region

    @region.setter
    def region(self, value):
        if isinstance(value, list) and not isinstance(value, APIList):
            self._region = APIList(DynectSession.get_session, 'region', None,
                                   value)
        elif isinstance(value, APIList):
            self._region = value
        self._region.uri = self.uri

    @property
    def monitor(self):
        """The health :class:`Monitor` for this service"""
        return self._monitor

    @monitor.setter
    def monitor(self, value):
        # We're only going accept new monitors of type Monitor
        if isinstance(value, Monitor):
            api_args = {'monitor': value.to_json()}
            response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                           api_args)
            self._build(response['data'], region=False)
            self._monitor = value

    @property
    def contact_nickname(self):
        """Name of contact to receive notifications from this :class:`GSLB`
        service
        """
        return self._contact_nickname

    @contact_nickname.setter
    def contact_nickname(self, value):
        self._contact_nickname = value
        api_args = {'contact_nickname': self._contact_nickname}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'], region=False)

    def delete(self):
        """Delete this :class:`GSLB` service from the DynECT System"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __str__(self):
        """str override"""
        return force_unicode('<GSLB>: {}').format(self._fqdn)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#10
0
文件: gslb.py 项目: Raz71/dyn-python
class GSLBRegion(object):
    """docstring for GSLBRegion"""

    def __init__(self, zone, fqdn, region_code, *args, **kwargs):
        """Create a :class:`GSLBRegion` object

        :param zone: Zone monitored by this :class:`GSLBRegion`
        :param fqdn: The fqdn of the specific node which will be monitored by
            this :class:`GSLBRegion`
        :param region_code: ISO region code of this :class:`GSLBRegion`
        :param pool: (*arg) The IP Pool list for this :class:`GSLBRegion`
        :param serve_count: How many records will be returned in each DNS
            response
        :param failover_mode: How the :class:`GSLBRegion` should failover. Must
            be one of 'ip', 'cname', 'region', 'global'
        :param failover_data: Dependent upon failover_mode. Must be one of
            'ip', 'cname', 'region', 'global'
        """
        super(GSLBRegion, self).__init__()
        self.valid_region_codes = ('US West', 'US Central', 'US East', 'Asia',
                                   'EU West', 'EU Central', 'EU East',
                                   'global')

        self.valid_modes = ('ip', 'cname', 'region', 'global')
        self._zone = zone
        self._fqdn = fqdn
        self._pool = self._serve_count = self._failover_mode = None
        self._failover_data = None
        self._task_id = None
        if region_code not in self.valid_region_codes:
            raise DynectInvalidArgumentError('region_code', region_code,
                                             self.valid_region_codes)
        self._region_code = region_code
        self.uri = '/GSLBRegion/{}/{}/{}/'.format(self._zone, self._fqdn,
                                                  self._region_code)
        self._pool = []
        if len(args) == 0 and len(kwargs) == 0:
            self._get()
        if len(kwargs) > 0:
            self._build(kwargs)
        elif len(args) > 0:
            for pool in args[0]:
                if isinstance(pool, dict):
                    self._pool.append(GSLBRegionPoolEntry(self._zone,
                                                          self._fqdn,
                                                          self._region_code,
                                                          **pool))
                else:
                    self._pool.append(pool)

    def _post(self, pool, serve_count=None, failover_mode=None,
              failover_data=None):
        """Create a new :class:`GSLBRegion` on the DynECT System"""
        self._pool = pool
        self._serve_count = serve_count
        self._failover_mode = failover_mode
        self._failover_data = failover_data
        uri = '/GSLBRegion/{}/{}/'.format(self._zone, self._fqdn)
        api_args = {'pool': self._pool.to_json(),
                    'region_code': self._region_code}
        if serve_count:
            api_args['serve_count'] = self._serve_count
        if self._failover_mode:
            if self._failover_mode not in self.valid_modes:
                raise DynectInvalidArgumentError('failover_mode',
                                                 self._failover_mode,
                                                 self.valid_modes)
            api_args['failover_mode'] = self._failover_mode
        if self._failover_data:
            if self._failover_data not in self.valid_modes:
                raise DynectInvalidArgumentError('failover_data',
                                                 self._failover_data,
                                                 self.valid_modes)
            api_args['failover_data'] = self._failover_data
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        self._build(response['data'])

    def _get(self):
        """Get an existing :class:`GSLBRegion` object"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _update(self, api_args):
        """Private udpate method for PUT commands"""
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        self._pool = []
        for key, val in data.items():
            if key == 'pool':
                for pool in val:
                    if isinstance(pool, dict):
                        self._pool.append(GSLBRegionPoolEntry(
                            self._zone, self._fqdn, self._region_code,
                            **pool)
                        )
                    else:
                        self._pool.append(pool)
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system
        action on this :class:`ActiveFailover`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def sync(self):
        """Sync this :class:`GSLBRegion` object with the DynECT System"""
        self._get()

    @property
    def zone(self):
        """Zone monitored by this :class:`GSLBRegion`"""
        return self._zone

    @zone.setter
    def zone(self, value):
        pass

    @property
    def fqdn(self):
        """The fqdn of the specific node which will be monitored by this
        :class:`GSLBRegion`
        """
        return self._fqdn

    @fqdn.setter
    def fqdn(self, value):
        pass

    @property
    def region_code(self):
        """ISO region code of this :class:`GSLBRegion`"""
        return self._region_code

    @region_code.setter
    def region_code(self, value):
        pass

    @property
    def serve_count(self):
        """How many records will be returned in each DNS response"""
        return self._serve_count

    @serve_count.setter
    def serve_count(self, value):
        self._serve_count = value
        api_args = {'serve_count': self._serve_count}
        self._update(api_args)

    @property
    def failover_mode(self):
        """How the :class:`GSLBRegion` should failover. Must be one of 'ip',
        'cname', 'region', 'global'
        """
        return self._failover_mode

    @failover_mode.setter
    def failover_mode(self, value):
        self._failover_mode = value
        api_args = {'failover_mode': self._failover_mode}
        self._update(api_args)

    @property
    def failover_data(self):
        """Dependent upon failover_mode. Must be one of 'ip', 'cname',
        'region', 'global'
        """
        return self._failover_data

    @failover_data.setter
    def failover_data(self, value):
        self._failover_data = value
        api_args = {'failover_data': self._failover_data}
        self._update(api_args)

    @property
    def pool(self):
        """The IP Pool list for this :class:`GSLBRegion`"""
        return self._pool

    @pool.setter
    def pool(self, value):
        self._pool = value
        api_args = {'pool': self._pool.to_json()}
        self._update(api_args)

    @property
    def _json(self):
        """Convert this :class:`GSLBRegion` to a json blob"""
        output = {'region_code': self.region_code,
                  'pool': [pool.to_json() for pool in self._pool]}
        if self._serve_count:
            output['serve_count'] = self._serve_count
        if self._failover_mode:
            output['failover_mode'] = self._failover_mode
        if self._failover_data:
            output['failover_data'] = self._failover_data
        return output

    def delete(self):
        """Delete this :class:`GSLBRegion`"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __str__(self):
        """str override"""
        return force_unicode('<GSLBRegion>: {}').format(self._region_code)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#11
0
文件: gslb.py 项目: Raz71/dyn-python
class GSLBRegionPoolEntry(object):
    """:class:`GSLBRegionPoolEntry`"""

    def __init__(self, zone, fqdn, region_code, address, *args, **kwargs):
        """Create a :class:`GSLBRegionPoolEntry` object

        :param zone: Zone monitored by this :class:`GSLBRegionPoolEntry`
        :param fqdn: The fqdn of the specific node which will be monitored by
            this :class:`GSLBRegionPoolEntry`
        :param region_code: ISO Region Code for this
            :class:`GSLBRegionPoolEntry`
        :param address: The IP address or FQDN of this Node IP
        :param label: Identifying descriptive information for this
            :class:`GSLBRegionPoolEntry`
        :param weight: A number in the range of 1-14 controlling the order in
            which this :class:`GSLBRegionPoolEntry` will be served
        :param serve_mode: Sets the behavior of this particular record. Must be
            one of 'always', 'obey', 'remove', 'no'
        """
        super(GSLBRegionPoolEntry, self).__init__()
        self.valid_serve_modes = ('always', 'obey', 'remove', 'no')
        self.valid_weight = range(1, 15)
        self._zone = zone
        self._fqdn = fqdn
        self._region_code = region_code
        self._address = address
        self._label = self._weight = self._serve_mode = None
        self._task_id = None

        uri = '/GSLBRegionPoolEntry/{}/{}/{}/{}/'
        self.uri = uri.format(self._zone, self._fqdn, self._region_code,
                              self._address)
        if len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._build(kwargs)

    def _post(self, label=None, weight=None, serve_mode=None):
        """Create a new :class:`GSLBRegionPoolEntry` on the DynECT System"""
        self._label = label
        self._weight = weight
        self._serve_mode = serve_mode
        uri = '/GSLBRegionPoolEntry/{}/{}/{}/'.format(self._zone, self._fqdn,
                                                      self._region_code)
        api_args = {'address': self._address}
        if label:
            api_args['label'] = self._label
        if weight:
            if weight not in self.valid_weight:
                raise DynectInvalidArgumentError('weight', weight,
                                                 self.valid_weight)
            api_args['weight'] = self._weight
        if serve_mode:
            if serve_mode not in self.valid_serve_modes:
                raise DynectInvalidArgumentError('serve_mode', serve_mode,
                                                 self.valid_serve_modes)
            api_args['serve_mode'] = self._serve_mode
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        self._build(response['data'])

    def _get(self):
        """Get an existing :class:`GSLBRegionPoolEntry` object from the DynECT
        System
        """
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    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):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system
        action on this :class:`ActiveFailover`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def sync(self):
        """Sync this :class:`GSLBRegionPoolEntry` object with the DynECT System
        """
        self._get()

    @property
    def zone(self):
        """Zone monitored by this :class:`GSLBRegionPoolEntry`"""
        return self._zone

    @zone.setter
    def zone(self, value):
        pass

    @property
    def fqdn(self):
        """The fqdn of the specific node which will be monitored by this
        :class:`GSLBRegionPoolEntry`
        """
        return self._fqdn

    @fqdn.setter
    def fqdn(self, value):
        pass

    @property
    def region_code(self):
        """ISO Region Code for this :class:`GSLBRegionPoolEntry`"""
        return self._region_code

    @region_code.setter
    def region_code(self, value):
        pass

    @property
    def address(self):
        """The IP address or FQDN of this Node IP"""
        return self._address

    @address.setter
    def address(self, value):
        self._address = value
        api_args = {'new_address': self._address}
        self._update(api_args)

    @property
    def label(self):
        """Identifying descriptive information for this
        :class:`GSLBRegionPoolEntry`
        """
        return self._label

    @label.setter
    def label(self, value):
        self._label = value
        api_args = {'label': self._label}
        self._update(api_args)

    @property
    def weight(self):
        """A number in the range of 1-14 controlling the order in which this
        :class:`GSLBRegionPoolEntry` will be served.
        """
        return self._weight

    @weight.setter
    def weight(self, new_weight):
        if new_weight not in self.valid_weight:
            raise DynectInvalidArgumentError(new_weight,
                                             self.valid_weight)
        self._weight = new_weight
        api_args = {'weight': self._weight}
        self._update(api_args)

    @property
    def serve_mode(self):
        """Sets the behavior of this particular record. Must be one of 'always',
        'obey', 'remove', or 'no'
        """
        return self._serve_mode

    @serve_mode.setter
    def serve_mode(self, new_serve_mode):
        if new_serve_mode not in self.valid_serve_modes:
            raise DynectInvalidArgumentError('serve_mode', new_serve_mode,
                                             self.valid_serve_modes)
        self._serve_mode = new_serve_mode
        api_args = {'serve_mode': self._serve_mode}
        self._update(api_args)

    def to_json(self):
        """Convert this object into a json blob"""
        output = {'address': self._address}
        if self._label:
            output['label'] = self._label
        if self._weight:
            output['weight'] = self._weight
        if self._serve_mode:
            output['serve_mode'] = self._serve_mode
        return output

    def delete(self):
        """Delete this :class:`GSLBRegionPoolEntry` from the DynECT System"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __str__(self):
        """str override"""
        s = force_unicode('<GSLBRegionPoolEntry>: {}')
        return s.format(self._region_code)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#12
0
文件: zones.py 项目: Raz71/dyn-python
class Zone(object):
    """A class representing a DynECT Zone"""

    def __init__(self, name, *args, **kwargs):
        """Create a :class:`Zone` object. Note: When creating a new
            :class:`Zone` if no contact is specified the path to a local zone
            file must be passed to the ``file_name`` param.

        :param name: the name of the zone to create
        :param contact: Administrative contact for this zone
        :param ttl: TTL (in seconds) for records in the zone
        :param serial_style: The style of the zone's serial. Valid values:
            increment, epoch, day, minute
        :param file_name: The path to a valid RFC1035, BIND, or tinydns style
            Master file. Note: this file must be under 1mb in size.
        :param master_ip: The IP of the master server from which to fetch zone
            data for Transferring this :class:`Zone`. Note: This argument is
            required for performing a valid ZoneTransfer operation.
        :param timeout: The time, in minutes, to wait for a zone xfer to
            complete
        """
        super(Zone, self).__init__()
        self.valid_serials = ('increment', 'epoch', 'day', 'minute')
        self._name = name
        self._fqdn = self._name
        if self._fqdn and not self._fqdn.endswith('.'):
            self._fqdn += '.'
        self._contact = self._ttl = self._serial_style = self._serial = None
        self._zone = self._status = None
        self.records = {}
        self._task_id = None
        self.services = {}
        self.uri = '/Zone/{}/'.format(self._name)
        if 'api' in kwargs:
            del kwargs['api']
            for key, val in kwargs.items():
                setattr(self, '_' + key, val)
                self._name = self._zone
                self.uri = '/Zone/{}/'.format(self._name)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)
            self._status = 'active'

    def _post(self, contact=None, ttl=60, serial_style='increment',
              file_name=None, master_ip=None, timeout=None):
        """Create a new :class:`Zone` object on the DynECT System"""
        if contact is None and file_name is None and master_ip is None:
            raise DynectInvalidArgumentError('contact', None)
        if file_name is not None:
            self._post_with_file(file_name)
        elif master_ip is not None:
            self._xfer(master_ip, timeout)
        else:
            self._contact = contact
            self._ttl = ttl
            if serial_style not in self.valid_serials:
                raise DynectInvalidArgumentError(serial_style,
                                                 self.valid_serials)
            self._serial_style = serial_style
            api_args = {'zone': self._name,
                        'rname': self._contact,
                        'ttl': self._ttl,
                        'serial_style': self._serial_style}
            response = DynectSession.get_session().execute(self.uri, 'POST',
                                                           api_args)
            self._build(response['data'])

    def _post_with_file(self, file_name):
        """Create a :class:`Zone` from a RFC1035 style Master file. A ZoneFile
        for BIND or tinydns will also be accepted

        :param file_name: The path to a valid ZoneFile
        """
        full_path = os.path.abspath(file_name)
        file_size = os.path.getsize(full_path)
        if file_size > 1048576:
            raise DynectInvalidArgumentError('Zone File Size', file_size,
                                             'Under 1MB')
        else:
            uri = '/ZoneFile/{}/'.format(self.name)
            f = open(full_path, 'r')
            content = f.read()
            f.close()
            api_args = {'file': content}
            response = DynectSession.get_session().execute(
                uri, 'POST', api_args)
            self.__poll_for_get()
            self._build(response['data'])

    def _xfer(self, master_ip, timeout=None):
        """Create a :class:`Zone` by ZoneTransfer by providing an optional
        master_ip argument.
        """
        uri = '/ZoneTransfer/{}/'.format(self.name)
        api_args = {'master_ip': master_ip}
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        self._build(response['data'])
        time_out = timeout or 10
        count = 0
        while count < time_out:
            response = DynectSession.get_session().execute(uri, 'GET', {})
            if response['status'] == 'running' and response['message'] == '':
                sleep(60)
                count += 1
            else:
                break
        self._get()

    def __poll_for_get(self, n_loops=10, xfer=False, xfer_master_ip=None):
        """For use ONLY by _post_with_file and _xfer. Will wait at MOST
        ``n_loops * 2`` seconds for a successfull GET API response. If no
        successfull get is recieved no error will be raised.
        """
        count = 0
        got = False
        while count < n_loops:
            try:
                self._get()
                got = True
                break
            except DynectGetError:
                sleep(2)
                count += 1
        if not got and xfer:
            uri = '/ZoneTransfer/{}/'.format(self.name)
            api_args = {}
            if xfer_master_ip is not None:
                api_args['master_ip'] = xfer_master_ip
            response = DynectSession.get_session().execute(uri, 'GET',
                                                           api_args)
            error_labels = ['running', 'waiting', 'failed', 'canceled']
            ok_labels = ['ready', 'unpublished', 'ok']
            if response['data']['status'] in error_labels:
                raise DynectCreateError(response['msgs'])
            elif response['data']['status'] in ok_labels:
                self._get()
            else:
                pass  # Should never get here

    def _get(self):
        """Get an existing :class:`Zone` object from the DynECT System"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    def _update(self, api_args):
        """Update this :class:`ActiveFailover`, via the API, with the args in
        api_args
        """
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    @property
    def __root_soa(self):
        """Return the SOA record associated with this Zone"""
        return self.get_all_records_by_type('SOA')[0]

    @property
    def name(self):
        """The name of this :class:`Zone`"""
        return self._name

    @name.setter
    def name(self, value):
        pass

    @property
    def fqdn(self):
        """The name of this :class:`Zone`"""
        return self._fqdn

    @fqdn.setter
    def fqdn(self, value):
        pass

    @property
    def contact(self):
        """The email address of the primary :class:`Contact` associated with
        this :class:`Zone`
        """
        self._contact = self.__root_soa.rname
        return self._contact

    @contact.setter
    def contact(self, value):
        self.__root_soa.rname = value

    @property
    def ttl(self):
        """This :class:`Zone`'s default TTL"""
        self._ttl = self.__root_soa.ttl
        return self._ttl

    @ttl.setter
    def ttl(self, value):
        self.__root_soa.ttl = value

    @property
    def serial(self):
        """The current serial of this :class:`Zone`"""
        self._get()
        return self._serial

    @serial.setter
    def serial(self, value):
        pass

    @property
    def serial_style(self):
        """The current serial style of this :class:`Zone`"""
        self._get()
        return self._serial_style

    @serial_style.setter
    def serial_style(self, value):
        if value not in self.valid_serials:
            raise DynectInvalidArgumentError('serial_style', value,
                                             self.valid_serials)
        self.__root_soa.serial_style = value

    @property
    def status(self):
        """Convenience property for :class:`Zones`. If a :class:`Zones` is
        frozen the status will read as `'frozen'`, if the :class:`Zones` is not
        frozen the status will read as `'active'`. Because the API does not
        return information about whether or not a :class:`Zones` is frozen
        there will be a few cases where this status will be `None` in order to
        avoid guessing what the current status actually is.
        """
        self._get()
        return self._status

    @status.setter
    def status(self, value):
        pass

    def freeze(self):
        """Causes the zone to become frozen. Freezing a zone prevents changes
        to the zone until it is thawed.
        """
        api_args = {'freeze': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])
        if response['status'] == 'success':
            self._status = 'frozen'

    def thaw(self):
        """Causes the zone to become thawed. Thawing a frozen zone allows
        changes to again be made to the zone.
        """
        api_args = {'thaw': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])
        if response['status'] == 'success':
            self._status = 'active'

    def publish(self, notes=None):
        """Causes all pending changes to become part of the zone. The serial
        number increments based on its serial style and the data is pushed out
        to the nameservers.
        """
        api_args = {'publish': True}
        if notes:
            api_args['notes'] = notes
        self._update(api_args)

    @property
    def task(self):
        """:class:`Task` for most recent system action on this :class:`Zone`.
        """
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def get_notes(self, offset=None, limit=None):
        """Generates a report containing the Zone Notes for this :class:`Zone`

        :param offset: The starting point at which to retrieve the notes
        :param limit: The maximum number of notes to be retrieved
        :return: A :class:`list` of :class:`dict` containing :class:`Zone`
            Notes
        """
        uri = '/ZoneNoteReport/'
        api_args = {'zone': self.name}
        if offset:
            api_args['offset'] = offset
        if limit:
            api_args['limit'] = limit
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        return response['data']

    def add_record(self, name=None, record_type='A', *args, **kwargs):
        """Adds an a record with the provided name and data to this
        :class:`Zone`

        :param name: The name of the node where this record will be added
        :param record_type: The type of record you would like to add.
            Valid record_type arguments are: 'A', 'AAAA', 'CERT', 'CNAME',
            'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'KX', 'LOC', 'IPSECKEY',
            'MX', 'NAPTR', 'PTR', 'PX', 'NSAP', 'RP', 'NS', 'SOA', 'SPF',
            'SRV', and 'TXT'.
        :param args: Non-keyword arguments to pass to the Record constructor
        :param kwargs: Keyword arguments to pass to the Record constructor
        """
        fqdn = name + '.' + self.name + '.' if name else self.name + '.'
        # noinspection PyCallingNonCallable
        rec = RECS[record_type](self.name, fqdn, *args, **kwargs)
        if record_type in self.records:
            self.records[record_type].append(rec)
        else:
            self.records[record_type] = [rec]
        return rec

    def add_service(self, name=None, service_type=None, *args, **kwargs):
        """Add the specified service type to this zone, or to a node under this
        zone

        :param name: The name of the :class:`Node` where this service will be
            attached to or `None` to attach it to the root :class:`Node` of
            this :class:`Zone`
        :param service_type: The type of the service you would like to create.
            Valid service_type arguments are: 'ActiveFailover', 'DDNS',
            'DNSSEC', 'DSF', 'GSLB', 'RDNS', 'RTTM', 'HTTPRedirect'
        :param args: Non-keyword arguments to pass to the Record constructor
        :param kwargs: Keyword arguments to pass to the Record constructor
        """
        constructors = {'ActiveFailover': ActiveFailover,
                        'DDNS': DynamicDNS,
                        'DNSSEC': DNSSEC,
                        'DSF': TrafficDirector,
                        'GSLB': GSLB,
                        'RDNS': ReverseDNS,
                        'RTTM': RTTM,
                        'HTTPRedirect': HTTPRedirect}
        fqdn = self.name + '.'
        if name:
            fqdn = name + '.' + fqdn
        if service_type == 'DNSSEC':
            # noinspection PyCallingNonCallable
            service = constructors[service_type](self.name, *args, **kwargs)
        else:
            # noinspection PyCallingNonCallable
            service = constructors[service_type](self.name, fqdn, *args,
                                                 **kwargs)
        if service_type in self.services:
            self.services[service_type].append(service)
        else:
            self.services[service_type] = [service]
        return service

    def get_all_nodes(self):
        """Returns a list of Node Objects for all subnodes in Zone (Excluding
        the Zone itself.)
        """
        api_args = {}
        uri = '/NodeList/{}/'.format(self._name)
        response = DynectSession.get_session().execute(uri, 'GET',
                                                       api_args)
        nodes = [Node(self._name, fqdn) for fqdn in response['data'] if
                 fqdn != self._name]
        return nodes

    def get_node(self, node=None):
        """Returns all DNS Records for that particular node

        :param node: The name of the Node you wish to access, or `None` to get
            the root :class:`Node` of this :class:`Zone`
        """
        if node:
            fqdn = node + '.' + self.name + '.'
        else:
            fqdn = self.name + '.'
        return Node(self.name, fqdn)

    def get_all_records(self):
        """Retrieve a list of all record resources for the specified node and
        zone combination as well as all records from any Base_Record below that
        point on the zone hierarchy

        :return: A :class:`List` of all the :class:`DNSRecord`'s under this
            :class:`Zone`
        """
        self.records = {}
        uri = '/AllRecord/{}/'.format(self._name)
        if self.fqdn is not None:
            uri += '{}/'.format(self.fqdn)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        # Strip out empty record_type lists
        record_lists = {label: rec_list for label, rec_list in
                        response['data'].items() if rec_list != []}
        records = {}
        for key, record_list in record_lists.items():
            search = key.split('_')[0].upper()
            try:
                constructor = RECS[search]
            except KeyError:
                constructor = RECS['UNKNOWN']
            list_records = []
            for record in record_list:
                del record['zone']
                fqdn = record['fqdn']
                del record['fqdn']
                # Unpack rdata
                for r_key, r_val in record['rdata'].items():
                    record[r_key] = r_val
                record['create'] = False
                list_records.append(constructor(self._name, fqdn, **record))
            records[key] = list_records
        return records

    def get_all_records_by_type(self, record_type):
        """Get a list of all :class:`DNSRecord` of type ``record_type`` which
        are owned by this node.

        :param record_type: The type of :class:`DNSRecord` you wish returned.
            Valid record_type arguments are: 'A', 'AAAA', 'CERT', 'CNAME',
            'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'KX', 'LOC', 'IPSECKEY',
            'MX', 'NAPTR', 'PTR', 'PX', 'NSAP', 'RP', 'NS', 'SOA', 'SPF',
            'SRV', and 'TXT'.
        :return: A :class:`List` of :class:`DNSRecord`'s
        """
        names = {'A': 'ARecord', 'AAAA': 'AAAARecord', 'ALIAS': 'ALIASRecord',
                 'CDS': 'CDSRecord', 'CDNSKEY': 'CDNSKEYRecord',
                 'CERT': 'CERTRecord', 'CSYNC': 'CSYNCRecord',
                 'CNAME': 'CNAMERecord', 'DHCID': 'DHCIDRecord',
                 'DNAME': 'DNAMERecord', 'DNSKEY': 'DNSKEYRecord',
                 'DS': 'DSRecord', 'KEY': 'KEYRecord', 'KX': 'KXRecord',
                 'LOC': 'LOCRecord', 'IPSECKEY': 'IPSECKEYRecord',
                 'MX': 'MXRecord', 'NAPTR': 'NAPTRRecord', 'PTR': 'PTRRecord',
                 'PX': 'PXRecord', 'NSAP': 'NSAPRecord', 'RP': 'RPRecord',
                 'NS': 'NSRecord', 'SOA': 'SOARecord', 'SPF': 'SPFRecord',
                 'SRV': 'SRVRecord', 'TLSA': 'TLSARecord', 'TXT': 'TXTRecord',
                 'SSHFP': 'SSHFPRecord'}

        constructor = RECS[record_type]
        uri = '/{}/{}/{}/'.format(names[record_type], self._name, self.fqdn)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        records = []
        for record in response['data']:
            fqdn = record['fqdn']
            del record['fqdn']
            del record['zone']
            # Unpack rdata
            for key, val in record['rdata'].items():
                record[key] = val
            del record['rdata']
            record['create'] = False
            records.append(constructor(self._name, fqdn, **record))
        return records

    def get_any_records(self):
        """Retrieve a list of all :class:`DNSRecord`'s associated with this
        :class:`Zone`
        """
        if self.fqdn is None:
            return
        api_args = {'detail': 'Y'}
        uri = '/ANYRecord/{}/{}/'.format(self._name, self.fqdn)
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        # Strip out empty record_type lists
        record_lists = {label: rec_list for label, rec_list in
                        response['data'].items() if rec_list != []}
        records = {}
        for key, record_list in record_lists.items():
            search = key.split('_')[0].upper()
            try:
                constructor = RECS[search]
            except KeyError:
                constructor = RECS['UNKNOWN']
            list_records = []
            for record in record_list:
                del record['zone']
                del record['fqdn']
                # Unpack rdata
                for r_key, r_val in record['rdata'].items():
                    record[r_key] = r_val
                record['create'] = False
                list_records.append(constructor(self._name, self.fqdn,
                                                **record))
            records[key] = list_records
        return records

    def get_all_active_failovers(self):
        """Retrieve a list of all :class:`ActiveFailover` services associated
        with this :class:`Zone`

        :return: A :class:`List` of :class:`ActiveFailover` Services
        """
        uri = '/Failover/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        afos = []
        for failover in response['data']:
            del failover['zone']
            del failover['fqdn']
            afos.append(ActiveFailover(self._name, self._fqdn, api=False,
                                       **failover))
        return afos

    def get_all_ddns(self):
        """Retrieve a list of all :class:`DDNS` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`DDNS` Services
        """
        uri = '/DDNS/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        ddnses = []
        for svc in response['data']:
            del svc['zone']
            del svc['fqdn']
            ddnses.append(
                DynamicDNS(self._name, self._fqdn, api=False, **svc))
        return ddnses

    def get_all_httpredirect(self):
        """Retrieve a list of all :class:`HTTPRedirect` services associated
        with this :class:`Zone`

        :return: A :class:`List` of :class:`HTTPRedirect` Services
        """
        uri = '/HTTPRedirect/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        httpredirs = []
        for httpredir in response['data']:
            del httpredir['zone']
            del httpredir['fqdn']
            httpredirs.append(
                HTTPRedirect(self._name, self._fqdn, api=False, **httpredir))
        return httpredirs

    def get_all_gslb(self):
        """Retrieve a list of all :class:`GSLB` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`GSLB` Services
        """
        uri = '/GSLB/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        gslbs = []
        for gslb_svc in response['data']:
            del gslb_svc['zone']
            del gslb_svc['fqdn']
            gslbs.append(GSLB(self._name, self._fqdn, api=False, **gslb_svc))
        return gslbs

    def get_all_rdns(self):
        """Retrieve a list of all :class:`ReverseDNS` services associated with
        this :class:`Zone`

        :return: A :class:`List` of :class:`ReverseDNS` Services
        """
        uri = '/IPTrack/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        rdnses = []
        for rdns in response['data']:
            del rdns['zone']
            del rdns['fqdn']
            rdnses.append(
                ReverseDNS(self._name, self._fqdn, api=False, **rdns))
        return rdnses

    def get_all_rttm(self):
        """Retrieve a list of all :class:`RTTM` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`RTTM` Services
        """
        uri = '/RTTM/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        rttms = []
        for rttm_svc in response['data']:
            del rttm_svc['zone']
            del rttm_svc['fqdn']
            rttms.append(RTTM(self._name, self._fqdn, api=False, **rttm_svc))
        return rttms

    def get_qps(self, start_ts, end_ts=None, breakdown=None, hosts=None,
                rrecs=None):
        """Generates a report with information about Queries Per Second (QPS)
        for this zone

        :param start_ts: datetime.datetime instance identifying point in time
            for the QPS report
        :param end_ts: datetime.datetime instance indicating the end of the
            data range for the report. Defaults to datetime.datetime.now()
        :param breakdown: By default, most data is aggregated together.
            Valid values ('hosts', 'rrecs', 'zones').
        :param hosts: List of hosts to include in the report.
        :param rrecs: List of record types to include in report.
        :return: A :class:`str` with CSV data
        """
        end_ts = end_ts or datetime.now()
        api_args = {'start_ts': unix_date(start_ts),
                    'end_ts': unix_date(end_ts),
                    'zones': [self.name]}
        if breakdown is not None:
            api_args['breakdown'] = breakdown
        if hosts is not None:
            api_args['hosts'] = hosts
        if rrecs is not None:
            api_args['rrecs'] = rrecs
        response = DynectSession.get_session().execute('/QPSReport/',
                                                       'POST', api_args)
        return response['data']

    def delete(self):
        """Delete this :class:`Zone` and perform nessecary cleanups"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __eq__(self, other):
        """Equivalence operations for easily pulling a :class:`Zone` out of a
        list of :class:`Zone` objects
        """
        if isinstance(other, str):
            return other == self._name
        elif isinstance(other, Zone):
            return other.name == self._name
        return False

    def __ne__(self, other):
        """Non-Equivalence operator"""
        return not self.__eq__(other)

    def __str__(self):
        """str override"""
        return force_unicode('<Zone>: {}').format(self._name)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#13
0
文件: zones.py 项目: Raz71/dyn-python
class SecondaryZone(object):
    """A class representing DynECT Secondary zones"""

    def __init__(self, zone, *args, **kwargs):
        """Create a :class:`SecondaryZone` object

        :param zone: The name of this secondary zone
        :param masters: A list of IPv4 or IPv6 addresses of the master
            nameserver(s) for this zone.
        :param contact_nickname: Name of the :class:`Contact` that will receive
            notifications for this zone
        :param tsig_key_name: Name of the TSIG key that will be used to sign
            transfer requests to this zone's master
        """
        super(SecondaryZone, self).__init__()
        self._zone = self._name = zone
        self.uri = '/Secondary/{}/'.format(self._zone)
        self._masters = self._contact_nickname = self._tsig_key_name = None
        self._task_id = None
        if 'api' in kwargs:
            del kwargs['api']
            for key, val in kwargs.items():
                setattr(self, '_' + key, val)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)

    def _get(self):
        """Get a :class:`SecondaryZone` object from the DynECT System"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _post(self, masters, contact_nickname=None, tsig_key_name=None):
        """Create a new :class:`SecondaryZone` object on the DynECT System"""
        self._masters = masters
        self._contact_nickname = contact_nickname
        self._tsig_key_name = tsig_key_name
        api_args = {'masters': self._masters}
        if contact_nickname:
            api_args['contact_nickname'] = self._contact_nickname
        if tsig_key_name:
            api_args['tsig_key_name'] = self._tsig_key_name
        response = DynectSession.get_session().execute(self.uri, 'POST',
                                                       api_args)
        self._build(response['data'])

    def _update(self, api_args, uri=None):
        """Update this :class:`ActiveFailover`, via the API, with the args in
        api_args
        """
        if not uri:
            uri = self.uri
        response = DynectSession.get_session().execute(uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system action on this :class:`SecondaryZone`.
        """
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    @property
    def zone(self):
        """The name of this :class:`SecondaryZone`"""
        return self._zone

    @zone.setter
    def zone(self, value):
        pass

    @property
    def masters(self):
        """A list of IPv4 or IPv6 addresses of the master nameserver(s) for
        this zone.
         """
        self._get()
        return self._masters

    @masters.setter
    def masters(self, value):
        self._masters = value
        api_args = {'masters': self._masters}
        self._update(api_args)

    @property
    def contact_nickname(self):
        """Name of the :class:`Contact` that will receive notifications for
        this zone
         """
        self._get()
        return self._contact_nickname

    @contact_nickname.setter
    def contact_nickname(self, value):
        self._contact_nickname = value
        api_args = {'contact_nickname': self._contact_nickname}
        self._update(api_args)

    @property
    def tsig_key_name(self):
        """Name of the TSIG key that will be used to sign transfer requests to
        this zone's master
        """
        self._get()
        return self._tsig_key_name

    @tsig_key_name.setter
    def tsig_key_name(self, value):
        self._tsig_key_name = value
        api_args = {'tsig_key_name': self._tsig_key_name}
        self._update(api_args)

    def activate(self):
        """Activates this secondary zone"""
        api_args = {'activate': True}
        self._update(api_args)

    def deactivate(self):
        """Deactivates this secondary zone"""
        api_args = {'deactivate': True}
        self._update(api_args)

    def retransfer(self):
        """Retransfers this secondary zone from its original provider into
        Dyn's Managed DNS
        """
        api_args = {'retransfer': True}
        self._update(api_args)

    def delete(self):
        """Delete this :class:`SecondaryZone`"""
        api_args = {}
        uri = '/Zone/{}/'.format(self._zone)
        DynectSession.get_session().execute(uri, 'DELETE', api_args)

    @property
    def active(self):
        """Reports the status of :class:`SecondaryZone` Y, L or N"""
        self._get()
        return self._active

    @property
    def serial(self):
        """Reports the serial of :class:`SecondaryZone`"""
        api_args = {}
        uri = '/Zone/{}/'.format(self._zone)
        self._update(api_args, uri)
        return self._serial

    def __str__(self):
        """str override"""
        return force_unicode('<SecondaryZone>: {}').format(self._zone)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#14
0
class RegionPoolEntry(object):
    """Creates a new RTTM service region pool entry in the zone/node
    indicated
    """

    def __init__(self, address, label, weight, serve_mode, **kwargs):
        """Create a :class:`RegionPoolEntry` object

        :param address: The IPv4 address or FQDN of this Node IP
        :param label: A descriptive string identifying this IP
        :param weight:  A number from 1-15 describing how often this record
            should be served. The higher the number, the more often the address
            is served
        :param serve_mode: Sets the behavior of this particular record. Must be
            one of 'always', 'obey', 'remove', or 'no'
        """
        super(RegionPoolEntry, self).__init__()
        self.valid_modes = ('always', 'obey', 'remove', 'no')
        self._address = address
        self._label = label
        self._task_id = None
        self._zone = kwargs.get('zone')
        self._fqdn = kwargs.get('fqdn')
        self._region_code = kwargs.get('region_code')
        if weight not in range(1, 16):
            raise DynectInvalidArgumentError('weight', weight, '1-15')
        self._weight = weight
        if serve_mode not in self.valid_modes:
            raise DynectInvalidArgumentError('serve_mode', serve_mode,
                                             self.valid_modes)
        self._serve_mode = serve_mode
        self._log = []
        self._build(kwargs)

    def _update(self, args):
        """Private method for processing various updates"""
        uri = '/RTTMRegionPoolEntry/{}/{}/{}/{}/'.format(self._zone,
                                                         self._fqdn,
                                                         self._region_code,
                                                         self._address)
        response = DynectSession.get_session().execute(uri, 'PUT', args)
        self._build(response['data'])

    def _get(self):
        uri = '/RTTMRegionPoolEntry/{}/{}/{}/{}/'.format(self._zone,
                                                         self._fqdn,
                                                         self._region_code,
                                                         self._address)
        args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', args)
        self._build(response['data'])

    def _build(self, data):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system
        action on this :class:`RegionPoolEntry`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    @property
    def logs(self):
        self._get()
        return self._log

    @logs.setter
    def logs(self, value):
        pass

    @property
    def address(self):
        """The IPv4 address or FQDN of this Node IP"""
        return self._address

    @address.setter
    def address(self, new_address):
        api_args = {'new_address': new_address}
        self._update(api_args)

    @property
    def zone(self):
        """Zone for this :class:`RegionPoolEntry`,
         this is stored locally for REST command completion"""
        return self._zone

    @zone.setter
    def zone(self, zone):
        self._zone = zone

    @property
    def fqdn(self):
        """FQDN for this :class:`RegionPoolEntry`,
         this is stored locally for REST command completion"""
        return self._fqdn

    @fqdn.setter
    def fqdn(self, fqdn):
        self._fqdn = fqdn

    @property
    def region_code(self):
        """region_code for this :class:`RegionPoolEntry`,
         this is stored locally for REST command completion"""
        return self._region_code

    @region_code.setter
    def region_code(self, region_code):
        self._region_code = region_code

    @property
    def label(self):
        """A descriptive string identifying this IP"""
        return self._label

    @label.setter
    def label(self, value):
        self._label = value
        api_args = {'label': self._label}
        self._update(api_args)

    @property
    def weight(self):
        """A number from 1-15 describing how often this record should be
        served. The higher the number, the more often the address is served
        """
        return self._weight

    @weight.setter
    def weight(self, new_weight):
        if new_weight < 1 or new_weight > 15:
            raise DynectInvalidArgumentError('weight', new_weight, '1-15')
        self._weight = new_weight
        api_args = {'weight': self._weight}
        self._update(api_args)

    @property
    def serve_mode(self):
        """Sets the behavior of this particular record"""
        return self._serve_mode

    @serve_mode.setter
    def serve_mode(self, serve_mode):
        if serve_mode not in self.valid_modes:
            raise DynectInvalidArgumentError('serve_mode', serve_mode,
                                             self.valid_modes)
        self._serve_mode = serve_mode
        api_args = {'serve_mode': self._serve_mode}
        self._update(api_args)

    def to_json(self):
        """Return a JSON representation of this RegionPoolEntry"""
        json_blob = {'address': self._address, 'label': self._label,
                     'weight': self._weight, 'serve_mode': self._serve_mode}
        return json_blob

    def delete(self):
        """Delete this :class:`RegionPoolEntry`"""
        uri = '/RTTMRegionPoolEntry/{}/{}/{}/{}/'.format(self._zone,
                                                         self._fqdn,
                                                         self._region_code,
                                                         self._address)
        DynectSession.get_session().execute(uri, 'DELETE', {})

    def __str__(self):
        """str override"""
        return force_unicode('<RTTMRegionPoolEntry>: {}').format(self._address)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#15
0
class SecondaryZone(object):
    """A class representing DynECT Secondary zones"""
    def __init__(self, zone, *args, **kwargs):
        """Create a :class:`SecondaryZone` object

        :param zone: The name of this secondary zone
        :param masters: A list of IPv4 or IPv6 addresses of the master
            nameserver(s) for this zone.
        :param contact_nickname: Name of the :class:`Contact` that will receive
            notifications for this zone
        :param tsig_key_name: Name of the TSIG key that will be used to sign
            transfer requests to this zone's master
        """
        super(SecondaryZone, self).__init__()
        self._zone = self._name = zone
        self.uri = '/Secondary/{}/'.format(self._zone)
        self._masters = self._contact_nickname = self._tsig_key_name = None
        self._task_id = None
        if 'api' in kwargs:
            del kwargs['api']
            for key, val in kwargs.items():
                setattr(self, '_' + key, val)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)

    def _get(self):
        """Get a :class:`SecondaryZone` object from the DynECT System"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _post(self, masters, contact_nickname=None, tsig_key_name=None):
        """Create a new :class:`SecondaryZone` object on the DynECT System"""
        self._masters = masters
        self._contact_nickname = contact_nickname
        self._tsig_key_name = tsig_key_name
        api_args = {'masters': self._masters}
        if contact_nickname:
            api_args['contact_nickname'] = self._contact_nickname
        if tsig_key_name:
            api_args['tsig_key_name'] = self._tsig_key_name
        response = DynectSession.get_session().execute(self.uri, 'POST',
                                                       api_args)
        self._build(response['data'])

    def _update(self, api_args, uri=None):
        """Update this :class:`ActiveFailover`, via the API, with the args in
        api_args
        """
        if not uri:
            uri = self.uri
        response = DynectSession.get_session().execute(uri, 'PUT', api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system action on this :class:`SecondaryZone`.
        """
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    @property
    def zone(self):
        """The name of this :class:`SecondaryZone`"""
        return self._zone

    @zone.setter
    def zone(self, value):
        pass

    @property
    def masters(self):
        """A list of IPv4 or IPv6 addresses of the master nameserver(s) for
        this zone.
         """
        self._get()
        return self._masters

    @masters.setter
    def masters(self, value):
        self._masters = value
        api_args = {'masters': self._masters}
        self._update(api_args)

    @property
    def contact_nickname(self):
        """Name of the :class:`Contact` that will receive notifications for
        this zone
         """
        self._get()
        return self._contact_nickname

    @contact_nickname.setter
    def contact_nickname(self, value):
        self._contact_nickname = value
        api_args = {'contact_nickname': self._contact_nickname}
        self._update(api_args)

    @property
    def tsig_key_name(self):
        """Name of the TSIG key that will be used to sign transfer requests to
        this zone's master
        """
        self._get()
        return self._tsig_key_name

    @tsig_key_name.setter
    def tsig_key_name(self, value):
        self._tsig_key_name = value
        api_args = {'tsig_key_name': self._tsig_key_name}
        self._update(api_args)

    def activate(self):
        """Activates this secondary zone"""
        api_args = {'activate': True}
        self._update(api_args)

    def deactivate(self):
        """Deactivates this secondary zone"""
        api_args = {'deactivate': True}
        self._update(api_args)

    def retransfer(self):
        """Retransfers this secondary zone from its original provider into
        Dyn's Managed DNS
        """
        api_args = {'retransfer': True}
        self._update(api_args)

    def delete(self):
        """Delete this :class:`SecondaryZone`"""
        api_args = {}
        uri = '/Zone/{}/'.format(self._zone)
        DynectSession.get_session().execute(uri, 'DELETE', api_args)

    @property
    def active(self):
        """Reports the status of :class:`SecondaryZone` Y, L or N"""
        self._get()
        return self._active

    @property
    def serial(self):
        """Reports the serial of :class:`SecondaryZone`"""
        api_args = {}
        uri = '/Zone/{}/'.format(self._zone)
        self._update(api_args, uri)
        return self._serial

    def __str__(self):
        """str override"""
        return force_unicode('<SecondaryZone>: {}').format(self._zone)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#16
0
class Zone(object):
    """A class representing a DynECT Zone"""
    def __init__(self, name, *args, **kwargs):
        """Create a :class:`Zone` object. Note: When creating a new
            :class:`Zone` if no contact is specified the path to a local zone
            file must be passed to the ``file_name`` param.

        :param name: the name of the zone to create
        :param contact: Administrative contact for this zone
        :param ttl: TTL (in seconds) for records in the zone
        :param serial_style: The style of the zone's serial. Valid values:
            increment, epoch, day, minute
        :param file_name: The path to a valid RFC1035, BIND, or tinydns style
            Master file. Note: this file must be under 1mb in size.
        :param master_ip: The IP of the master server from which to fetch zone
            data for Transferring this :class:`Zone`. Note: This argument is
            required for performing a valid ZoneTransfer operation.
        :param timeout: The time, in minutes, to wait for a zone xfer to
            complete
        """
        super(Zone, self).__init__()
        self.valid_serials = ('increment', 'epoch', 'day', 'minute')
        self._name = name
        self._fqdn = self._name
        if self._fqdn and not self._fqdn.endswith('.'):
            self._fqdn += '.'
        self._contact = self._ttl = self._serial_style = self._serial = None
        self._zone = self._status = None
        self.records = {}
        self._task_id = None
        self.services = {}
        self.uri = '/Zone/{}/'.format(self._name)
        if 'api' in kwargs:
            del kwargs['api']
            for key, val in kwargs.items():
                setattr(self, '_' + key, val)
                self._name = self._zone
                self.uri = '/Zone/{}/'.format(self._name)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)
            self._status = 'active'

    def _post(self,
              contact=None,
              ttl=60,
              serial_style='increment',
              file_name=None,
              master_ip=None,
              timeout=None):
        """Create a new :class:`Zone` object on the DynECT System"""
        if contact is None and file_name is None and master_ip is None:
            raise DynectInvalidArgumentError('contact', None)
        if file_name is not None:
            self._post_with_file(file_name)
        elif master_ip is not None:
            self._xfer(master_ip, timeout)
        else:
            self._contact = contact
            self._ttl = ttl
            if serial_style not in self.valid_serials:
                raise DynectInvalidArgumentError(serial_style,
                                                 self.valid_serials)
            self._serial_style = serial_style
            api_args = {
                'zone': self._name,
                'rname': self._contact,
                'ttl': self._ttl,
                'serial_style': self._serial_style
            }
            response = DynectSession.get_session().execute(
                self.uri, 'POST', api_args)
            self._build(response['data'])

    def _post_with_file(self, file_name):
        """Create a :class:`Zone` from a RFC1035 style Master file. A ZoneFile
        for BIND or tinydns will also be accepted

        :param file_name: The path to a valid ZoneFile
        """
        full_path = os.path.abspath(file_name)
        file_size = os.path.getsize(full_path)
        if file_size > 1048576:
            raise DynectInvalidArgumentError('Zone File Size', file_size,
                                             'Under 1MB')
        else:
            uri = '/ZoneFile/{}/'.format(self.name)
            f = open(full_path, 'r')
            content = f.read()
            f.close()
            api_args = {'file': content}
            response = DynectSession.get_session().execute(
                uri, 'POST', api_args)
            self.__poll_for_get()
            self._build(response['data'])

    def _xfer(self, master_ip, timeout=None):
        """Create a :class:`Zone` by ZoneTransfer by providing an optional
        master_ip argument.
        """
        uri = '/ZoneTransfer/{}/'.format(self.name)
        api_args = {'master_ip': master_ip}
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        self._build(response['data'])
        time_out = timeout or 10
        count = 0
        while count < time_out:
            response = DynectSession.get_session().execute(uri, 'GET', {})
            if response['status'] == 'running' and response['message'] == '':
                sleep(60)
                count += 1
            else:
                break
        self._get()

    def __poll_for_get(self, n_loops=10, xfer=False, xfer_master_ip=None):
        """For use ONLY by _post_with_file and _xfer. Will wait at MOST
        ``n_loops * 2`` seconds for a successfull GET API response. If no
        successfull get is recieved no error will be raised.
        """
        count = 0
        got = False
        while count < n_loops:
            try:
                self._get()
                got = True
                break
            except DynectGetError:
                sleep(2)
                count += 1
        if not got and xfer:
            uri = '/ZoneTransfer/{}/'.format(self.name)
            api_args = {}
            if xfer_master_ip is not None:
                api_args['master_ip'] = xfer_master_ip
            response = DynectSession.get_session().execute(
                uri, 'GET', api_args)
            error_labels = ['running', 'waiting', 'failed', 'canceled']
            ok_labels = ['ready', 'unpublished', 'ok']
            if response['data']['status'] in error_labels:
                raise DynectCreateError(response['msgs'])
            elif response['data']['status'] in ok_labels:
                self._get()
            else:
                pass  # Should never get here

    def _get(self):
        """Get an existing :class:`Zone` object from the DynECT System"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build the variables in this object by pulling out the data from data
        """
        for key, val in data.items():
            if key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    def _update(self, api_args):
        """Update this :class:`ActiveFailover`, via the API, with the args in
        api_args
        """
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    @property
    def __root_soa(self):
        """Return the SOA record associated with this Zone"""
        return self.get_all_records_by_type('SOA')[0]

    @property
    def name(self):
        """The name of this :class:`Zone`"""
        return self._name

    @name.setter
    def name(self, value):
        pass

    @property
    def fqdn(self):
        """The name of this :class:`Zone`"""
        return self._fqdn

    @fqdn.setter
    def fqdn(self, value):
        pass

    @property
    def contact(self):
        """The email address of the primary :class:`Contact` associated with
        this :class:`Zone`
        """
        self._contact = self.__root_soa.rname
        return self._contact

    @contact.setter
    def contact(self, value):
        self.__root_soa.rname = value

    @property
    def ttl(self):
        """This :class:`Zone`'s default TTL"""
        self._ttl = self.__root_soa.ttl
        return self._ttl

    @ttl.setter
    def ttl(self, value):
        self.__root_soa.ttl = value

    @property
    def serial(self):
        """The current serial of this :class:`Zone`"""
        self._get()
        return self._serial

    @serial.setter
    def serial(self, value):
        pass

    @property
    def serial_style(self):
        """The current serial style of this :class:`Zone`"""
        self._get()
        return self._serial_style

    @serial_style.setter
    def serial_style(self, value):
        if value not in self.valid_serials:
            raise DynectInvalidArgumentError('serial_style', value,
                                             self.valid_serials)
        self.__root_soa.serial_style = value

    @property
    def status(self):
        """Convenience property for :class:`Zones`. If a :class:`Zones` is
        frozen the status will read as `'frozen'`, if the :class:`Zones` is not
        frozen the status will read as `'active'`. Because the API does not
        return information about whether or not a :class:`Zones` is frozen
        there will be a few cases where this status will be `None` in order to
        avoid guessing what the current status actually is.
        """
        self._get()
        return self._status

    @status.setter
    def status(self, value):
        pass

    def freeze(self):
        """Causes the zone to become frozen. Freezing a zone prevents changes
        to the zone until it is thawed.
        """
        api_args = {'freeze': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])
        if response['status'] == 'success':
            self._status = 'frozen'

    def thaw(self):
        """Causes the zone to become thawed. Thawing a frozen zone allows
        changes to again be made to the zone.
        """
        api_args = {'thaw': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])
        if response['status'] == 'success':
            self._status = 'active'

    def publish(self, notes=None):
        """Causes all pending changes to become part of the zone. The serial
        number increments based on its serial style and the data is pushed out
        to the nameservers.
        """
        api_args = {'publish': True}
        if notes:
            api_args['notes'] = notes
        self._update(api_args)

    @property
    def task(self):
        """:class:`Task` for most recent system action on this :class:`Zone`.
        """
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def get_notes(self, offset=None, limit=None):
        """Generates a report containing the Zone Notes for this :class:`Zone`

        :param offset: The starting point at which to retrieve the notes
        :param limit: The maximum number of notes to be retrieved
        :return: A :class:`list` of :class:`dict` containing :class:`Zone`
            Notes
        """
        uri = '/ZoneNoteReport/'
        api_args = {'zone': self.name}
        if offset:
            api_args['offset'] = offset
        if limit:
            api_args['limit'] = limit
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        return response['data']

    def add_record(self, name=None, record_type='A', *args, **kwargs):
        """Adds an a record with the provided name and data to this
        :class:`Zone`

        :param name: The name of the node where this record will be added
        :param record_type: The type of record you would like to add.
            Valid record_type arguments are: 'A', 'AAAA', 'CERT', 'CNAME',
            'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'KX', 'LOC', 'IPSECKEY',
            'MX', 'NAPTR', 'PTR', 'PX', 'NSAP', 'RP', 'NS', 'SOA', 'SPF',
            'SRV', and 'TXT'.
        :param args: Non-keyword arguments to pass to the Record constructor
        :param kwargs: Keyword arguments to pass to the Record constructor
        """
        fqdn = name + '.' + self.name + '.' if name else self.name + '.'
        # noinspection PyCallingNonCallable
        rec = RECS[record_type](self.name, fqdn, *args, **kwargs)
        if record_type in self.records:
            self.records[record_type].append(rec)
        else:
            self.records[record_type] = [rec]
        return rec

    def add_service(self, name=None, service_type=None, *args, **kwargs):
        """Add the specified service type to this zone, or to a node under this
        zone

        :param name: The name of the :class:`Node` where this service will be
            attached to or `None` to attach it to the root :class:`Node` of
            this :class:`Zone`
        :param service_type: The type of the service you would like to create.
            Valid service_type arguments are: 'ActiveFailover', 'DDNS',
            'DNSSEC', 'DSF', 'GSLB', 'RDNS', 'RTTM', 'HTTPRedirect'
        :param args: Non-keyword arguments to pass to the Record constructor
        :param kwargs: Keyword arguments to pass to the Record constructor
        """
        constructors = {
            'ActiveFailover': ActiveFailover,
            'DDNS': DynamicDNS,
            'DNSSEC': DNSSEC,
            'DSF': TrafficDirector,
            'GSLB': GSLB,
            'RDNS': ReverseDNS,
            'RTTM': RTTM,
            'HTTPRedirect': HTTPRedirect
        }
        fqdn = self.name + '.'
        if name:
            fqdn = name + '.' + fqdn
        if service_type == 'DNSSEC':
            # noinspection PyCallingNonCallable
            service = constructors[service_type](self.name, *args, **kwargs)
        else:
            # noinspection PyCallingNonCallable
            service = constructors[service_type](self.name, fqdn, *args,
                                                 **kwargs)
        if service_type in self.services:
            self.services[service_type].append(service)
        else:
            self.services[service_type] = [service]
        return service

    def get_all_nodes(self):
        """Returns a list of Node Objects for all subnodes in Zone (Excluding
        the Zone itself.)
        """
        api_args = {}
        uri = '/NodeList/{}/'.format(self._name)
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        nodes = [
            Node(self._name, fqdn) for fqdn in response['data']
            if fqdn != self._name
        ]
        return nodes

    def get_node(self, node=None):
        """Returns all DNS Records for that particular node

        :param node: The name of the Node you wish to access, or `None` to get
            the root :class:`Node` of this :class:`Zone`
        """
        if node:
            fqdn = node + '.' + self.name + '.'
        else:
            fqdn = self.name + '.'
        return Node(self.name, fqdn)

    def get_all_records(self):
        """Retrieve a list of all record resources for the specified node and
        zone combination as well as all records from any Base_Record below that
        point on the zone hierarchy

        :return: A :class:`List` of all the :class:`DNSRecord`'s under this
            :class:`Zone`
        """
        self.records = {}
        uri = '/AllRecord/{}/'.format(self._name)
        if self.fqdn is not None:
            uri += '{}/'.format(self.fqdn)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        # Strip out empty record_type lists
        record_lists = {
            label: rec_list
            for label, rec_list in response['data'].items() if rec_list != []
        }
        records = {}
        for key, record_list in record_lists.items():
            search = key.split('_')[0].upper()
            try:
                constructor = RECS[search]
            except KeyError:
                constructor = RECS['UNKNOWN']
            list_records = []
            for record in record_list:
                del record['zone']
                fqdn = record['fqdn']
                del record['fqdn']
                # Unpack rdata
                for r_key, r_val in record['rdata'].items():
                    record[r_key] = r_val
                record['create'] = False
                list_records.append(constructor(self._name, fqdn, **record))
            records[key] = list_records
        return records

    def get_all_records_by_type(self, record_type):
        """Get a list of all :class:`DNSRecord` of type ``record_type`` which
        are owned by this node.

        :param record_type: The type of :class:`DNSRecord` you wish returned.
            Valid record_type arguments are: 'A', 'AAAA', 'CERT', 'CNAME',
            'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'KX', 'LOC', 'IPSECKEY',
            'MX', 'NAPTR', 'PTR', 'PX', 'NSAP', 'RP', 'NS', 'SOA', 'SPF',
            'SRV', and 'TXT'.
        :return: A :class:`List` of :class:`DNSRecord`'s
        """
        names = {
            'A': 'ARecord',
            'AAAA': 'AAAARecord',
            'ALIAS': 'ALIASRecord',
            'CDS': 'CDSRecord',
            'CDNSKEY': 'CDNSKEYRecord',
            'CERT': 'CERTRecord',
            'CSYNC': 'CSYNCRecord',
            'CNAME': 'CNAMERecord',
            'DHCID': 'DHCIDRecord',
            'DNAME': 'DNAMERecord',
            'DNSKEY': 'DNSKEYRecord',
            'DS': 'DSRecord',
            'KEY': 'KEYRecord',
            'KX': 'KXRecord',
            'LOC': 'LOCRecord',
            'IPSECKEY': 'IPSECKEYRecord',
            'MX': 'MXRecord',
            'NAPTR': 'NAPTRRecord',
            'PTR': 'PTRRecord',
            'PX': 'PXRecord',
            'NSAP': 'NSAPRecord',
            'RP': 'RPRecord',
            'NS': 'NSRecord',
            'SOA': 'SOARecord',
            'SPF': 'SPFRecord',
            'SRV': 'SRVRecord',
            'TLSA': 'TLSARecord',
            'TXT': 'TXTRecord',
            'SSHFP': 'SSHFPRecord'
        }

        constructor = RECS[record_type]
        uri = '/{}/{}/{}/'.format(names[record_type], self._name, self.fqdn)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        records = []
        for record in response['data']:
            fqdn = record['fqdn']
            del record['fqdn']
            del record['zone']
            # Unpack rdata
            for key, val in record['rdata'].items():
                record[key] = val
            del record['rdata']
            record['create'] = False
            records.append(constructor(self._name, fqdn, **record))
        return records

    def get_any_records(self):
        """Retrieve a list of all :class:`DNSRecord`'s associated with this
        :class:`Zone`
        """
        if self.fqdn is None:
            return
        api_args = {'detail': 'Y'}
        uri = '/ANYRecord/{}/{}/'.format(self._name, self.fqdn)
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        # Strip out empty record_type lists
        record_lists = {
            label: rec_list
            for label, rec_list in response['data'].items() if rec_list != []
        }
        records = {}
        for key, record_list in record_lists.items():
            search = key.split('_')[0].upper()
            try:
                constructor = RECS[search]
            except KeyError:
                constructor = RECS['UNKNOWN']
            list_records = []
            for record in record_list:
                del record['zone']
                del record['fqdn']
                # Unpack rdata
                for r_key, r_val in record['rdata'].items():
                    record[r_key] = r_val
                record['create'] = False
                list_records.append(
                    constructor(self._name, self.fqdn, **record))
            records[key] = list_records
        return records

    def get_all_active_failovers(self):
        """Retrieve a list of all :class:`ActiveFailover` services associated
        with this :class:`Zone`

        :return: A :class:`List` of :class:`ActiveFailover` Services
        """
        uri = '/Failover/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        afos = []
        for failover in response['data']:
            del failover['zone']
            del failover['fqdn']
            afos.append(
                ActiveFailover(self._name, self._fqdn, api=False, **failover))
        return afos

    def get_all_ddns(self):
        """Retrieve a list of all :class:`DDNS` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`DDNS` Services
        """
        uri = '/DDNS/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        ddnses = []
        for svc in response['data']:
            del svc['zone']
            del svc['fqdn']
            ddnses.append(DynamicDNS(self._name, self._fqdn, api=False, **svc))
        return ddnses

    def get_all_httpredirect(self):
        """Retrieve a list of all :class:`HTTPRedirect` services associated
        with this :class:`Zone`

        :return: A :class:`List` of :class:`HTTPRedirect` Services
        """
        uri = '/HTTPRedirect/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        httpredirs = []
        for httpredir in response['data']:
            del httpredir['zone']
            del httpredir['fqdn']
            httpredirs.append(
                HTTPRedirect(self._name, self._fqdn, api=False, **httpredir))
        return httpredirs

    def get_all_gslb(self):
        """Retrieve a list of all :class:`GSLB` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`GSLB` Services
        """
        uri = '/GSLB/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        gslbs = []
        for gslb_svc in response['data']:
            del gslb_svc['zone']
            del gslb_svc['fqdn']
            gslbs.append(GSLB(self._name, self._fqdn, api=False, **gslb_svc))
        return gslbs

    def get_all_rdns(self):
        """Retrieve a list of all :class:`ReverseDNS` services associated with
        this :class:`Zone`

        :return: A :class:`List` of :class:`ReverseDNS` Services
        """
        uri = '/IPTrack/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        rdnses = []
        for rdns in response['data']:
            del rdns['zone']
            del rdns['fqdn']
            rdnses.append(ReverseDNS(self._name, self._fqdn, api=False,
                                     **rdns))
        return rdnses

    def get_all_rttm(self):
        """Retrieve a list of all :class:`RTTM` services associated with this
        :class:`Zone`

        :return: A :class:`List` of :class:`RTTM` Services
        """
        uri = '/RTTM/{}/'.format(self._name)
        api_args = {'detail': 'Y'}
        response = DynectSession.get_session().execute(uri, 'GET', api_args)
        rttms = []
        for rttm_svc in response['data']:
            del rttm_svc['zone']
            del rttm_svc['fqdn']
            rttms.append(RTTM(self._name, self._fqdn, api=False, **rttm_svc))
        return rttms

    def get_qps(self,
                start_ts,
                end_ts=None,
                breakdown=None,
                hosts=None,
                rrecs=None):
        """Generates a report with information about Queries Per Second (QPS)
        for this zone

        :param start_ts: datetime.datetime instance identifying point in time
            for the QPS report
        :param end_ts: datetime.datetime instance indicating the end of the
            data range for the report. Defaults to datetime.datetime.now()
        :param breakdown: By default, most data is aggregated together.
            Valid values ('hosts', 'rrecs', 'zones').
        :param hosts: List of hosts to include in the report.
        :param rrecs: List of record types to include in report.
        :return: A :class:`str` with CSV data
        """
        end_ts = end_ts or datetime.now()
        api_args = {
            'start_ts': unix_date(start_ts),
            'end_ts': unix_date(end_ts),
            'zones': [self.name]
        }
        if breakdown is not None:
            api_args['breakdown'] = breakdown
        if hosts is not None:
            api_args['hosts'] = hosts
        if rrecs is not None:
            api_args['rrecs'] = rrecs
        response = DynectSession.get_session().execute('/QPSReport/', 'POST',
                                                       api_args)
        return response['data']

    def delete(self):
        """Delete this :class:`Zone` and perform nessecary cleanups"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __eq__(self, other):
        """Equivalence operations for easily pulling a :class:`Zone` out of a
        list of :class:`Zone` objects
        """
        if isinstance(other, str):
            return other == self._name
        elif isinstance(other, Zone):
            return other.name == self._name
        return False

    def __ne__(self, other):
        """Non-Equivalence operator"""
        return not self.__eq__(other)

    def __str__(self):
        """str override"""
        return force_unicode('<Zone>: {}').format(self._name)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#17
0
class RTTM(object):
    def __init__(self, zone, fqdn, *args, **kwargs):
        """Create a :class:`RTTM` object

        :param auto_recover:  Indicates whether or not the service should
            automatically come out of failover when the IP addresses resume
            active status or if the service should remain in failover until
            manually reset. Must be one of 'Y' or 'N'
        :param ttl: Time To Live in seconds of records in the service. Must be
            less than 1/2 of the Health Probe's monitoring interval. Must be
            one of 30, 60, 150, 300, or 450.
        :param notify_events: A list of the events which trigger notifications.
            Must be one of 'ip', 'svc', or 'nosrv'
        :param syslog_server: The Hostname or IP address of a server to receive
            syslog notifications on monitoring events
        :param syslog_port: The port where the remote syslog server listens for
            notifications
        :param syslog_ident: The ident to use when sending syslog notifications
        :param syslog_facility: The syslog facility to use when sending syslog
            notifications. Must be one of kern, user, mail, daemon, auth,
            syslog, lpr, news, uucp, cron, authpriv, ftp, ntp, security,
            console, local0, local1, local2, local3, local4, local5, local6, or
            local7
        :param syslog_delivery: The syslog delivery action type. 'all' will
            deliver notifications no matter what the endpoint state. 'change'
            (default) will deliver only on change in the detected endpoint
            state
        :param region: A list of :class:`RTTMRegion`'s
        :param monitor: The :class:`Monitor` for this service
        :param performance_monitor: The performance monitor for the service
        :param contact_nickname: Name of contact to receive notifications
        :param syslog_probe_fmt: see below for format:
        :param syslog_status_fmt: see below for format:
        :param syslog_rttm_fmt: see below for format:
            Use the following format for syslog_xxxx_fmt paramaters.
            %hos	hostname
            %tim	current timestamp or monitored interval
            %reg	region code
            %sta	status
            %ser	record serial
            %rda	rdata
            %sit	monitoring site
            %rti	response time
            %msg	message from monitoring
            %adr	address of monitored node
            %med	median value
            %rts	response times (RTTM)
        :param recovery_delay: number of up status polling intervals to
            consider service up
        """
        super(RTTM, self).__init__()
        self.valid_ttls = (30, 60, 150, 300, 450)
        self.valid_notify_events = ('ip', 'svc', 'nosrv')
        self.valid_syslog_facilities = ('kern', 'user', 'mail', 'daemon',
                                        'auth', 'syslog', 'lpr', 'news',
                                        'uucp', 'cron', 'authpriv', 'ftp',
                                        'ntp', 'security', 'console', 'local0',
                                        'local1', 'local2', 'local3', 'local4',
                                        'local5', 'local6', 'local7')
        self._zone = zone
        self._fqdn = fqdn
        self.uri = '/RTTM/{}/{}/'.format(self._zone, self._fqdn)
        self._auto_recover = self._ttl = self._notify_events = None
        self._syslog_server = self._syslog_port = self._syslog_ident = None
        self._syslog_facility = self._monitor = None
        self._performance_monitor = self._contact_nickname = None
        self._active = self._syslog_delivery = self._syslog_probe_fmt = None
        self._syslog_status_fmt = self._syslog_rttm_fmt = None
        self._recovery_delay = None
        self._region = APIList(DynectSession.get_session, 'region')
        self._task_id = None
        if 'api' in kwargs:
            del kwargs['api']
            self._build(kwargs)
        elif len(args) == 0 and len(kwargs) == 0:
            self._get()
        else:
            self._post(*args, **kwargs)
        self._region.uri = self.uri

    def _post(self, contact_nickname, performance_monitor, region, ttl=None,
              auto_recover=None, notify_events=None, syslog_server=None,
              syslog_port=514, syslog_ident='dynect', syslog_facility='daemon',
              syslog_delivery='change', syslog_probe_fmt=None,
              syslog_status_fmt=None, syslog_rttm_fmt=None,
              recovery_delay=None, monitor=None):
        """Create a new RTTM Service on the DynECT System"""
        self._auto_recover = auto_recover
        self._ttl = ttl
        self._notify_events = notify_events
        self._syslog_server = syslog_server
        self._syslog_port = syslog_port
        self._syslog_ident = syslog_ident
        self._syslog_facility = syslog_facility
        self._syslog_delivery = syslog_delivery
        self._region += region
        self._monitor = monitor
        self._performance_monitor = performance_monitor
        self._contact_nickname = contact_nickname
        self._syslog_probe_fmt = syslog_probe_fmt
        self._syslog_status_fmt = syslog_status_fmt
        self._syslog_rttm_fmt = syslog_rttm_fmt
        self._recovery_delay = recovery_delay
        api_args = {}
        if auto_recover:
            if auto_recover not in ('Y', 'N'):
                raise DynectInvalidArgumentError('auto_recover', auto_recover,
                                                 ('Y', 'N'))
            api_args['auto_recover'] = self._auto_recover
        if ttl:
            if ttl not in self.valid_ttls:
                raise DynectInvalidArgumentError('ttl', ttl, self.valid_ttls)
            api_args['ttl'] = self._ttl
        if notify_events:
            for event in notify_events:
                if event not in self.valid_notify_events:
                    raise DynectInvalidArgumentError('notify_events', event,
                                                     self.valid_notify_events)
            api_args['notify_events'] = self._notify_events
        if syslog_server:
            api_args['syslog_server'] = self._syslog_server
        if syslog_port:
            api_args['syslog_port'] = self._syslog_port
        if syslog_ident:
            api_args['syslog_ident'] = self._syslog_ident
        if syslog_facility:
            if syslog_facility not in self.valid_syslog_facilities:
                raise DynectInvalidArgumentError('syslog_facility',
                                                 syslog_facility,
                                                 self.valid_syslog_facilities)
            api_args['syslog_facility'] = self._syslog_facility
        if syslog_delivery:
            api_args['syslog_delivery'] = self._syslog_delivery
        if syslog_probe_fmt:
            api_args['syslog_probe_fmt'] = self._syslog_probe_fmt
        if syslog_status_fmt:
            api_args['syslog_status_fmt'] = self._syslog_status_fmt
        if syslog_rttm_fmt:
            api_args['syslog_rttm_fmt'] = self._syslog_rttm_fmt
        if recovery_delay:
            api_args['recovery_delay'] = self._recovery_delay
        if region:
            api_args['region'] = [reg._json for reg in self._region]
        if monitor:
            api_args['monitor'] = self._monitor.to_json()
        if performance_monitor:
            mon_args = self._performance_monitor.to_json()
            api_args['performance_monitor'] = mon_args
        if contact_nickname:
            api_args['contact_nickname'] = self._contact_nickname

        # API expects a CSV string, not a list
        if isinstance(self.notify_events, list):
            api_args['notify_events'] = ','.join(self.notify_events)

        response = DynectSession.get_session().execute(self.uri, 'POST',
                                                       api_args)
        self._build(response['data'])

    def _get(self):
        """Build an object around an existing DynECT RTTM Service"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _update(self, api_args):
        """Perform a PUT api call using this objects data"""
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        """Build the neccesary substructures under this :class:`RTTM`"""
        for key, val in data.items():
            if key == 'region':
                self._region = APIList(DynectSession.get_session, 'region')
                for region in val:
                    code = region.pop('region_code', None)
                    pool = region.pop('pool', None)
                    status = region.pop('status', None)

                    r = RTTMRegion(self._zone, self._fqdn, code, pool,
                                   **region)
                    r._status = status
                    self._region.append(r)
            elif key == 'monitor':
                if self._monitor is not None:
                    self._monitor.zone = self._zone
                    self._monitor.fqdn = self._fqdn
                else:
                    proto = val.pop('protocol', None)
                    inter = val.pop('interval', None)
                    self._monitor = Monitor(proto, inter, **val)
            elif key == 'performance_monitor':
                if self._performance_monitor is not None:
                    self._performance_monitor.zone = self._zone
                    self._performance_monitor.fqdn = self._fqdn
                else:
                    proto = val.pop('protocol', None)
                    inter = val.pop('interval', None)
                    self._performance_monitor = PerformanceMonitor(proto,
                                                                   inter,
                                                                   **val)
            elif key == 'notify_events':
                self._notify_events = [item.strip() for item in val.split(',')]
            elif key == 'active':
                self._active = Active(val)
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)
        self._region.uri = self.uri

    @property
    def task(self):
        """:class:`Task` for most recent system
         action on this :class:`ActiveFailover`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    def get_rrset_report(self, ts):
        """Generates a report of regional response sets for this RTTM service
        at a given point in time

        :param ts: UNIX timestamp identifying point in time for the log report
        :return: dictionary containing rrset report data
        """
        api_args = {'zone': self._zone,
                    'fqdn': self._fqdn,
                    'ts': ts}
        response = DynectSession.get_session().execute('/RTTMRRSetReport/',
                                                       'POST', api_args)
        return response['data']

    def get_log_report(self, start_ts, end_ts=None):
        """Generates a report with information about changes to an existing
        RTTM service

        :param start_ts: datetime.datetime instance identifying point in time
            for the start of the log report
        :param end_ts: datetime.datetime instance identifying point in time
            for the end of the log report. Defaults to datetime.datetime.now()
        :return: dictionary containing log report data
        """
        end_ts = end_ts or datetime.now()
        api_args = {'zone': self._zone,
                    'fqdn': self._fqdn,
                    'start_ts': unix_date(start_ts),
                    'end_ts': unix_date(end_ts)}
        response = DynectSession.get_session().execute('/RTTMLogReport/',
                                                       'POST', api_args)
        return response['data']

    def activate(self):
        """Activate this RTTM Service"""
        api_args = {'activate': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def deactivate(self):
        """Deactivate this RTTM Service"""
        api_args = {'deactivate': True}
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def recover(self, recoverip=None, address=None):
        """Recovers the RTTM service or a specific node IP within the service
        """
        api_args = {'recover': True}
        if recoverip:
            api_args['recoverip'] = recoverip
            api_args['address'] = address
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    @property
    def active(self):
        """Returns whether or not this :class:`RTTM` Service is currently
        active. When setting directly, rather than using activate/deactivate
        valid arguments are 'Y' or True to activate, or 'N' or False to
        deactivate. Note: If your service is already active and you try to
        activate it, nothing will happen. And vice versa for deactivation.

        :returns: An :class:`Active` object representing the current state of
            this :class:`ReverseDNS` Service
        """
        return self._active

    @active.setter
    def active(self, value):
        deactivate = ('N', False)
        activate = ('Y', True)
        if value in deactivate and self.active:
            self.deactivate()
        elif value in activate and not self.active:
            self.activate()

    @property
    def auto_recover(self):
        """Indicates whether or not the service should automatically come out
        of failover when the IP addresses resume active status or if the
        service should remain in failover until manually reset. Must be one of
        'Y' or 'N'
        """
        return self._auto_recover

    @auto_recover.setter
    def auto_recover(self, value):
        if value not in ('Y', 'N'):
            raise DynectInvalidArgumentError('auto_recover', value,
                                             ('Y', 'N'))
        api_args = {'auto_recover': value}
        self._update(api_args)

    @property
    def ttl(self):
        """Time To Live in seconds of records in the service. Must be less than
        1/2 of the Health Probe's monitoring interval. Must be one of 30, 60,
        150, 300, or 450.
        """
        return self._ttl

    @ttl.setter
    def ttl(self, value):
        if value not in self.valid_ttls:
            raise DynectInvalidArgumentError('ttl', value, self.valid_ttls)
        api_args = {'ttl': value}
        self._update(api_args)

    @property
    def notify_events(self):
        """A list of events which trigger notifications. Valid values are:
        'ip', 'svc', and 'nosrv'
        """
        return self._notify_events

    @notify_events.setter
    def notify_events(self, value):
        for val in value:
            if val not in self.valid_notify_events:
                raise DynectInvalidArgumentError('notify_events', val,
                                                 self.valid_notify_events)
        value = ','.join(value)
        api_args = {'notify_events': value}
        self._update(api_args)

    @property
    def status(self):
        """Status"""
        self._get()
        return self._status

    @property
    def syslog_server(self):
        """The Hostname or IP address of a server to receive syslog
        notifications on monitoring events
        """
        self._get()
        return self._syslog_server

    @syslog_server.setter
    def syslog_server(self, value):
        api_args = {'syslog_server': value}
        self._update(api_args)

    @property
    def syslog_port(self):
        """The port where the remote syslog server listens for notifications"""
        self._get()
        return self._syslog_port

    @syslog_port.setter
    def syslog_port(self, value):
        api_args = {'syslog_port': value}
        self._update(api_args)

    @property
    def syslog_ident(self):
        """The ident to use when sending syslog notifications"""
        self._get()
        return self._syslog_ident

    @syslog_ident.setter
    def syslog_ident(self, value):
        api_args = {'syslog_ident': value}
        self._update(api_args)

    @property
    def syslog_facility(self):
        """The syslog facility to use when sending syslog notifications. Must
        be one of kern, user, mail, daemon, auth, syslog, lpr, news, uucp,
        cron, authpriv, ftp, ntp, security, console, local0, local1, local2,
        local3, local4, local5, local6, or local7
        """
        self._get()
        return self._syslog_facility

    @syslog_facility.setter
    def syslog_facility(self, value):
        if value not in self.valid_syslog_facilities:
            raise DynectInvalidArgumentError('syslog_facility', value,
                                             self.valid_syslog_facilities)
        api_args = {'syslog_facility': value}
        self._update(api_args)

    @property
    def syslog_delivery(self):
        self._get()
        return self._syslog_delivery

    @syslog_delivery.setter
    def syslog_delivery(self, value):
        api_args = {'syslog_delivery': value}
        self._update(api_args)

    @property
    def syslog_probe_format(self):
        self._get()
        return self._syslog_probe_fmt

    @syslog_probe_format.setter
    def syslog_probe_format(self, value):
        api_args = {'syslog_probe_fmt': value}
        self._update(api_args)

    @property
    def syslog_status_format(self):
        self._get()
        return self._syslog_status_fmt

    @syslog_status_format.setter
    def syslog_status_format(self, value):
        api_args = {'syslog_status_fmt': value}
        self._update(api_args)

    @property
    def syslog_rttm_format(self):
        self._get()
        return self._syslog_rttm_fmt

    @syslog_rttm_format.setter
    def syslog_rttm_format(self, value):
        api_args = {'syslog_rttm_fmt': value}
        self._update(api_args)

    @property
    def recovery_delay(self):
        self._get()
        return self._recovery_delay

    @recovery_delay.setter
    def recovery_delay(self, value):
        api_args = {'recovery_delay': value}
        self._update(api_args)

    @property
    def region(self):
        """A list of :class:`RTTMRegion`'s"""
        return self._region

    @region.setter
    def region(self, value):
        if isinstance(value, list) and not isinstance(value, APIList):
            self._region = APIList(DynectSession.get_session, 'region', None,
                                   value)
        elif isinstance(value, APIList):
            self._region = value
        self._region.uri = self.uri

    @property
    def monitor(self):
        """The :class:`Monitor` for this service"""
        return self._monitor

    @monitor.setter
    def monitor(self, value):
        if isinstance(value, Monitor):
            self._monitor = value
            api_args = {'monitor': self._monitor.to_json()}
            self._update(api_args)

    @property
    def performance_monitor(self):
        """The Performance :class:`Monitor` for this service"""
        return self._performance_monitor

    @performance_monitor.setter
    def performance_monitor(self, value):
        if isinstance(value, Monitor):
            self._performance_monitor = value
            api_args = {'performance_monitor':
                        self._performance_monitor.to_json()}
            self._update(api_args)

    @property
    def contact_nickname(self):
        """The name of contact to receive notifications from this service"""
        return self._contact_nickname

    @contact_nickname.setter
    def contact_nickname(self, value):
        api_args = {'contact_nickname': value}
        self._update(api_args)

    def delete(self):
        """Delete this RTTM Service"""
        api_args = {}
        DynectSession.get_session().execute(self.uri, 'DELETE', api_args)

    def __str__(self):
        """str override"""
        return force_unicode('<RTTM>: {}').format(self._fqdn)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())
示例#18
0
class RTTMRegion(object):
    """docstring for RTTMRegion"""

    def __init__(self, zone, fqdn, region_code, *args, **kwargs):
        """Create a :class:`RTTMRegion` object

        :param region_code: Name of the region
        :param pool: (*arg) The IP Pool list for this region
        :param autopopulate: If set to Y, this region will automatically be
            filled in from the global pool, and any other options passed in for
            this region will be ignored
        :param ep: Eligibility Pool - How many records will make it into the
            eligibility pool. The addresses that get chosen will be those that
            respond the fastest
        :param apmc: The minimum amount of IPs that must be in the up state,
            otherwise the region will be in failover
        :param epmc: The minimum amount of IPs that must be populated in the
            EP, otherwise the region will be in failover
        :param serve_count: How many records will be returned in each DNS
            response
        :param failover_mode: How the region should failover. Must be one of
            'ip', 'cname', 'region', or 'global'
        :param failover_data: Dependent upon failover_mode. Must be one of ip',
            'cname', 'region', or 'global'
        """
        super(RTTMRegion, self).__init__()
        self.valid_region_codes = ('US West', 'US Central', 'US East', 'Asia',
                                   'EU West', 'EU Central', 'EU East',
                                   'global')
        self.valid_modes = ('ip', 'cname', 'region', 'global')
        self._task_id = None
        self._zone = zone
        self._fqdn = fqdn
        self._autopopulate = self._ep = self._apmc = None
        self._epmc = self._serve_count = self._failover_mode = None
        self._failover_data = None
        if len(args) != 0:
            pool = args[0]
        else:
            pool = None
        if region_code not in self.valid_region_codes:
            raise DynectInvalidArgumentError('region_code', region_code,
                                             self.valid_region_codes)
        self._region_code = region_code
        self._pool = []
        self.uri = '/RTTMRegion/{}/{}/{}/'.format(self._zone, self._fqdn,
                                                  self._region_code)
        # Backwards Compatability, since we changed the structure of this
        # Class:
        if kwargs.get('pool'):
            warnings.warn("passing pool as keyword argument is\
                          depreciated! please pass in as 4th argument",
                          DeprecationWarning)
            pool = kwargs.pop('pool')

        if not pool and len(kwargs) == 0:
            self._get()
        if len(kwargs) > 0:
            self._build(kwargs)
        if pool:
            for poole in pool:
                if isinstance(poole, dict):
                    rpe = RegionPoolEntry(zone=self._zone,
                                          fqdn=self._fqdn,
                                          region_code=self._region_code,
                                          **poole)
                    self._pool.append(rpe)
                else:
                    if not poole.zone:
                        poole.zone = self._zone
                    if not poole.fqdn:
                        poole.fqdn = self._fqdn
                    if not poole.region_code:
                        poole.region_code = self._region_code
                    self._pool.append(poole)
        self._status = None

    def _post(self):
        """Create a new :class:`RTTMRegion` on the DynECT System"""
        uri = '/RTTMRegion/{}/{}/'.format(self._zone, self._fqdn)
        api_args = {'region_code': self._region_code,
                    'pool': [poole.to_json() for poole in self._pool]}
        if self._autopopulate:
            if self._autopopulate not in ('Y', 'N'):
                raise DynectInvalidArgumentError('autopopulate',
                                                 self._autopopulate,
                                                 ('Y', 'N'))
            api_args['autopopulate'] = self._autopopulate
        if self._ep:
            api_args['ep'] = self._ep
        if self._apmc:
            api_args['apmc'] = self._apmc
        if self._epmc:
            api_args['epmc'] = self._epmc
        if self._serve_count:
            api_args['serve_count'] = self._serve_count
        if self._failover_mode:
            if self._failover_mode not in self.valid_modes:
                raise DynectInvalidArgumentError('failover_mode',
                                                 self._failover_mode,
                                                 self.valid_modes)
            api_args['failover_mode'] = self._failover_mode
        if self._failover_data:
            if self._failover_data not in self.valid_modes:
                raise DynectInvalidArgumentError('failover_data',
                                                 self._failover_data,
                                                 self.valid_modes)
            api_args['failover_data'] = self._failover_data
        response = DynectSession.get_session().execute(uri, 'POST', api_args)
        self._build(response['data'])

    def _get(self):
        """Get an existing :class:`RTTMRegion` object from the DynECT System"""
        api_args = {}
        response = DynectSession.get_session().execute(self.uri, 'GET',
                                                       api_args)
        self._build(response['data'])

    def _update(self, api_args):
        """Private Update method to cut back on redundant code"""
        response = DynectSession.get_session().execute(self.uri, 'PUT',
                                                       api_args)
        self._build(response['data'])

    def _build(self, data):
        for key, val in data.items():
            if key == 'pool':
                pass
            elif key == "task_id" and not val:
                self._task_id = None
            elif key == "task_id":
                self._task_id = Task(val)
            else:
                setattr(self, '_' + key, val)

    @property
    def task(self):
        """:class:`Task` for most recent system
         action on this :class:`ActiveFailover`."""
        if self._task_id:
            self._task_id.refresh()
        return self._task_id

    @property
    def autopopulate(self):
        """If set to Y, this region will automatically be filled in from the
        global pool, and any other options passed in for this region will be
        ignored. Must be either 'Y' or 'N'.
        """
        return self._autopopulate

    @autopopulate.setter
    def autopopulate(self, value):
        self._autopopulate = value
        api_args = {'autopopulate': self._autopopulate}
        self._update(api_args)

    @property
    def ep(self):
        """Eligibility Pool - How many records will make it into the
        eligibility pool. The addresses that get chosen will be those that
        respond the fastest
        """
        return self._ep

    @ep.setter
    def ep(self, value):
        self._ep = value
        api_args = {'ep': self._ep}
        self._update(api_args)

    @property
    def apmc(self):
        """The minimum amount of IPs that must be in the up state, otherwise
        the region will be in failover.
        """
        return self._apmc

    @apmc.setter
    def apmc(self, value):
        self._apmc = value
        api_args = {'apmc': self._apmc}
        self._update(api_args)

    @property
    def epmc(self):
        """The minimum amount of IPs that must be populated in the EP,
        otherwise the region will be in failover
        """
        return self._epmc

    @epmc.setter
    def epmc(self, value):
        self._epmc = value
        api_args = {'epmc': self._epmc}
        self._update(api_args)

    @property
    def serve_count(self):
        """How many records will be returned in each DNS response"""
        return self._serve_count

    @serve_count.setter
    def serve_count(self, value):
        self._serve_count = value
        api_args = {'serve_count': self._serve_count}
        self._update(api_args)

    @property
    def failover_mode(self):
        """How the region should failover. Must be one of 'ip', 'cname',
        'region', or 'global'
        """
        return self._failover_mode

    @failover_mode.setter
    def failover_mode(self, value):
        self._failover_mode = value
        api_args = {'failover_mode': self._failover_mode}
        self._update(api_args)

    @property
    def failover_data(self):
        """Dependent upon failover_mode. Must be one of ip', 'cname', 'region',
        or 'global'
        """

        return self._failover_data

    @failover_data.setter
    def failover_data(self, value):
        if value not in self.valid_modes:
            raise DynectInvalidArgumentError('failover_data', value,
                                             self.valid_modes)
        api_args = {'failover_data': value}
        self._update(api_args)

    @property
    def pool(self):
        """The IP Pool list for this :class:`RTTMRegion`"""
        return self._pool

    @pool.setter
    def pool(self, value):
        self._pool = value
        api_args = {'pool': self._pool}
        self._update(api_args)

    @property
    def status(self):
        """The current state of the region."""
        self._get()
        return self._status

    @status.setter
    def status(self, value):
        pass

    @property
    def _json(self):
        """Unpack this object and return it as a JSON blob"""
        json_blob = {'region_code': self._region_code,
                     'pool': [entry.to_json() for entry in self._pool]}
        if self._autopopulate:
            json_blob['autopopulate'] = self._autopopulate
        if self._ep:
            json_blob['ep'] = self._ep
        if self._apmc:
            json_blob['apmc'] = self._apmc
        if self._epmc:
            json_blob['epmc'] = self._epmc
        if self._serve_count:
            json_blob['serve_count'] = self._serve_count
        if self._failover_mode:
            json_blob['failover_mode'] = self._failover_mode
        if self._failover_data:
            json_blob['failover_data'] = self._failover_data
        return json_blob

    def delete(self):
        """Delete an existing :class:`RTTMRegion` object from the DynECT
        System
        """
        DynectSession.get_session().execute(self.uri, 'DELETE')

    def __str__(self):
        """str override"""
        return force_unicode('<RTTMRegion>: {}').format(self._region_code)

    __repr__ = __unicode__ = __str__

    def __bytes__(self):
        """bytes override"""
        return bytes(self.__str__())