Skip to content

Commit

Permalink
Merge pull request #1242 from boverhof/foqus_cloud
Browse files Browse the repository at this point in the history
Foqus cloud
  • Loading branch information
boverhof authored Oct 14, 2024
2 parents d502425 + 06110ec commit 7ef873d
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 24 deletions.
38 changes: 38 additions & 0 deletions cloud/aws/logging.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Default AWS Config
version: 1
disable_existing_loggers: False
formatters:
simple_formatter:
format: "%(levelname)-8s - %(asctime)12s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: DEBUG
stream: ext://sys.stdout
formatter: simple_formatter
logfile:
class: logging.handlers.RotatingFileHandler
level: DEBUG
filename: watchtower.log
maxBytes: 1000000
backupCount: 3
formatter: simple_formatter
watchtower:
#class: watchtower.CloudWatchLogHandler
class: foqus_lib.service.flowsheet.FoqusCloudWatchLogHandler
level: DEBUG
log_group_name: foqus-cloud-service
#log_stream_name: "{machine_name}-{strftime:%y-%m-%d}"
log_stream_name: "{machine_name}"
send_interval: 10
create_log_group: True
formatter: simple_formatter
root:
level: DEBUG
propagate: True
handlers: [console, logfile, watchtower]
loggers:
botocore:
level: WARN
urllib3:
level: WARN
210 changes: 210 additions & 0 deletions foqus_lib/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#################################################################################
# FOQUS Copyright (c) 2012 - 2024, by the software owners: Oak Ridge Institute
# for Science and Education (ORISE), TRIAD National Security, LLC., Lawrence
# Livermore National Security, LLC., The Regents of the University of
# California, through Lawrence Berkeley National Laboratory, Battelle Memorial
# Institute, Pacific Northwest Division through Pacific Northwest National
# Laboratory, Carnegie Mellon University, West Virginia University, Boston
# University, the Trustees of Princeton University, The University of Texas at
# Austin, URS Energy & Construction, Inc., et al. All rights reserved.
#
# Please see the file LICENSE.md for full copyright and license information,
# respectively. This file is also available online at the URL
# "https://github.com/CCSI-Toolset/FOQUS".
#################################################################################
"""
Joshua Boverhof, Lawrence Berkeley National Labs, 2024
"""
import os, shutil, logging

# from foqus_lib.framework.session.session import generalSettings as FoqusSettings


class DependencyTracker:
@classmethod
def available(cls):
"""Returns set of available packages"""
raise NotImplementedError()

@classmethod
def unavailable(cls):
"""Returns set of unavailable packages"""
raise NotImplementedError()


class ModuleDependencyTracker:
"""tracks imported python modules"""

python_modules_available = {}
python_modules_unavailable = {}
python_module_name = None

@classmethod
def available(cls):
return tuple(cls.python_modules_available.values())

@classmethod
def unavailable(cls):
return tuple(cls.python_modules_unavailable.values())

@classmethod
def load(cls):
instance = cls.python_modules_available.get(cls.python_module_name)
if instance is not None:
return instance
instance = cls()
try:
exec("import %s" % (instance.python_module_name))
except ModuleNotFoundError:
cls.python_modules_unavailable[instance.python_module_name] = instance
raise
instance._module = eval(instance.python_module_name)
cls.python_modules_available[instance.python_module_name] = instance
return instance

@classmethod
def load_capture_error(cls):
instance = None
try:
instance = cls.load()
except ModuleNotFoundError:
pass
return instance

def __init__(self):
self._module = None

@property
def module(self):
return self._module


class ExecutableDependencyTracker(DependencyTracker):
"""tracks optional executables"""

executables_available = dict()
executables_unavailable = dict()
executable_name = None
default_path = None
required = False

@classmethod
def available(cls):
return cls.executables_available.values()

@classmethod
def unavailable(cls):
return cls.executables_unavailable.values()

@classmethod
def path(cls):
raise NotImplementedError()

@classmethod
def load(cls):
assert cls.executable_name is not None
instance = cls.executables_available.get(cls.executable_name)
if instance is not None:
return instance
instance = cls()
if not os.path.isfile(instance.path()):
raise RuntimeError("%r: Failed to Load Dependency" % (instance))
if not os.access(instance.path(), os.X_OK):
raise RuntimeError(
"%r: Dependency Path is not Executable: %s" % (instance.path())
)
cls.executables_available[instance.executable_name] = instance


class PsuadeDependencyTracker(ExecutableDependencyTracker):
"""
plugin = PsuadeDependencyTracker.load()
if plugin == None: print("unavailable")
elif plugin.nomad is False: print("nomand unavailable")
"""

required = False
executable_name = "psuade"
default_path = "C:/Program Files (x86)/psuade_project 1.7.5/bin/psuade.exe"

def path(self):
return shutil.which("psuade") or self.default_path


class RScriptDependencyTracker(ExecutableDependencyTracker):
required = False
executable_name = "Rscript.exe"
default_path = "C:\\Program Files\\R\\R-3.1.2\\bin\\x64\\Rscript.exe"

@classmethod
def path(cls):
return shutil.which(cls.executable_name) or cls.default_path


class WindowsPackageDependencyTracker(DependencyTracker):
"""tracks installed Windows Packages"""

windows_packages_available = {}
windows_packages_unavailable = {}
package_name = None
install_path = None
required = False

@classmethod
def available(cls):
return cls.windows_packages_available.values()

@classmethod
def unavailable(cls):
return cls.windows_packages_unavailable.values()

@classmethod
def load(cls):
instance = cls.windows_packages_available.get(cls.package_name)
instance = instance or cls()
if not os.path.isdir(instance.path):
if cls.required:
raise RuntimeError("Install Path Does Not Exist: %s" % (instance.path))
if instance.package_name not in cls.windows_packages_unavailable:
cls.windows_packages_unavailable[instance.package_name] = (
cls.windows_packages_unavailable
)
logging.getLogger().warning(
"Install Path Does Not Exist: %s" % (instance.path)
)
cls.windows_packages_available[instance.package_name] = instance
return instance

@classmethod
def path(cls):
raise NotImplementedError()


class SimSinterDependencyTracker(WindowsPackageDependencyTracker):
"""
plugin = PsuadeDependencyTracker.load()
if plugin == None: print("unavailable")
elif plugin.nomad is False: print("nomand unavailable")
"""

package_name = "SimSinter"
install_path = "C:/Program Files/CCSI/SimSinter"

@property
def path(self):
return self.install_path


class TurbineLiteDependencyTracker(WindowsPackageDependencyTracker):
"""
plugin = PsuadeDependencyTracker.load()
if plugin == None: print("unavailable")
elif plugin.nomad is False: print("nomand unavailable")
"""

package_name = "TurbineLite"
install_path = "C:/Program Files/Turbine/Lite"

@property
def path(self):
return self.install_path
7 changes: 3 additions & 4 deletions foqus_lib/foqus.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import sys
import time
import uuid
import traceback
import turbine

# FOQUS imports
import foqus_lib.version.version as ver # foqus version and other info
Expand Down Expand Up @@ -254,10 +256,7 @@ def main(args_to_parse=None):
logging.getLogger("foqus").setLevel(logging.DEBUG)
logging.getLogger("turbine").setLevel(logging.DEBUG)
sys.excepthook = logException # for unhandled exception logging
try:
turbine.commands._setup_logging.done = True
except:
_logger.exception("Cannot find turbine module")
turbine.commands._setup_logging.done = True
app = None # Qt application if I need to display message boxes.
## Setup the command line arguments
parser = argparse.ArgumentParser()
Expand Down
9 changes: 5 additions & 4 deletions foqus_lib/framework/session/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
import sys
import uuid

from foqus_lib import core
import foqus_lib.framework.optimizer.problem as oprob
from foqus_lib.framework.graph.graph import *
from foqus_lib.framework.graph.graph import Graph, GraphEx
from foqus_lib.framework.graph.node import nodeModelTypes
from foqus_lib.framework.ml_ai_models import mlaiSearch
from foqus_lib.framework.optimizer import problem
Expand All @@ -40,7 +41,7 @@
from foqus_lib.framework.plugins import pluginSearch
from foqus_lib.framework.pymodel import pymodel
from foqus_lib.framework.sampleResults.results import Results
from foqus_lib.framework.sim.turbineConfiguration import *
from foqus_lib.framework.sim.turbineConfiguration import TurbineConfiguration
from foqus_lib.framework.surrogate import surrogate
from foqus_lib.framework.surrogate.surrogate import surrogate as junk2
from foqus_lib.framework.uq.LocalExecutionModule import *
Expand Down Expand Up @@ -770,7 +771,7 @@ def __init__(self):
self.working_dir_override = False
self.working_dir = ""
self.new_working_dir = ""
self.simsinter_path = "C:/Program Files (x86)/CCSI/SimSinter"
self.simsinter_path = core.SimSinterDependencyTracker.load().path
self.psuade_path = (
shutil.which("psuade")
or "C:/Program Files (x86)/psuade_project 1.7.5/bin/psuade.exe"
Expand All @@ -791,7 +792,7 @@ def __init__(self):
self.turbineRemoteReSub = 0 # number of times to resubmit failed
# jobs to Turbine when running remote
self.aspenVersion = 2 # 0 = none, 1 = 7.3, 2 = 7.3.2 or higher
self.turbLiteHome = "C:\\Program Files (x86)\\Turbine\\Lite"
self.turbLiteHome = core.TurbineLiteDependencyTracker.load().path
self.rScriptPath = "C:\\Program Files\\R\\R-3.1.2\\bin\\x64\\Rscript.exe"
self.logFormat = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
self.logRotate = False
Expand Down
4 changes: 3 additions & 1 deletion foqus_lib/framework/sim/turbineConfiguration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
read_configuration,
)

from foqus_lib import core
import foqus_lib.framework.sim.process_management as _pm
from foqus_lib.framework.foqusException.foqusException import *

Expand Down Expand Up @@ -238,7 +239,7 @@ def __init__(self, path="turbine.cfg"):
self.user = ""
self.pwd = ""
self.turbVer = "Lite" # Lite, Remote or ....
self.turbineLiteHome = "C:\\Program Files (x86)\\Turbine\\Lite"
self.turbineLiteHome = core.TurbineLiteDependencyTracker.load().path
self.consumers = {}
self.consumerCountDict = {}
self.reloadTurbine()
Expand Down Expand Up @@ -368,6 +369,7 @@ def startConsumer(self, nodeName, simName):

sinter_process_log = open("%s_sinter_log.txt" % app, "a")
sinter_process_log.write("starting consumer\n")
_log.info("executing process: %s", f)
proc = subprocess.Popen(
[f],
stdout=sinter_process_log,
Expand Down
8 changes: 5 additions & 3 deletions foqus_lib/framework/sim/turbineLiteDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
John Eslick, Carnegie Mellon University, 2014
"""
import os
import os.path
import threading
import time
import uuid

import adodbapi
import adodbapi.apibase
from foqus_lib import core

adodbapi.adodbapi.defaultCursorLocation = 2 # adodbapi.adUseServer

Expand Down Expand Up @@ -57,9 +59,9 @@ class turbineLiteDB:
def __init__(self, close_after=True):
self.conn = None
self.close_after = close_after
self.dbFile = (
"C:\\Program Files (x86)"
"\\Turbine\\Lite\\Data\\TurbineCompactDatabase.sdf"
self.dbFile = os.path.join(
core.TurbineLiteDependencyTracker.load().path,
"/Data/TurbineCompactDatabase.sdf",
)

def __del__(self):
Expand Down
Loading

0 comments on commit 7ef873d

Please sign in to comment.