def protocol(self, value): if value not in self.valid_protocols: raise Exception self._protocol = value api_args = {'monitor': {'protocol': self._protocol}} uri = '/Failover/{}/{}/'.format(self.zone, self.fqdn) DynectSession.get_session().execute(uri, 'PUT', api_args)
def delete(self, publish='Y'): """Delete this HTTPRedirect service from the DynECT System publish='N' can be passed into this function to do a soft-delete which will be acted upon during a zone publish. """ api_args = {'publish': publish} DynectSession.get_session().execute(self.uri, 'DELETE', api_args)
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 delete(self): """Delete this :class:`AdvancedRedirectRule` service from the DynECT System """ self.uri = '/AdvRedirectRule/{}/{}/{}'.format(self._zone, self._fqdn, self._public_id) DynectSession.get_session().execute(self.uri, 'DELETE', {})
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 address(self, value): self._address = value api_args = {'address': self._address} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
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 """ self.records = {} uri = '/AllRecord/{}/'.format(self.zone) 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.zone, fqdn, **record)) records[key] = list_records return records
def _get(self): """Get a :class:`TSIG` object from the DynECT System""" api_args = {'name': self._name} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
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 reset(self): """Resets the abuse count on this Dynamic DNS service""" api_args = {'reset': True} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
def _post(self, record_type, address, user=None): """Create a new DynamicDNS Service on the DynECT System""" self._record_type = record_type self._address = address if user: self._user = user self.uri = '/DDNS/{}/{}/{}/'.format(self._zone, self._fqdn, self._record_type) api_args = {'address': self._address} if user: api_args['user'] = self._user api_args['full_setup'] = True response = DynectSession.get_session().execute(self.uri, 'POST', api_args) for key, val in response['data'].items(): if user: if key == 'ddns': for ddns_key, ddns_val in val.items(): setattr(self, '_' + ddns_key, ddns_val) if key == 'new_user': user_name = val['user_name'] del val['user_name'] self._user = User(user_name, api=False, **val) elif key == 'active': self._active = Active(val) else: setattr(self, '_' + key, val)
def _update(self, api_args): """Update the Dyn System with data from this :class:`PerformanceMonitor` """ uri = '/RTTM/{}/{}/'.format(self.zone, self.fqdn) response = DynectSession.get_session().execute(uri, 'PUT', api_args) self._build(response['data']['performance_monitor'])
def cancel(self): """Cancels Task""" api_args = dict() response = DynectSession.get_session().execute(self.uri, 'DELETE', api_args) self._build(response['data'])
def _update(self, api_args=None): """Update an existing :class:`AdvancedRedirect` Service on the DynECT System""" self.uri = '/AdvRedirect/{}/{}/'.format(self._zone, self._fqdn) response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data'])
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'])
def _update(self, api_args): """Update this object by making a PUT API call with the provided api_args """ response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) self._build(response['data'])
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_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 __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 deactivate(self): """Deactivate this Dynamic DNS service""" api_args = {'deactivate': True} response = DynectSession.get_session().execute(self.uri, 'PUT', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
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_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 """ self.records = {} uri = '/AllRecord/{}/'.format(self.zone) 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.zone, fqdn, **record)) records[key] = list_records return records
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 _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(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_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(self): """Build an object around an existing DynECT HTTPRedirect Service""" self.uri = '/HTTPRedirect/{}/{}/'.format(self._zone, self._fqdn) api_args = {'detail': 'Y'} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
def _post(self, *args, **kwargs): """Create a new :class:`TSIG` object on the DynECT System""" api_args = {'name': self._name, 'secret': kwargs['secret'], 'algorithm': kwargs['algorithm']} response = DynectSession.get_session().execute(self.uri, 'POST', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)
def _get(self): """Update this object from an existing :class:`DNSSEC` service from the Dynect System. """ api_args = {} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) self._build(response['data'])
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 status(self): """Get the current status of this :class:`HealthMonitor` from the DynECT System """ api_args = {} uri = '/Failover/{}/{}/'.format(self.zone, self.fqdn) respnose = DynectSession.get_session().execute(uri, 'GET', api_args) return respnose['data']['status']
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 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)
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
def _post(self, groups, ttl=None): """Create a new :class:`Geo` service on the DynECT System""" self._groups = groups self._ttl = ttl api_args = {'groups': []} nodes = [] for group in groups: weight = {} serve_count = {} ttls = {} label = {} rdata = {} for record in group.geo_records: weight_name = ''.join([record.rec_name, '_weight']) serve_name = ''.join([record.rec_name, '_serve_count']) ttl_name = ''.join([record.rec_name, '_ttl']) label_name = ''.join([record.rec_name, '_label']) rdata_name = ''.join([record.rec_name, '_rdata']) # Build weight hash if hasattr(record, 'weight'): if weight_name in weight: weight[weight_name].append(record.weight) else: weight[weight_name] = [record.weight] # Build serve_count hash if hasattr(record, 'serve_count'): serve_count[serve_name] = str(record.serve_count) # Build ttl hash if ttl_name in serve_count: ttls[ttl_name] = str(record.ttl) or str(self._ttl) # Build label hash autolabel = '' if label_name in label: label[label_name].append(record.label or autolabel) else: label[label_name] = [record.label or autolabel] # Build rdata hash if rdata_name in rdata: rdata[rdata_name].append(record.geo_rdata) else: rdata[rdata_name] = [record.geo_rdata] nodes.append(record.geo_node) group_data = {'weight': weight, 'serve_count': serve_count, 'ttl': ttls, 'label': label, 'rdata': rdata, 'countries': group.countries, 'name': group._name} api_args['groups'].append(group_data) if self._ttl: api_args['ttl'] = self._ttl api_args['nodes'] = nodes response = DynectSession.get_session().execute(self.uri, 'POST', api_args) for key, val in response['data'].items(): if key == 'groups': pass elif key == 'nodes': pass else: setattr(self, '_' + key, val)
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)
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 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 _get(self, service_id): """Build an object around an existing DynECT ReverseDNS Service""" self._iptrack_id = service_id uri = '/IPTrack/{}/{}/{}/'.format(self._zone, self._fqdn, self._iptrack_id) api_args = {} response = DynectSession.get_session().execute(uri, 'GET', api_args) self._build(response['data']) self.uri = '/IPTrack/{}/{}/{}/'.format(self._zone, self._fqdn, self._iptrack_id)
def _get(self): """Build an object around an existing DynECT :class:`AdvancedRedirectRule` Service""" self.uri = '/AdvRedirectRule/{}/{}/{}'.format(self._zone, self._fqdn, self._public_id) api_args = {'detail': 'Y'} response = DynectSession.get_session().execute(self.uri, 'GET', api_args) for key, val in response['data'].items(): setattr(self, '_' + key, val)