Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
warner committed Mar 31, 2016
1 parent 5b40b54 commit 1efd0ee
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 114 deletions.
69 changes: 15 additions & 54 deletions src/foolscap/appserver/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# does "flappserver start" need us to refrain from importing the reactor here?
# A: probably, to allow --reactor= to work
import foolscap
from foolscap.api import Tub, Referenceable, fireEventually
from foolscap.api import Tub, Referenceable
from foolscap.pb import generateSwissnumber
from foolscap.appserver.services import build_service, BadServiceArguments
from foolscap.appserver.server import AppServer, load_service_data, save_service_data
Expand Down Expand Up @@ -41,8 +41,8 @@ class CreateOptions(BaseOptions):
("quiet", "q", "Be silent upon success"),
]
optParameters = [
("port", "p", "tcp:0", "TCP port to listen on (strports string)"),
("location", "l", "", "Tub location hints to use in generated FURLs. An empty location means to generate one automatically, by looking at the active network interfaces."),
("port", "p", "tcp:3116", "TCP port to listen on (strports string)"),
("location", "l", None, "(required) Tub location hints to use in generated FURLs. e.g. 'example.org:3116'"),
("umask", None, None, "(octal) file creation mask to use for the server. If not provided, the current umask (%04o) is copied." % get_umask()),
]

Expand All @@ -57,6 +57,8 @@ def parseArgs(self, basedir):
def postOptions(self):
if self["umask"] is None:
self["umask"] = get_umask()
if not self["location"]:
raise usage.UsageError("--location= is mandatory")

FLAPPSERVER_TACFILE = """\
# -*- python -*-
Expand Down Expand Up @@ -93,13 +95,14 @@ def run(self, options):
os.makedirs(os.path.join(basedir, "services"))
os.chmod(basedir, 0700)

# start the server and let it run briefly. This lets the Tub spin up,
# create the key, decide upon a port, and auto-determine its location
# (if one was not provided with --location=). The base FURL will be
# Start the server and let it create the key. The base FURL will be
# written to a file so that subsequent 'add' and 'list' can compute
# FURLs without needing to run the Tub (which might already be
# running).

assert options["port"]
assert options["location"]

f = open(os.path.join(basedir, "port"), "w")
f.write("%s\n" % options["port"])
f.close()
Expand All @@ -115,45 +118,8 @@ def run(self, options):

save_service_data(basedir, {"version": 1, "services": {}})

self.server = None
d = fireEventually(basedir)
d.addCallback(AppServer, stdout)
d.addCallback(self.stash_and_start_appserver)
d.addCallback(self.appserver_ready, options)
d.addBoth(self.stop_appserver)
d.addCallback(lambda ign: 0)
return d

def stash_and_start_appserver(self, ap):
self.server = ap
self.server.startService()
return ap.when_ready()

def appserver_ready(self, _ignored, options):
basedir = options.basedir
stdout = options.stdout
quiet = options["quiet"]

tub = self.server.tub
# what port is it actually listening on?
l0 = tub.getListeners()[0]

port = options["port"]
got_port = port
pieces = port.split(":")
if "0" in pieces:
# If the --port argument didn't tightly specify the port to use,
# write down the one we actually got, so we'll keep using the
# same one later
pieces[pieces.index("0")] = str(l0.getPortnum())
if pieces[0] != "tcp":
pieces = ["tcp"] + pieces
got_port = ":".join(pieces)
f = open(os.path.join(basedir, "port"), "w")
f.write(got_port + "\n")
f.close()

tubid = tub.getTubID()
a = AppServer(basedir, stdout)
tub = a.tub

sample_furl = tub.registerReference(Referenceable())
furl_prefix = sample_furl[:sample_furl.rfind("/")+1]
Expand All @@ -168,17 +134,12 @@ def appserver_ready(self, _ignored, options):
f.write(FLAPPSERVER_TACFILE % { 'path': stashed_path })
f.close()

if not quiet:
if not options["quiet"]:
print >>stdout, "Foolscap Application Server created in %s" % basedir
print >>stdout, "TubID %s, listening on port %s" % (tubid, got_port)
print >>stdout, "TubID %s, listening on port %s" % (tub.getTubID(),
options["port"])
print >>stdout, "Now launch the daemon with 'flappserver start %s'" % basedir

def stop_appserver(self, res):
d = defer.succeed(None)
if self.server:
d.addCallback(lambda ign: self.server.stopService())
d.addCallback(lambda ign: res)
return d
return defer.succeed(0)

class AddOptions(BaseOptions):
synopsis = "Usage: flappserver add [--comment C] BASEDIR SERVICE-TYPE SERVICE-ARGS.."
Expand Down
36 changes: 14 additions & 22 deletions src/foolscap/appserver/server.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@

import os, sys, json, ast
from twisted.application import service
from twisted.python import log
from twisted.internet import defer
from foolscap.api import Tub
from foolscap.appserver.services import build_service
from foolscap.observer import OneShotObserverList
from foolscap.util import move_into_place

class UnknownVersion(Exception):
Expand Down Expand Up @@ -72,36 +69,31 @@ def __init__(self, basedir=".", stdout=sys.stdout):
self.umask = int(umask, 8) # octal string like 0022
except EnvironmentError:
self.umask = None
port = open(os.path.join(basedir, "port")).read().strip()
self.port = open(os.path.join(basedir, "port")).read().strip()
self.tub = Tub(certFile=os.path.join(basedir, "tub.pem"))
self.tub.listenOn(port)
self.tub.listenOn(self.port)
self.tub.setServiceParent(self)
self.tub.registerNameLookupHandler(self.lookup)
self.setMyLocation()
print >>stdout, "Server Running"
self.ready_observers = OneShotObserverList()
# make sure we log any problems
self.when_ready().addErrback(log.err)

def when_ready(self):
# return a Deferred that fires (with this AppServer instance) when
# the service is running and the location is set.
return self.ready_observers.whenFired()

def startService(self):
if self.umask is not None:
os.umask(self.umask)
service.MultiService.startService(self)
d = self.setMyLocation()
d.addBoth(self.ready_observers.fire)

def setMyLocation(self):
location = open(os.path.join(self.basedir, "location")).read().strip()
if location:
self.tub.setLocation(location)
return defer.succeed(self)
d = self.tub.setLocationAutomatically()
d.addCallback(lambda ign: self)
return d
location_fn = os.path.join(self.basedir, "location")
location = open(location_fn).read().strip()
if not location:
raise ValueError("This flappserver was created without "
"'--location=', and Foolscap no longer uses "
"IP-address autodetection. Please edit '%s' "
"to contain e.g. 'example.org:12345', with a "
"hostname and port number that match this "
"server (we're listening on %s)"
% (location_fn, self.port))
self.tub.setLocation(location)

def lookup(self, name):
# walk through our configured services, see if we know about this one
Expand Down
8 changes: 4 additions & 4 deletions src/foolscap/test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,8 @@ def makeServer(self, options={}, listenerOptions={}):
tub.startService()
self.services.append(tub)
portnum = allocate_tcp_port()
l = tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum,
_test_options=listenerOptions)
tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum,
_test_options=listenerOptions)
tub.setLocation("127.0.0.1:%d" % portnum)
self.target = Target()
return tub.registerReference(self.target), portnum
Expand All @@ -512,7 +512,7 @@ def makeSpecificServer(self, certData,
tub.startService()
self.services.append(tub)
portnum = allocate_tcp_port()
l = tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum)
tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum)
tub.setLocation("127.0.0.1:%d" % portnum)
self.target = Target()
return tub.registerReference(self.target), portnum
Expand All @@ -524,7 +524,7 @@ def createSpecificServer(self, certData,
tub.startService()
self.services.append(tub)
portnum = allocate_tcp_port()
l = tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum)
tub.listenOn("tcp:%d:interface=127.0.0.1" % portnum)
tub.setLocation("127.0.0.1:%d" % portnum)
target = Target()
return tub, target, tub.registerReference(target), portnum
Expand Down
51 changes: 18 additions & 33 deletions src/foolscap/test/test_appserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from foolscap.api import Tub, eventually
from foolscap.appserver import cli, server, client
from foolscap.test.common import ShouldFailMixin, StallMixin
from foolscap.util import allocate_tcp_port

orig_service_data = {"version": 1,
"services": {
Expand Down Expand Up @@ -132,7 +133,7 @@ def test_create(self):
basedir = "appserver/CLI/create"
os.makedirs(basedir)
serverdir = os.path.join(basedir, "fl")
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:1234", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand All @@ -151,7 +152,7 @@ def test_create_no_clobber_dir(self):
os.makedirs(basedir)
serverdir = os.path.join(basedir, "fl")
os.mkdir(serverdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 1)
self.failUnlessIn("Refusing to touch pre-existing directory", err)
Expand All @@ -164,13 +165,16 @@ def test_create2(self):
basedir = "appserver/CLI/create2"
os.makedirs(basedir)
serverdir = os.path.join(basedir, "fl")
d = self.run_cli("create", "--port","tcp:0", "--umask","022", serverdir)
portnum = allocate_tcp_port()
d = self.run_cli("create",
"--location", "localhost:%d" % portnum,
"--port", "tcp:%d" % portnum,
"--umask", "022", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
got_port = open(os.path.join(serverdir, "port"), "r").read().strip()
self.failIfEqual(got_port, "tcp:0") # it should pick a real port
portnum = int(got_port[got_port.find(":")+1:])
self.failUnlessEqual(got_port, "tcp:%d" % portnum)
prefix = open(os.path.join(serverdir, "furl_prefix"), "r").read().strip()
self.failUnless(prefix.endswith(":%d/" % portnum), prefix)
umask = open(os.path.join(serverdir, "umask")).read().strip()
Expand All @@ -193,29 +197,13 @@ def _check((rc,out,err)):
d.addCallback(_check)
return d

def test_create4(self):
basedir = "appserver/CLI/create4"
os.makedirs(basedir)
serverdir = os.path.join(basedir, "fl")
d = self.run_cli("create", "--port", "0", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
got_port = open(os.path.join(serverdir, "port"), "r").read().strip()
self.failIfEqual(got_port, "tcp:0") # it should pick a real port
portnum = int(got_port[got_port.find(":")+1:])
prefix = open(os.path.join(serverdir, "furl_prefix"), "r").read().strip()
self.failUnless(prefix.endswith(":%d/" % portnum), prefix)
d.addCallback(_check)
return d

def test_add(self):
basedir = "appserver/CLI/add"
os.makedirs(basedir)
serverdir = os.path.join(basedir, "fl")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -245,7 +233,7 @@ def test_add_service(self):
serverdir = os.path.join(basedir, "fl")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -288,7 +276,7 @@ def test_add_comment(self):
serverdir = os.path.join(basedir, "fl")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -322,7 +310,7 @@ def test_add_badargs(self):
servicesdir = os.path.join(serverdir, "services")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -359,7 +347,7 @@ def test_list(self):
serverdir = os.path.join(basedir, "fl")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -397,7 +385,7 @@ def test_list_comment(self):
serverdir = os.path.join(basedir, "fl")
incomingdir = os.path.join(basedir, "incoming")
os.mkdir(incomingdir)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand Down Expand Up @@ -444,7 +432,7 @@ def test_run(self):

self.tub = Tub()
self.tub.setServiceParent(self.s)
d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand All @@ -461,7 +449,6 @@ def _check_add((rc,out,err)):
def _start_server(ign):
ap = server.AppServer(serverdir, stdout)
ap.setServiceParent(self.s)
return ap.when_ready()
d.addCallback(_start_server)
# make sure the server can actually instantiate a service
d.addCallback(lambda _ign: self.tub.getReference(self.furl))
Expand Down Expand Up @@ -501,7 +488,7 @@ def test_run(self):
os.mkdir(incomingdir)
furlfile = os.path.join(basedir, "furlfile")

d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand All @@ -525,7 +512,6 @@ def _check_add((rc,out,err)):
def _start_server(ign):
ap = server.AppServer(serverdir, stdout)
ap.setServiceParent(self.s)
return ap.when_ready()
d.addCallback(_start_server)

sourcefile = os.path.join(basedir, "foo.txt")
Expand Down Expand Up @@ -712,7 +698,7 @@ def test_run(self):
os.mkdir(incomingdir)
self.furls = {}

d = self.run_cli("create", serverdir)
d = self.run_cli("create", "--location", "localhost:3116", serverdir)
def _check((rc,out,err)):
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.isdir(serverdir))
Expand All @@ -739,7 +725,6 @@ def _populate_foo(ign):
def _start_server(ign):
ap = server.AppServer(serverdir, stdout)
ap.setServiceParent(self.s)
return ap.when_ready()
d.addCallback(_start_server)

d.addCallback(lambda _ign:
Expand Down
2 changes: 1 addition & 1 deletion src/foolscap/test/test_gifts.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ def setUp(self):
for s in self.services:
s.startService()
p = allocate_tcp_port()
l = s.listenOn("tcp:%d:interface=127.0.0.1" % p)
s.listenOn("tcp:%d:interface=127.0.0.1" % p)
s.setLocation("127.0.0.1:%d" % p)
self.tubIDs = [self.tubA.getShortTubID(),
self.tubB.getShortTubID(),
Expand Down

0 comments on commit 1efd0ee

Please sign in to comment.