def add_subdomains(subdomains, domain_fqa): """ subdomains => list Subdomain objects to add domain_fqa => fully qualified domain name to add the subdomain to. - must be owned by the Core's wallet - must not already have a subdomain associated with it """ assert isinstance(subdomains, list) # get domain's current zonefile zf_resp = bs_zonefile.get_name_zonefile(domain_fqa) if 'error' in zf_resp: log.error(zf_resp) raise Exception(zf_resp['error']) zonefile_json = zf_resp['zonefile'] def filter_by(x, y): try: resolve_subdomain(x, y) return False except SubdomainNotFound as e: return True zf_txt, subdomains_failed = subdomain_util.add_subdomains( subdomains, domain_fqa, zonefile_json, filter_by) if len(subdomains_failed) > 0: raise SubdomainAlreadyExists(subdomains[subdomains_failed[0]], domain_fqa) return issue_zonefile(domain_fqa, zf_txt)
def add_subdomains(subdomains, domain_fqa): """ subdomains => list Subdomain objects to add domain_fqa => fully qualified domain name to add the subdomain to. - must be owned by the Core's wallet - must not already have a subdomain associated with it """ assert isinstance(subdomains, list) # get domain's current zonefile zf_resp = bs_zonefile.get_name_zonefile(domain_fqa) if 'error' in zf_resp: log.error(zf_resp) raise Exception(zf_resp['error']) zonefile_json = zf_resp['zonefile'] def filter_by(x, y): try: resolve_subdomain(x, y) return False except SubdomainNotFound as e: return True zf_txt, subdomains_failed = subdomain_util.add_subdomains( subdomains, domain_fqa, zonefile_json, filter_by) if len(subdomains_failed) > 0: raise SubdomainAlreadyExists(subdomains[subdomains_failed[0]], domain_fqa) return issue_zonefile(domain_fqa, zf_txt)
def submit_transaction(self): queued_rows = list(self._get_queued_rows()) if len(queued_rows) == 0: return {'status': 'true', 'subdomain_updates': 0} zf_init = get_zonefile(self.domain) for slice_sz in range(len(queued_rows), -1, -1): if slice_sz == 0: return { 'error': "Failed to construct small enough zonefile (size < {})". format(self.zonefile_limit) } cur_queued_rows = queued_rows[:slice_sz] indexes, entries = zip(*cur_queued_rows) to_add = list(entries) kwargs = {} zf_txt, subs_failed = util.add_subdomains(to_add, self.domain, zf_init) if len(subs_failed) > 0: indexes = list(indexes) db_indexes_failed = [] subs_failed.sort(reverse=True) for i in subs_failed: db_indexes_failed.append(indexes.pop(i)) log.info("Subdomain already existed for ({})".format( [entries[i].name for i in subs_failed])) self._set_in_tx(db_indexes_failed, "ERR:ALREADYEXISTED") if len(indexes) == 0: return {'status': 'true', 'subdomain_updates': 0} if len(zf_txt) < self.zonefile_limit: break # issue user zonefile update to API endpoint target = "/v1/names/{}/zonefile".format(self.domain) resp = rest_to_api(target, data=json.dumps({'zonefile': zf_txt}), call=requests.put) log.info("Submitting zonefile (length = {})".format(len(zf_txt))) if resp.status_code != 202: msg = 'Error submitting subdomain bundle: {}'.format(resp.text) log.error(msg) try: resp_js = resp.json() if "maxLength" in str(resp_js["error"]): self.zonefile_limit = len(zf_txt) - 1 log.warn( "Zonefile too large for server, reducing zonefile size to {}" .format(self.zonefile_limit)) return { 'error': 'Zonefile too large, try again.', 'retry': True } except Exception as e: pass self._set_in_tx(indexes, "ERR:{}".format(msg)) return {'error': msg} try: resp_js = resp.json() except Exception as e: log.error("Error in response: {}".format(resp)) log.exception(e) return {'error': 'Error in parsing response'} if 'error' in resp_js: msg = 'Error submitting subdomain bundle: {}'.format( resp_js['error']) log.error(msg) self._set_in_tx(indexes, "ERR:{}".format(msg)) return {'error': msg} txid = str(resp_js['transaction_hash']) self._set_in_tx(indexes, txid) self.entries_per_tx_hint = min( len(indexes) + 1, config.max_entries_per_zonefile()) log.info('Issued update for {} subdomain entries. In tx: {}'.format( len(indexes), txid)) return { 'status': 'true', 'subdomain_updates': len(indexes), 'transaction_hash': txid }
def submit_transaction(self): queued_rows = list(self._get_queued_rows()) if len(queued_rows) == 0: return {'status' : 'true', 'subdomain_updates' : 0} zf_init = get_zonefile(self.domain) for slice_sz in range(len(queued_rows), -1, -1): if slice_sz == 0: return {'error' : "Failed to construct small enough zonefile (size < {})".format(self.zonefile_limit)} cur_queued_rows = queued_rows[:slice_sz] indexes, entries = zip(* cur_queued_rows) to_add = list(entries) kwargs = {} zf_txt, subs_failed = util.add_subdomains(to_add, self.domain, zf_init) if len(subs_failed) > 0: indexes = list(indexes) db_indexes_failed = [] subs_failed.sort(reverse=True) for i in subs_failed: db_indexes_failed.append(indexes.pop(i)) log.info("Subdomain already existed for ({})".format( [ entries[i].name for i in subs_failed ] )) self._set_in_tx(db_indexes_failed, "ERR:ALREADYEXISTED") if len(indexes) == 0: return {'status' : 'true', 'subdomain_updates' : 0} if len(zf_txt) < self.zonefile_limit: break # issue user zonefile update to API endpoint target = "/v1/names/{}/zonefile".format(self.domain) resp = rest_to_api(target, data = json.dumps({'zonefile' : zf_txt}), call = requests.put) log.info("Submitting zonefile (length = {})".format(len(zf_txt))) if resp.status_code != 202: msg = 'Error submitting subdomain bundle: {}'.format(resp.text) log.error(msg) try: resp_js = resp.json() if "maxLength" in str(resp_js["error"]): self.zonefile_limit = len(zf_txt) - 1 log.warn("Zonefile too large for server, reducing zonefile size to {}".format( self.zonefile_limit)) return {'error' : 'Zonefile too large, try again.', 'retry' : True} except Exception as e: pass self._set_in_tx(indexes, "ERR:{}".format(msg)) return {'error' : msg} try: resp_js = resp.json() except Exception as e: log.error("Error in response: {}".format(resp)) log.exception(e) return {'error' : 'Error in parsing response'} if 'error' in resp_js: msg = 'Error submitting subdomain bundle: {}'.format(resp_js['error']) log.error(msg) self._set_in_tx(indexes, "ERR:{}".format(msg)) return {'error' : msg} txid = str(resp_js['transaction_hash']) self._set_in_tx(indexes, txid) self.entries_per_tx_hint = min(len(indexes) + 1, config.max_entries_per_zonefile()) log.info('Issued update for {} subdomain entries. In tx: {}'.format( len(indexes), txid)) return {'status' : 'true', 'subdomain_updates' : len(indexes), 'transaction_hash' : txid}