mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #289 from tokejepsen/2.x/feature/cloud_mongo
Cloud Mongo
This commit is contained in:
commit
ce7bf38c2a
12 changed files with 137 additions and 115 deletions
|
|
@ -32,7 +32,10 @@ from .lib import (
|
|||
get_version_from_path,
|
||||
get_last_version_from_path,
|
||||
modified_environ,
|
||||
add_tool_to_environment
|
||||
add_tool_to_environment,
|
||||
decompose_url,
|
||||
compose_url,
|
||||
get_default_components
|
||||
)
|
||||
|
||||
# Special naming case for subprocess since its a built-in method.
|
||||
|
|
@ -44,6 +47,9 @@ __all__ = [
|
|||
"project_overrides_dir_path",
|
||||
"config",
|
||||
"execute",
|
||||
"decompose_url",
|
||||
"compose_url",
|
||||
"get_default_components",
|
||||
|
||||
# plugin classes
|
||||
"Extractor",
|
||||
|
|
|
|||
75
pype/lib.py
75
pype/lib.py
|
|
@ -17,6 +17,11 @@ import six
|
|||
import avalon.api
|
||||
from .api import config
|
||||
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
except ImportError:
|
||||
from urlparse import urlparse
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -1386,3 +1391,73 @@ def ffprobe_streams(path_to_file):
|
|||
popen_output = popen.communicate()[0]
|
||||
log.debug("FFprobe output: {}".format(popen_output))
|
||||
return json.loads(popen_output)["streams"]
|
||||
|
||||
|
||||
def decompose_url(url):
|
||||
components = {
|
||||
"scheme": None,
|
||||
"host": None,
|
||||
"port": None,
|
||||
"username": None,
|
||||
"password": None,
|
||||
"query": None
|
||||
}
|
||||
|
||||
result = urlparse(url)
|
||||
|
||||
components["scheme"] = result.scheme
|
||||
components["host"] = result.hostname
|
||||
try:
|
||||
components["port"] = result.port
|
||||
except ValueError:
|
||||
raise RuntimeError("invalid port specified")
|
||||
|
||||
components["username"] = result.username
|
||||
components["password"] = result.password
|
||||
components["query"] = result.query
|
||||
|
||||
return components
|
||||
|
||||
|
||||
def compose_url(scheme=None,
|
||||
host=None,
|
||||
username=None,
|
||||
password=None,
|
||||
database=None,
|
||||
collection=None,
|
||||
port=None,
|
||||
query=None):
|
||||
|
||||
url = "{scheme}://"
|
||||
|
||||
if username and password:
|
||||
url += "{username}:{password}@"
|
||||
|
||||
url += "{host}"
|
||||
|
||||
if database:
|
||||
url += "/{database}"
|
||||
|
||||
if database and collection:
|
||||
url += "/{collection}"
|
||||
|
||||
if port:
|
||||
url += ":{port}"
|
||||
|
||||
if query:
|
||||
url += "?{}".format(query)
|
||||
|
||||
return url.format(**{
|
||||
"scheme": scheme,
|
||||
"host": host,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"database": database,
|
||||
"collection": collection,
|
||||
"port": port,
|
||||
"query": query
|
||||
})
|
||||
|
||||
|
||||
def get_default_components():
|
||||
return decompose_url(os.environ["MONGO_URL"])
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import contextlib
|
|||
|
||||
from avalon import schema
|
||||
from avalon.vendor import requests
|
||||
from pype.api import get_default_components, compose_url
|
||||
|
||||
# Third-party dependencies
|
||||
import pymongo
|
||||
|
|
@ -72,8 +73,15 @@ class DbConnector(object):
|
|||
self.Session.update(self._from_environment())
|
||||
|
||||
timeout = int(self.Session["AVALON_TIMEOUT"])
|
||||
|
||||
components = get_default_components()
|
||||
port = components.pop("port")
|
||||
host = compose_url(**components)
|
||||
self._mongo_client = pymongo.MongoClient(
|
||||
self.Session["AVALON_MONGO"], serverSelectionTimeoutMS=timeout)
|
||||
host=host,
|
||||
port=port,
|
||||
serverSelectionTimeoutMS=timeout
|
||||
)
|
||||
|
||||
for retry in range(3):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@ from pype.modules.ftrack.lib.custom_db_connector import DbConnector
|
|||
|
||||
|
||||
class AvalonRestApi(RestApi):
|
||||
dbcon = DbConnector(
|
||||
os.environ["AVALON_MONGO"],
|
||||
os.environ["AVALON_DB"]
|
||||
)
|
||||
dbcon = DbConnector(os.environ["AVALON_DB"])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ import time
|
|||
import uuid
|
||||
|
||||
import ftrack_api
|
||||
import pymongo
|
||||
from pype.modules.ftrack.lib import credentials
|
||||
from pype.modules.ftrack.ftrack_server.lib import (
|
||||
ftrack_events_mongo_settings, check_ftrack_url
|
||||
)
|
||||
from pype.modules.ftrack.ftrack_server.lib import check_ftrack_url
|
||||
from pype.api import get_default_components, compose_url
|
||||
import socket_thread
|
||||
|
||||
|
||||
|
|
@ -30,22 +30,19 @@ class MongoPermissionsError(Exception):
|
|||
|
||||
def check_mongo_url(host, port, log_error=False):
|
||||
"""Checks if mongo server is responding"""
|
||||
sock = None
|
||||
try:
|
||||
sock = socket.create_connection(
|
||||
(host, port),
|
||||
timeout=1
|
||||
)
|
||||
return True
|
||||
except socket.error as err:
|
||||
client = pymongo.MongoClient(host=host, port=port)
|
||||
# Force connection on a request as the connect=True parameter of
|
||||
# MongoClient seems to be useless here
|
||||
client.server_info()
|
||||
except pymongo.errors.ServerSelectionTimeoutError as err:
|
||||
if log_error:
|
||||
print("Can't connect to MongoDB at {}:{} because: {}".format(
|
||||
host, port, err
|
||||
))
|
||||
return False
|
||||
finally:
|
||||
if sock is not None:
|
||||
sock.close()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def validate_credentials(url, user, api):
|
||||
|
|
@ -190,9 +187,9 @@ def main_loop(ftrack_url):
|
|||
|
||||
os.environ["FTRACK_EVENT_SUB_ID"] = str(uuid.uuid1())
|
||||
# Get mongo hostname and port for testing mongo connection
|
||||
mongo_list = ftrack_events_mongo_settings()
|
||||
mongo_hostname = mongo_list[0]
|
||||
mongo_port = mongo_list[1]
|
||||
components = get_default_components()
|
||||
mongo_port = components.pop("port")
|
||||
mongo_hostname = compose_url(**components)
|
||||
|
||||
# Current file
|
||||
file_path = os.path.dirname(os.path.realpath(__file__))
|
||||
|
|
@ -275,7 +272,7 @@ def main_loop(ftrack_url):
|
|||
# Run threads only if Ftrack is accessible
|
||||
if not ftrack_accessible or not mongo_accessible:
|
||||
if not mongo_accessible and not printed_mongo_error:
|
||||
mongo_url = mongo_hostname + ":" + mongo_port
|
||||
mongo_url = "{}:{}".format(mongo_hostname, mongo_port)
|
||||
print("Can't access Mongo {}".format(mongo_url))
|
||||
|
||||
if not ftrack_accessible and not printed_ftrack_error:
|
||||
|
|
|
|||
|
|
@ -18,12 +18,8 @@ import ftrack_api.operation
|
|||
import ftrack_api._centralized_storage_scenario
|
||||
import ftrack_api.event
|
||||
from ftrack_api.logging import LazyLogMessage as L
|
||||
try:
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
except ImportError:
|
||||
from urlparse import urlparse, parse_qs
|
||||
|
||||
from pype.api import Logger
|
||||
from pype.api import Logger, compose_url, get_default_components
|
||||
|
||||
from pype.modules.ftrack.lib.custom_db_connector import DbConnector
|
||||
|
||||
|
|
@ -32,67 +28,10 @@ TOPIC_STATUS_SERVER = "pype.event.server.status"
|
|||
TOPIC_STATUS_SERVER_RESULT = "pype.event.server.status.result"
|
||||
|
||||
|
||||
def ftrack_events_mongo_settings():
|
||||
host = None
|
||||
port = None
|
||||
username = None
|
||||
password = None
|
||||
collection = None
|
||||
database = None
|
||||
auth_db = ""
|
||||
|
||||
if os.environ.get('FTRACK_EVENTS_MONGO_URL'):
|
||||
result = urlparse(os.environ['FTRACK_EVENTS_MONGO_URL'])
|
||||
|
||||
host = result.hostname
|
||||
try:
|
||||
port = result.port
|
||||
except ValueError:
|
||||
raise RuntimeError("invalid port specified")
|
||||
username = result.username
|
||||
password = result.password
|
||||
try:
|
||||
database = result.path.lstrip("/").split("/")[0]
|
||||
collection = result.path.lstrip("/").split("/")[1]
|
||||
except IndexError:
|
||||
if not database:
|
||||
raise RuntimeError("missing database name for logging")
|
||||
try:
|
||||
auth_db = parse_qs(result.query)['authSource'][0]
|
||||
except KeyError:
|
||||
# no auth db provided, mongo will use the one we are connecting to
|
||||
pass
|
||||
else:
|
||||
host = os.environ.get('FTRACK_EVENTS_MONGO_HOST')
|
||||
port = int(os.environ.get('FTRACK_EVENTS_MONGO_PORT', "0"))
|
||||
database = os.environ.get('FTRACK_EVENTS_MONGO_DB')
|
||||
username = os.environ.get('FTRACK_EVENTS_MONGO_USER')
|
||||
password = os.environ.get('FTRACK_EVENTS_MONGO_PASSWORD')
|
||||
collection = os.environ.get('FTRACK_EVENTS_MONGO_COL')
|
||||
auth_db = os.environ.get('FTRACK_EVENTS_MONGO_AUTH_DB', 'avalon')
|
||||
|
||||
return host, port, database, username, password, collection, auth_db
|
||||
|
||||
|
||||
def get_ftrack_event_mongo_info():
|
||||
host, port, database, username, password, collection, auth_db = (
|
||||
ftrack_events_mongo_settings()
|
||||
)
|
||||
user_pass = ""
|
||||
if username and password:
|
||||
user_pass = "{}:{}@".format(username, password)
|
||||
|
||||
socket_path = "{}:{}".format(host, port)
|
||||
|
||||
dab = ""
|
||||
if database:
|
||||
dab = "/{}".format(database)
|
||||
|
||||
auth = ""
|
||||
if auth_db:
|
||||
auth = "?authSource={}".format(auth_db)
|
||||
|
||||
url = "mongodb://{}{}{}{}".format(user_pass, socket_path, dab, auth)
|
||||
url = compose_url(get_default_components())
|
||||
database = os.environ.get("FTRACK_EVENTS_MONGO_DB") or "pype"
|
||||
collection = os.environ.get("FTRACK_EVENTS_MONGO_COL") or "ftrack_events"
|
||||
|
||||
return url, database, collection
|
||||
|
||||
|
|
@ -205,7 +144,6 @@ class ProcessEventHub(SocketBaseEventHub):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.dbcon = DbConnector(
|
||||
mongo_url=self.url,
|
||||
database_name=self.database,
|
||||
table_name=self.table_name
|
||||
)
|
||||
|
|
@ -269,7 +207,7 @@ class ProcessEventHub(SocketBaseEventHub):
|
|||
def load_events(self):
|
||||
"""Load not processed events sorted by stored date"""
|
||||
ago_date = datetime.datetime.now() - datetime.timedelta(days=3)
|
||||
result = self.dbcon.delete_many({
|
||||
self.dbcon.delete_many({
|
||||
"pype_data.stored": {"$lte": ago_date},
|
||||
"pype_data.is_processed": True
|
||||
})
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ class SessionFactory:
|
|||
|
||||
url, database, table_name = get_ftrack_event_mongo_info()
|
||||
dbcon = DbConnector(
|
||||
mongo_url=url,
|
||||
database_name=database,
|
||||
table_name=table_name
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import atexit
|
|||
# Third-party dependencies
|
||||
import pymongo
|
||||
|
||||
from pype.api import get_default_components, compose_url
|
||||
|
||||
|
||||
class NotActiveTable(Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -63,13 +65,12 @@ class DbConnector:
|
|||
log = logging.getLogger(__name__)
|
||||
timeout = 1000
|
||||
|
||||
def __init__(self, mongo_url, database_name, table_name=None):
|
||||
def __init__(self, database_name, table_name=None):
|
||||
self._mongo_client = None
|
||||
self._sentry_client = None
|
||||
self._sentry_logging_handler = None
|
||||
self._database = None
|
||||
self._is_installed = False
|
||||
self._mongo_url = mongo_url
|
||||
self._database_name = database_name
|
||||
|
||||
self.active_table = table_name
|
||||
|
|
@ -95,8 +96,12 @@ class DbConnector:
|
|||
atexit.register(self.uninstall)
|
||||
logging.basicConfig()
|
||||
|
||||
components = get_default_components()
|
||||
port = components.pop("port")
|
||||
host = compose_url(**components)
|
||||
self._mongo_client = pymongo.MongoClient(
|
||||
self._mongo_url,
|
||||
host=host,
|
||||
port=port,
|
||||
serverSelectionTimeoutMS=self.timeout
|
||||
)
|
||||
|
||||
|
|
@ -113,11 +118,11 @@ class DbConnector:
|
|||
else:
|
||||
raise IOError(
|
||||
"ERROR: Couldn't connect to %s in "
|
||||
"less than %.3f ms" % (self._mongo_url, self.timeout)
|
||||
"less than %.3f ms" % (host, self.timeout)
|
||||
)
|
||||
|
||||
self.log.info("Connected to %s, delay %.3f s" % (
|
||||
self._mongo_url, time.time() - t1
|
||||
host, time.time() - t1
|
||||
))
|
||||
|
||||
self._database = self._mongo_client[self._database_name]
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@ class DbConnector(object):
|
|||
|
||||
timeout = int(self.Session["AVALON_TIMEOUT"])
|
||||
self._mongo_client = pymongo.MongoClient(
|
||||
self.Session["AVALON_MONGO"], serverSelectionTimeoutMS=timeout)
|
||||
host=os.environ["AVALON_MONGO_HOST"],
|
||||
port=int(os.environ["AVALON_MONGO_PORT"]),
|
||||
serverSelectionTimeoutMS=timeout
|
||||
)
|
||||
|
||||
for retry in range(3):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import os
|
||||
import collections
|
||||
from Qt import QtCore
|
||||
from pype.api import Logger
|
||||
from pypeapp.lib.log import _bootstrap_mongo_log
|
||||
from pypeapp.lib.log import _bootstrap_mongo_log, COLLECTION
|
||||
|
||||
log = Logger().get_logger("LogModel", "LoggingModule")
|
||||
|
||||
|
|
@ -41,11 +40,10 @@ class LogModel(QtCore.QAbstractItemModel):
|
|||
super(LogModel, self).__init__(parent)
|
||||
self._root_node = Node()
|
||||
|
||||
collection = os.environ.get('PYPE_LOG_MONGO_COL')
|
||||
database = _bootstrap_mongo_log()
|
||||
self.dbcon = None
|
||||
if collection in database.list_collection_names():
|
||||
self.dbcon = database[collection]
|
||||
if COLLECTION in database.list_collection_names():
|
||||
self.dbcon = database[COLLECTION]
|
||||
|
||||
def add_log(self, log):
|
||||
node = Node(log)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
from Qt import QtWidgets
|
||||
|
||||
from pype.api import Logger
|
||||
|
||||
from ..gui.app import LogsWindow
|
||||
|
||||
log = Logger().get_logger("LoggingModule", "logging")
|
||||
|
||||
|
||||
class LoggingModule:
|
||||
def __init__(self, main_parent=None, parent=None):
|
||||
self.parent = parent
|
||||
self.log = Logger().get_logger(self.__class__.__name__, "logging")
|
||||
|
||||
self.window = LogsWindow()
|
||||
try:
|
||||
self.window = LogsWindow()
|
||||
self.tray_menu = self._tray_menu
|
||||
except Exception:
|
||||
self.log.warning(
|
||||
"Couldn't set Logging GUI due to error.", exc_info=True
|
||||
)
|
||||
|
||||
# Definition of Tray menu
|
||||
def tray_menu(self, parent_menu):
|
||||
def _tray_menu(self, parent_menu):
|
||||
# Menu for Tray App
|
||||
menu = QtWidgets.QMenu('Logging', parent_menu)
|
||||
# menu.setProperty('submenu', 'on')
|
||||
|
|
|
|||
|
|
@ -56,13 +56,6 @@
|
|||
"pattern": "^\\w*$",
|
||||
"example": "maya2016"
|
||||
},
|
||||
"AVALON_MONGO": {
|
||||
"description": "Address to the asset database",
|
||||
"type": "string",
|
||||
"pattern": "^mongodb://[\\w/@:.]*$",
|
||||
"example": "mongodb://localhost:27017",
|
||||
"default": "mongodb://localhost:27017"
|
||||
},
|
||||
"AVALON_DB": {
|
||||
"description": "Name of database",
|
||||
"type": "string",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue