Modified fn-setup to check FMS, added fn-setupfms command. Features: Modified fn-setup to check the FMS configuration and update the config file. --fmshost, --fmsport, --fmsid set the host, port and fms id respectively. Added fn-setupfms command to test and update the FMS configuration.
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py
--- a/infocalypse/__init__.py
+++ b/infocalypse/__init__.py
@@ -361,7 +361,8 @@ from infcmds import get_config_info, exe
execute_push, execute_setup, execute_copy, execute_reinsert, \
execute_info
-from fmscmds import execute_fmsread, execute_fmsnotify, get_uri_from_hash
+from fmscmds import execute_fmsread, execute_fmsnotify, get_uri_from_hash, \
+ execute_setupfms
from sitecmds import execute_putsite, execute_genkey
from wikicmds import execute_wiki, execute_wiki_apply
@@ -699,6 +700,16 @@ def infocalypse_setup(ui_, **opts):
opts['fcpport'],
opts['tmpdir'])
+ if not opts['nofms']:
+ execute_setupfms(ui_, opts)
+ else:
+ ui_.status("Skipped FMS configuration because --nofms was set.\n")
+
+def infocalypse_setupfms(ui_, **opts):
+ """ Setup or modify the fms configuration. """
+ # REQUIRES config file.
+ execute_setupfms(ui_, opts)
+
#----------------------------------------------------------"
def do_archive_create(ui_, opts, params, stored_cfg):
""" fn-archive --create."""
@@ -795,6 +806,11 @@ FCP_OPTS = [('', 'fcphost', '', 'fcp hos
('', 'fcpport', 0, 'fcp port'),
]
+FMS_OPTS = [('', 'fmshost', '', 'fms host'),
+ ('', 'fmsport', 0, 'fms port'),
+]
+
+
AGGRESSIVE_OPT = [('', 'aggressive', None, 'aggressively search for the '
+ 'latest USK index'),]
NOSEARCH_OPT = [('', 'nosearch', None, 'use USK version in URI'), ]
@@ -895,10 +911,19 @@ cmdtable = {
"[options]"),
"fn-setup": (infocalypse_setup,
- [('', 'tmpdir', '~/infocalypse_tmp', 'temp directory'),]
- + FCP_OPTS,
+ [('', 'tmpdir', '~/infocalypse_tmp', 'temp directory'),
+ ('', 'nofms', None, 'skip FMS configuration'),
+ ('', 'fmsid', '', "fmsid (only part before '@'!)"),
+ ('', 'timeout', 30, "fms socket timeout in seconds")]
+ + FCP_OPTS
+ + FMS_OPTS,
"[options]"),
+ "fn-setupfms": (infocalypse_setupfms,
+ [('', 'fmsid', '', "fmsid (only part before '@'!)"),
+ ('', 'timeout', 30, "fms socket timeout in seconds"),]
+ + FMS_OPTS,
+ "[options]"),
"fn-archive": (infocalypse_archive,
[('', 'uri', '', 'Request URI for --pull, Insert URI ' +
@@ -915,10 +940,10 @@ cmdtable = {
+ NOSEARCH_OPT
+ AGGRESSIVE_OPT,
"[options]"),
-
}
commands.norepo += ' fn-setup'
+commands.norepo += ' fn-setupfms'
commands.norepo += ' fn-genkey'
commands.norepo += ' fn-archive'
diff --git a/infocalypse/config.py b/infocalypse/config.py
--- a/infocalypse/config.py
+++ b/infocalypse/config.py
@@ -81,6 +81,7 @@ def norm_path(dir_name):
fixed = split[0].replace(':', '') + split[1]
return fixed
+# REDFLAG: THis is an ancient hack. Safe to back it out?
# NOTE:
# The bug prevents ConfigParser from even reading
# the file. That's why I'm operating on the file
@@ -131,7 +132,7 @@ class Config:
self.file_name = None
# Use a dict instead of members to avoid pylint R0902.
- self.defaults = {}
+ self.defaults = {} # REDFLAG: Why is this called defaults? BAD NAME
self.defaults['HOST'] = '127.0.0.1'
self.defaults['PORT'] = 9481
self.defaults['TMP_DIR'] = None
diff --git a/infocalypse/devnotes.txt b/infocalypse/devnotes.txt
--- a/infocalypse/devnotes.txt
+++ b/infocalypse/devnotes.txt
@@ -1,8 +1,11 @@
!!! experimental branch for testing wiki over hg idea !!!
See (note updated uri)
-reenet:USK@Gq-FBhpgvr11VGpapG~y0rGFOAHVfzyW1WoKGwK-fFw,MpzFUh5Rmw6N~aMKwm9h2Uk~6aTRhYaY0shXVotgBUc,AQACAAE/fniki/2/
+reenet:USK@Gq-FBhpgvr11VGpapG~y0rGFOAHVfzyW1WoKGwK-fFw,MpzFUh5Rmw6N~aMKwm9h2Uk~6aTRhYaY0shXVotgBUc,AQACAAE/fniki/-22/
!!!
+djk20100207
+BUG: fn-wiki will run without .infocalypse. audit other new commands, should abort cleanly.
+
djk20100123
Saw error reinserting fred staging mirror:
{4}:008c3b951f:(102, 117, 0):PutSuccessful
diff --git a/infocalypse/fmscmds.py b/infocalypse/fmscmds.py
--- a/infocalypse/fmscmds.py
+++ b/infocalypse/fmscmds.py
@@ -21,6 +21,8 @@
"""
# REDFLAG: Go back and fix all the places where you return instead of Abort()
+import socket
+
from mercurial import util
from fcpclient import get_usk_hash
@@ -416,3 +418,139 @@ def get_uri_from_hash(ui_, dummy, params
return target_usk
+
+CRLF = '\x0d\x0a'
+FMS_TIMEOUT_SECS = 30
+FMS_SOCKET_ERR_MSG = """
+Socket level error.
+It looks like your FMS host or port might be wrong.
+Set them with --fmshost and/or --fmsport.
+"""
+
+def connect_to_fms(ui_, fms_host, fms_port, timeout):
+ """ INTERNAL: Helper, connects to fms and reads the login msg. """
+ ui_.status("Testing FMS connection [%s:%i]...\n" % (fms_host, fms_port))
+ try:
+ old_timeout = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(timeout)
+ connected_socket = None
+ try:
+ connected_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ connected_socket.connect((fms_host, fms_port))
+ bytes = ''
+ while bytes.find(CRLF) == -1:
+ bytes = bytes + connected_socket.recv(4096)
+ finally:
+ socket.setdefaulttimeout(old_timeout)
+ if connected_socket:
+ connected_socket.close()
+
+ except socket.error: # Not an IOError until 2.6.
+ ui_.warn(FMS_SOCKET_ERR_MSG)
+ return None
+
+ except IOError:
+ ui_.warn(FMS_SOCKET_ERR_MSG)
+ return None
+
+ return bytes
+
+
+# Passing opts instead of separate args to get around pylint
+# warning about long arg list.
+def get_fms_args(cfg, opts):
+ """ INTERNAL: Helper to extract args from Config/mercurial opts. """
+ def false_to_none(value):
+ """ INTERNAL: Return None if not bool(value), value otherwise. """
+ if value:
+ return value
+ return None
+
+ fms_id = false_to_none(opts['fmsid'])
+ fms_host = false_to_none(opts['fmshost'])
+ fms_port = false_to_none(opts['fmsport'])
+ timeout = opts['timeout']
+
+ if not cfg is None:
+ if fms_id is None:
+ fms_id = cfg.defaults.get('FMS_ID', None)
+ if fms_host is None:
+ fms_host = cfg.defaults.get('FMS_HOST', None)
+ if fms_port is None:
+ fms_port = cfg.defaults.get('FMS_PORT', None)
+
+ if fms_id is None:
+ fms_id = 'None' # hmmm
+ if fms_host is None:
+ fms_host = '127.0.0.1'
+ if fms_port is None:
+ fms_port = 1119
+
+ return (fms_id, fms_host, fms_port, timeout)
+
+# DCI: clean up defaults
+def setup_fms_config(ui_, cfg, opts):
+ """ INTERNAL: helper tests the fms connection. """
+
+ fms_id, fms_host, fms_port, timeout = get_fms_args(cfg, opts)
+
+ ui_.status("Running FMS checks...\nChecking fms_id...\n")
+ if fms_id.find('@') != -1:
+ ui_.warn("\n")
+ ui_.warn(""" The FMS id should only contain the part before the '@'!
+ You won't be able to use fn-fmsnotify until this is fixed.
+ Run: hg fn-setupfms with the --fmsid argument.
+
+""")
+ elif fms_id.lower() == 'none':
+ ui_.warn(""" FMS id isn't set!
+ You won't be able to use fn-fmsnotify until this is fixed.
+ Run: hg fn-setupfms with the --fmsid argument.
+
+""")
+ else:
+ ui_.status("OK.\n\n") # hmmm... what if they manually edited the config?
+
+ bytes = connect_to_fms(ui_, fms_host, fms_port, timeout)
+ if not bytes:
+ if not bytes is None:
+ ui_.warn("Connected but no response. Are you sure that's "
+ "an FMS server?\n")
+ return None
+
+ fields = bytes.split(' ')
+ if fields[0] != '200':
+ ui_.warn("Didn't get expected response from FMS server!\n")
+ return None
+
+ if not bytes.lower().find("posting allowed"):
+ ui_.warn("Didn't see expected 'posting allowed' message.\n")
+ ui_.warn("Check that FMS is setup to allow outgoing message.\n")
+ return None # Hmmm.. feeble, relying on message text.
+ else:
+ ui_.status("Got expected response from FMS. Looks good.\n")
+
+ return (fms_host, fms_port, fms_id)
+
+def execute_setupfms(ui_, opts):
+ """ Execute the fn-setupfms command. """
+ cfg = Config.from_ui(ui_)
+ result = setup_fms_config(ui_, cfg, opts)
+ if result:
+ cfg.defaults['FMS_ID'] = result[2]
+ cfg.defaults['FMS_HOST'] = result[0]
+ cfg.defaults['FMS_PORT'] = result[1]
+ ui_.status("""Updating config file:
+fms_id = %s
+fms_host = %s
+fms_port = %i
+""" % (result[2], result[0], result[1]))
+ Config.to_file(cfg)
+ else:
+ ui_.warn("""
+Run:
+ hg fn-setupfms
+with the appropriate arguments to try to fix the problem.
+
+""")
+
diff --git a/infocalypse/infcmds.py b/infocalypse/infcmds.py
--- a/infocalypse/infcmds.py
+++ b/infocalypse/infcmds.py
@@ -768,6 +768,7 @@ def setup_tmp_dir(ui_, tmp):
ui_.warn(err)
return tmp
+
MSG_HGRC_SET = \
"""Read the config file name from the:
@@ -788,8 +789,13 @@ want to re-run setup.
Consider before deleting it. It may contain
the *only copy* of your private key.
+If you're just trying to update the FMS configuration run:
+
+hg fn-setupfms
+
+instead.
+
"""
-
def execute_setup(ui_, host, port, tmp, cfg_file = None):
""" Run the setup command. """
def connection_failure(msg):
@@ -797,6 +803,7 @@ def execute_setup(ui_, host, port, tmp,
ui_.warn(msg)
ui_.warn("It looks like your FCP host or port might be wrong.\n")
ui_.warn("Set them with --fcphost and/or --fcpport and try again.\n")
+ raise util.Abort("Connection to FCP server failed.")
# Fix defaults.
if host == '':
@@ -820,8 +827,7 @@ def execute_setup(ui_, host, port, tmp,
tmp = setup_tmp_dir(ui_, tmp)
if not is_writable(tmp):
- ui_.warn("Can't write to temp dir: %s\n" % tmp)
- return
+ raise util.Abort("Can't write to temp dir: %s\n" % tmp)
# Test FCP connection.
timeout_secs = 20
@@ -841,7 +847,6 @@ def execute_setup(ui_, host, port, tmp,
if not connection.is_connected():
connection_failure(("\nGave up after waiting %i secs for an "
+ "FCP NodeHello.\n") % timeout_secs)
- return
ui_.status("Looks good.\nGenerating a default private key...\n")
@@ -854,17 +859,14 @@ def execute_setup(ui_, host, port, tmp,
except FCPError:
# Protocol error.
connection_failure("\nMaybe that's not an FCP server?\n")
- return
except socket.error: # Not an IOError until 2.6.
# Horked.
connection_failure("\nSocket level error.\n")
- return
except IOError:
# Horked.
connection_failure("\nSocket level error.\n")
- return
cfg = Config()
cfg.defaults['HOST'] = host
@@ -882,6 +884,8 @@ cfg file: %s
Default private key:
%s
+The config file was successfully written!
+
""" % (host, port, tmp, cfg_file, default_private_key))