Repository: virtool/virtool
Issue: Virtool fails to start after initial setup when MongoDB is on a different server

After starting Virtool for the first time, I configured the connection to a MongoDB database running on a different server `mongodb`. This was stored in `settings.json` as follows:

```
    "db_host": "mongodb",
    "db_name": "virtool",
    "db_port": 27017,
```

However, after clicking 'Save and Reload', Virtool failed to start with the following error:

```
2018-02-12 23:30:40  base        DEBUG    Configuring Raven for host: <raven.conf.remote.RemoteConfig object at 0x7efc33c4eb00>
2018-02-12 23:30:41  app         INFO     Starting database checks. Do not interrupt. This may take several minutes.
2018-02-12 23:30:41  app         INFO     Checking viruses...
Sending message of length 3544 to https://sentry.io/api/220532/store/
Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/cx_Freeze/initscripts/__startup__.py", line 14, in run
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/cx_Freeze/initscripts/Console.py", line 26, in run
  File "run.py", line 58, in <module>
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/web.py", line 439, in run_app
  File "uvloop/loop.pyx", line 1364, in uvloop.loop.Loop.run_until_complete
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/web.py", line 263, in startup
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/signals.py", line 51, in send
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/aiohttp/signals.py", line 17, in _send
  File "/home/travis/build/virtool/virtool/virtool/app.py", line 100, in init_db
  File "/home/travis/build/virtool/virtool/virtool/organize.py", line 16, in organize_viruses
  File "/opt/python/3.6.3/lib/python3.6/concurrent/futures/thread.py", line 56, in run
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/pymongo/collection.py", line 2059, in distinct
  File "/opt/python/3.6.3/lib/python3.6/contextlib.py", line 81, in __enter__
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/pymongo/mongo_client.py", line 904, in _socket_for_reads
  File "/opt/python/3.6.3/lib/python3.6/contextlib.py", line 81, in __enter__
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/pymongo/mongo_client.py", line 868, in _get_socket
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/pymongo/topology.py", line 214, in select_server
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/pymongo/topology.py", line 189, in select_servers
pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused
```

Setting up MongoDB on the same server as Virtool (`localhost`) seems to work.

Changed files:
virtool/app.py, virtool/errors.py

diff --git a/virtool/app.py b/virtool/app.py
index 17e900f84..8d9cb5625 100644
--- a/virtool/app.py
+++ b/virtool/app.py
@@ -3,6 +3,7 @@ import concurrent.futures
 import logging
 import os
 import pymongo
+import pymongo.errors
 import ssl
 import sys
 import subprocess
@@ -16,6 +17,7 @@ import virtool.app_routes
 import virtool.app_settings
 import virtool.job_manager
 import virtool.job_resources
+import virtool.errors
 import virtool.error_pages
 import virtool.file_manager
 import virtool.organize
@@ -93,7 +95,19 @@ async def init_db(app):
     """
     app["db_name"] = app.get("db_name", None) or app["settings"].get("db_name")
 
-    app["db"] = motor_asyncio.AsyncIOMotorClient(io_loop=app.loop)[app["db_name"]]
+    db_host = app["settings"].get("db_host", "localhost")
+    db_port = app["settings"].get("db_port", 27017)
+
+    client = motor_asyncio.AsyncIOMotorClient(db_host, db_port, serverSelectionTimeoutMS=6000, io_loop=app.loop)
+
+    try:
+        await client.database_names()
+    except pymongo.errors.ServerSelectionTimeoutError:
+        raise virtool.errors.MongoConnectionError(
+            "Could not connect to MongoDB server at {}:{}".format(db_host, db_port)
+        )
+
+    app["db"] = client[app["db_name"]]
 
 
 async def init_check_db(app):
diff --git a/virtool/errors.py b/virtool/errors.py
index d882eddbd..3583f552a 100644
--- a/virtool/errors.py
+++ b/virtool/errors.py
@@ -10,6 +10,10 @@ class GitHubError(Exception):
     pass
 
 
+class MongoConnectionError(Exception):
+    pass
+
+
 class NCBIError(Exception):
     pass