def test_introducer_furl(self, deploy_config, details): """ The introducer furl included in the generated configuration includes the introducer tub id and swissnum and a connection hint derived from the address information on the subscription details. """ config = create_configuration(deploy_config, details, model) introducer_furl = loads( config.data["introducer.json"])["introducer"]["introducer_furl"] self.assertThat( decode_furl(introducer_furl), Equals(( details.introducer_tub_id, [ "{}:{}".format(details.publichost, details.introducer_port_number) ], decode_furl(details.external_introducer_furl)[2], )), ) # There's another copy of that in the storage server's config. Make # sure it matches. self.assertThat( introducer_furl, Equals( loads(config.data["storage.json"])["storage"] ["introducer_furl"]), )
def _register_reference(key, config, tub, referenceable): """ Register a referenceable in a tub with a stable fURL. Stability is achieved by storing the fURL in the configuration the first time and then reading it back on for future calls. :param bytes key: An identifier for this reference which can be used to identify its fURL in the configuration. :param _Config config: The configuration to use for fURL persistence. :param Tub tub: The tub in which to register the reference. :param Referenceable referenceable: The referenceable to register in the Tub. :return bytes: The fURL at which the object is registered. """ persisted_furl = config.get_private_config( key, default=None, ) name = None if persisted_furl is not None: _, _, name = decode_furl(persisted_furl) registered_furl = tub.registerReference( referenceable, name=name, ) if persisted_furl is None: config.write_private_config(key, registered_furl) return registered_furl
def introducer_furl(introducer, base_dir): furl_fname = join(base_dir, 'introducer', 'private', 'introducer.furl') while not exists(furl_fname): print("Don't see {} yet".format(furl_fname)) sleep(.1) furl = open(furl_fname, 'r').read() # Make sure it is valid. _, location, _ = decode_furl(furl) if location == []: raise Exception("introducer furl with no location hints: {}".format(furl)) return furl
def _introduce(adave): # The third way is to mangle the location hints, which will # result in a failure during negotiation as it attempts to # establish a TCP connection. (tubid, location_hints, name) = decode_furl(adave.tracker.url) # highly unlikely that there's anything listening on this port location_hints = ["tcp:127.0.0.1:2"] adave.tracker.url = encode_furl(tubid, location_hints, name) return self.shouldFail(ConnectionRefusedError, "Bad.test_location", "Connection was refused by other side", self.acarol.callRemote, "set", adave)
def _introduce(adave): # The second way is to mangle the tubid, which will result in a # failure during negotiation. We mangle it by reversing the # characters: this makes it syntactically valid but highly # unlikely to remain the same. NOTE: this will have to change # when we modify the way gifts are referenced, since tracker.url # is scheduled to go away. (tubid, location_hints, name) = decode_furl(adave.tracker.url) tubid = "".join(reversed(tubid)) adave.tracker.url = encode_furl(tubid, location_hints, name) return self.shouldFail(BananaError, "Bad.test_tubid", "unknown TubID", self.acarol.callRemote, "set", adave)
def test_introducer_furl(self, deploy_config, details): """ The introducer furl included in the generated configuration includes the introducer tub id and swissnum and a connection hint derived from the address information on the subscription details. """ config = create_configuration(deploy_config, details, model) introducer_furl = loads(config.data["introducer.json"])["introducer"]["introducer_furl"] self.assertThat( decode_furl(introducer_furl), Equals(( details.introducer_tub_id, ["{}:{}".format(details.publichost, details.introducer_port_number)], decode_furl(details.external_introducer_furl)[2], )), ) # There's another copy of that in the storage server's config. Make # sure it matches. self.assertThat( introducer_furl, Equals(loads(config.data["storage.json"])["storage"]["introducer_furl"]), )
def _introduce(adave): # The next form of mangling is to connect to a port which never # responds, which could happen if a firewall were silently # dropping the TCP packets. We can't accurately simulate this # case, but we can connect to a port which accepts the connection # and then stays silent. This should trigger the overall # connection timeout. (tubid, location_hints, name) = decode_furl(adave.tracker.url) location_hints = ["tcp:127.0.0.1:%d" % p.getHost().port] adave.tracker.url = encode_furl(tubid, location_hints, name) self.tubD._test_options['connect_timeout'] = 2 return self.shouldFail(NegotiationError, "Bad.test_hang", "no connection established within client timeout", self.acarol.callRemote, "set", adave)
def introducer_furl(introducer, temp_dir): furl_fname = join(temp_dir, 'introducer', 'private', 'introducer.furl') while not exists(furl_fname): print("Don't see {} yet".format(furl_fname)) sleep(.1) furl = open(furl_fname, 'r').read() tubID, location_hints, name = decode_furl(furl) if not location_hints: # If there are no location hints then nothing can ever possibly # connect to it and the only thing that can happen next is something # will hang or time out. So just give up right now. raise ValueError( "Introducer ({!r}) fURL has no location hints!".format( introducer_furl, ), ) return furl
def __init__(self, when, index, canary, ann_d): self.when = when self.index = index self.canary = canary self.announcement = ann_d self.service_name = ann_d["service-name"] self.version = ann_d.get("my-version", "") self.nickname = ann_d.get("nickname", u"") (_, key_s) = index self.serverid = key_s furl = ann_d.get("anonymous-storage-FURL") if furl: _, self.connection_hints, _ = decode_furl(furl) else: self.connection_hints = []
def _introduce(adave): # The next form of mangling is to connect to a port which never # responds, which could happen if a firewall were silently # dropping the TCP packets. We can't accurately simulate this # case, but we can connect to a port which accepts the connection # and then stays silent. This should trigger the overall # connection timeout. (tubid, location_hints, name) = decode_furl(adave.tracker.url) location_hints = ["tcp:127.0.0.1:%d" % p.getHost().port] adave.tracker.url = encode_furl(tubid, location_hints, name) self.tubD._test_options['connect_timeout'] = 2 return self.shouldFail( NegotiationError, "Bad.test_hang", "no connection established within client timeout", self.acarol.callRemote, "set", adave)
def __init__(self, url=None): self.locationHints = [] # list of strings self.url = url if url: self.tubID, self.locationHints, self.name = decode_furl(url)
def _get_hints(furl): tub_id, hints, name = decode_furl(furl) return hints
def make_external_furl(internal_furl, publichost, port): tub_id, location_hints, name = decode_furl(internal_furl) location_hints[:] = [u"{}:{}".format(publichost, port).encode("ascii")] return encode_furl(tub_id, location_hints, name)
import attr from attr import validators from pem import parse from twisted.python.url import URL from foolscap.pb import Tub from foolscap.furl import decode_furl, encode_furl from lae_util.validators import all validate_furl = all( attr.validators.instance_of(str), lambda inst, attr, value: decode_furl(value), ) @attr.s(frozen=True) class DeploymentConfiguration(object): domain = attr.ib(validator=attr.validators.instance_of(unicode)) # This supposes the storage server and introducer run in the same pod. # Which is how they run for now. And I'm not sure why it would ever be # different. private_host = u"127.0.0.1" # It is optional because DeploymentConfiguration is used basically # everywhere but only the subscription-converger needs to know a # Kubernetes namespace. :/
def test_complete(self, introducer_config, storage_config): """ Introducer and storage configuration can be supplied via ``configure_tahoe``. """ introducer_furl = introducer_config["introducer_furl"] config = marshal_tahoe_configuration( introducer_pem=introducer_config["node_pem"], storage_pem=storage_config["node_pem"], storage_privkey=storage_config["node_privkey"], introducer_port=introducer_config["port"], storageserver_port=storage_config["port"], bucket_name=storage_config["bucket_name"], publichost=storage_config["publichost"], privatehost=storage_config["privatehost"], introducer_furl=introducer_furl, s3_access_key_id=storage_config["s3_access_key_id"], s3_secret_key=storage_config["s3_secret_key"], log_gatherer_furl=introducer_config["log_gatherer_furl"], stats_gatherer_furl=introducer_config["stats_gatherer_furl"], ) configure_tahoe({"introducer": config["introducer"]}, self.nodes.introducer.path) configure_tahoe({"storage": config["storage"]}, self.nodes.storage.path) intro_config_path = self.nodes.introducer.child(b"tahoe.cfg") storage_config_path = self.nodes.storage.child(b"tahoe.cfg") config_files = [intro_config_path, storage_config_path] # If the log and stats gatherers are given, the storage and # introducer configurations are written with those values for # those fields. self.expectThat( config_files, AllMatch( hasConfiguration({ ("node", "log_gatherer.furl", introducer_config["log_gatherer_furl"]), ("client", "stats_gatherer.furl", introducer_config["stats_gatherer_furl"]), }))) # The introducer furl in the introducer configuration is # written to the ``private/introducer.furl`` file in the # introducer's state/configuration directory and to the # storage node's configuration file. self.expectThat( self.nodes.introducer.descendant([b"private", b"introducer.furl"]), hasContents(introducer_furl), ) tub_id, location_hints, name = decode_furl(introducer_furl) port = location_hints[0].split(":")[1] location_hints[:0] = [storage_config["privatehost"] + ":" + port] internal_introducer_furl = encode_furl(tub_id, location_hints, name) self.expectThat( storage_config_path, hasConfiguration({ ("client", "introducer.furl", internal_introducer_furl), }), )
def test_complete(self, introducer_config, storage_config): """ Introducer and storage configuration can be supplied via ``configure_tahoe``. """ introducer_furl = introducer_config["introducer_furl"] config = marshal_tahoe_configuration( introducer_pem=introducer_config["node_pem"], storage_pem=storage_config["node_pem"], storage_privkey=storage_config["node_privkey"], introducer_port=introducer_config["port"], storageserver_port=storage_config["port"], bucket_name=storage_config["bucket_name"], key_prefix=storage_config["key_prefix"], publichost=storage_config["publichost"], privatehost=storage_config["privatehost"], introducer_furl=introducer_furl, s3_access_key_id=storage_config["s3_access_key_id"], s3_secret_key=storage_config["s3_secret_key"], log_gatherer_furl=introducer_config["log_gatherer_furl"], stats_gatherer_furl=introducer_config["stats_gatherer_furl"], ) configure_tahoe({"introducer": config["introducer"]}, self.nodes.introducer.path) configure_tahoe({"storage": config["storage"]}, self.nodes.storage.path) intro_config_path = self.nodes.introducer.child(b"tahoe.cfg") storage_config_path = self.nodes.storage.child(b"tahoe.cfg") config_files = [intro_config_path, storage_config_path] # If the log and stats gatherers are given, the storage and # introducer configurations are written with those values for # those fields. self.expectThat( config_files, AllMatch( hasConfiguration({ ("node", "log_gatherer.furl", introducer_config["log_gatherer_furl"]), ("client", "stats_gatherer.furl", introducer_config["stats_gatherer_furl"]), }))) # The introducer furl in the introducer configuration is # written to the ``private/introducer.furl`` file in the # introducer's state/configuration directory and to the # storage node's configuration file. self.expectThat( self.nodes.introducer.descendant([b"private", b"introducer.furl"]), hasContents(introducer_furl), ) tub_id, location_hints, name = decode_furl(introducer_furl) port = location_hints[0].split(":")[1] location_hints[:0] = [storage_config["privatehost"] + ":" + port] internal_introducer_furl = encode_furl(tub_id, location_hints, name) self.expectThat( storage_config_path, hasConfiguration({ ("client", "introducer.furl", internal_introducer_furl), }), ) self.expectThat( self.nodes.storage.child(b"announcement-seqnum"), hasContentsMatching( # The second hand could click over between when the file is # written and when this test code runs. In fact, it could # click over multiple times... But the only way to really fix # that is to parameterize the clock and the structure of # configure_tahoe makes that tricky. So just suppose that one # second is all the leeway we need to make this reliable. AfterPreprocessing(int, Not(LessThan(int(time() - 1)))), ), )
def get_hint_port(furl): tub_id, location_hints, name = decode_furl(furl) host, port = location_hints[0].split(u":") return int(port)