opencue-rqd 1.11.66__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opencue_rqd-1.11.66/.gitignore +3 -0
- opencue_rqd-1.11.66/Dockerfile +43 -0
- opencue_rqd-1.11.66/PKG-INFO +13 -0
- opencue_rqd-1.11.66/README.md +59 -0
- opencue_rqd-1.11.66/deploy/opencue-rqd.service +19 -0
- opencue_rqd-1.11.66/deploy/rqd3_init.d +53 -0
- opencue_rqd-1.11.66/pyproject.toml +43 -0
- opencue_rqd-1.11.66/pytests/__init__.py +0 -0
- opencue_rqd-1.11.66/pytests/test_rqdlogging.py +47 -0
- opencue_rqd-1.11.66/rqd/__init__.py +13 -0
- opencue_rqd-1.11.66/rqd/__main__.py +245 -0
- opencue_rqd-1.11.66/rqd/cuerqd.py +309 -0
- opencue_rqd-1.11.66/rqd/rqconstants.py +301 -0
- opencue_rqd-1.11.66/rqd/rqcore.py +1669 -0
- opencue_rqd-1.11.66/rqd/rqdocker.py +281 -0
- opencue_rqd-1.11.66/rqd/rqdservicers.py +149 -0
- opencue_rqd-1.11.66/rqd/rqexceptions.py +37 -0
- opencue_rqd-1.11.66/rqd/rqlogging.py +191 -0
- opencue_rqd-1.11.66/rqd/rqmachine.py +1048 -0
- opencue_rqd-1.11.66/rqd/rqnetwork.py +422 -0
- opencue_rqd-1.11.66/rqd/rqnimby.py +155 -0
- opencue_rqd-1.11.66/rqd/rqswap.py +194 -0
- opencue_rqd-1.11.66/rqd/rqutil.py +221 -0
- opencue_rqd-1.11.66/rqd.example.conf +50 -0
- opencue_rqd-1.11.66/tests/__init__.py +13 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_drack_4-2-2 +96 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_dub_8-4-2 +184 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_genosis_1-1-1 +19 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_hp8600_8-4-2 +184 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_rider_4-2-2 +92 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_shark_8-4-2 +200 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_shark_ht_8-4-2-2 +400 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_srdsvr05_ht_12-6-2-2 +600 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_srdsvr09_48-12-4 +1248 -0
- opencue_rqd-1.11.66/tests/cpuinfo/_cpuinfo_vrack_2-1-2 +40 -0
- opencue_rqd-1.11.66/tests/cuebot_listener_test.py +213 -0
- opencue_rqd-1.11.66/tests/cuerqd_test.py +204 -0
- opencue_rqd-1.11.66/tests/rqconstants_test.py +129 -0
- opencue_rqd-1.11.66/tests/rqcore_test.py +1042 -0
- opencue_rqd-1.11.66/tests/rqmachine_test.py +561 -0
- opencue_rqd-1.11.66/tests/rqnimby_test.py +192 -0
- opencue_rqd-1.11.66/winps/setup.py +14 -0
- opencue_rqd-1.11.66/winps/winps.cpp +228 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
FROM rockylinux:8.9
|
|
2
|
+
|
|
3
|
+
WORKDIR /opt/opencue
|
|
4
|
+
|
|
5
|
+
# Paths to the pre-built python packages.
|
|
6
|
+
# They are all defined her but no necessary used to make it simpler between the images
|
|
7
|
+
ARG OPENCUE_PROTO_PACKAGE_PATH=/tmp/invalidpath
|
|
8
|
+
ARG OPENCUE_RQD_PACKAGE_PATH=/tmp/invalidpath
|
|
9
|
+
ARG OPENCUE_PYCUE_PACKAGE_PATH=/tmp/invalidpath
|
|
10
|
+
ARG OPENCUE_PYOUTLINE_PACKAGE_PATH=/tmp/invalidpath
|
|
11
|
+
ARG OPENCUE_CUESUBMIT_PACKAGE_PATH=/tmp/invalidpath
|
|
12
|
+
ARG OPENCUE_CUEGUI_PACKAGE_PATH=/tmp/invalidpath
|
|
13
|
+
ARG OPENCUE_CUEADMIN_PACKAGE_PATH=/tmp/invalidpath
|
|
14
|
+
|
|
15
|
+
RUN yum -y install \
|
|
16
|
+
epel-release \
|
|
17
|
+
gcc \
|
|
18
|
+
time
|
|
19
|
+
|
|
20
|
+
RUN dnf install -y \
|
|
21
|
+
python39 \
|
|
22
|
+
python39-devel \
|
|
23
|
+
python39-pip
|
|
24
|
+
|
|
25
|
+
RUN python3.9 -m pip install --upgrade pip
|
|
26
|
+
|
|
27
|
+
COPY LICENSE ./
|
|
28
|
+
|
|
29
|
+
RUN mkdir /tmp/packages
|
|
30
|
+
COPY ${OPENCUE_PROTO_PACKAGE_PATH} /tmp/packages/
|
|
31
|
+
COPY ${OPENCUE_RQD_PACKAGE_PATH} /tmp/packages/
|
|
32
|
+
|
|
33
|
+
RUN python3.9 -m pip install /tmp/packages/*.whl
|
|
34
|
+
|
|
35
|
+
RUN mkdir -p /etc/opencue
|
|
36
|
+
RUN echo "[Override]" > /etc/opencue/rqd.conf
|
|
37
|
+
RUN echo "USE_NIMBY_PYNPUT=false" >> /etc/opencue/rqd.conf
|
|
38
|
+
|
|
39
|
+
# RQD gRPC server
|
|
40
|
+
EXPOSE 8444
|
|
41
|
+
|
|
42
|
+
# NOTE: This shell out is needed to avoid RQD getting PID 0 which leads to leaking child processes.
|
|
43
|
+
ENTRYPOINT ["/bin/bash", "-c", "set -e && rqd"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: opencue_rqd
|
|
3
|
+
Version: 1.11.66
|
|
4
|
+
Requires-Dist: future==1.0.0
|
|
5
|
+
Requires-Dist: opencue-proto
|
|
6
|
+
Requires-Dist: psutil==5.9.8
|
|
7
|
+
Requires-Dist: pynput==1.7.6
|
|
8
|
+
Provides-Extra: test
|
|
9
|
+
Requires-Dist: docker==7.1.0; extra == 'test'
|
|
10
|
+
Requires-Dist: loki-urllib3-client; extra == 'test'
|
|
11
|
+
Requires-Dist: mock==2.0.0; extra == 'test'
|
|
12
|
+
Requires-Dist: pyfakefs==5.2.3; extra == 'test'
|
|
13
|
+
Requires-Dist: pytest; extra == 'test'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# RQD
|
|
2
|
+
|
|
3
|
+
RQD is a software client that runs on all hosts doing work for an OpenCue
|
|
4
|
+
deployment.
|
|
5
|
+
|
|
6
|
+
RQD's responsibilities include:
|
|
7
|
+
|
|
8
|
+
- Registering the host with Cuebot.
|
|
9
|
+
- Receiving instructions about what work to do.
|
|
10
|
+
- Monitoring the worker processes it launches and reporting on results.
|
|
11
|
+
|
|
12
|
+
RQD uses [gRPC](https://grpc.io/) to communicate with Cuebot. It also runs its
|
|
13
|
+
own gRPC server, which is called by the Cuebot client to send instructions to
|
|
14
|
+
RQD.
|
|
15
|
+
|
|
16
|
+
## How to start rqd from source
|
|
17
|
+
|
|
18
|
+
### Setup python environment
|
|
19
|
+
```bash
|
|
20
|
+
# Create virtual environment
|
|
21
|
+
python3 -m venv OpenCue-venv
|
|
22
|
+
# Activate virtual environment
|
|
23
|
+
source OpenCue-venv/bin/activate
|
|
24
|
+
# Change directory to Opencue source
|
|
25
|
+
cd <OpenCueSourceDir>
|
|
26
|
+
|
|
27
|
+
# Install compiled proto files which is needed by RQD into the virtual environment
|
|
28
|
+
pip install ./proto
|
|
29
|
+
|
|
30
|
+
# Install RQD into the virtual environment
|
|
31
|
+
pip install ./rqd
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Create rqd.conf
|
|
35
|
+
Example `rqd.conf` file :
|
|
36
|
+
|
|
37
|
+
```ini
|
|
38
|
+
[Override]
|
|
39
|
+
# Variable that decided if RQD should switch to the user of the job running. Requires root
|
|
40
|
+
RQD_BECOME_JOB_USER = False
|
|
41
|
+
|
|
42
|
+
# Log levels for RQD
|
|
43
|
+
CONSOLE_LOG_LEVEL = INFO
|
|
44
|
+
FILE_LOG_LEVEL = ERROR
|
|
45
|
+
|
|
46
|
+
# Number of seconds to wait before checking if the user has become idle.
|
|
47
|
+
CHECK_INTERVAL_LOCKED = 60
|
|
48
|
+
# Seconds of idle time required before NIMBY (Not In My BackYard) unlocks.
|
|
49
|
+
MINIMUM_IDLE = 900
|
|
50
|
+
|
|
51
|
+
# Whether or not to prefix each line in the log with a timestamp
|
|
52
|
+
RQD_PREPEND_TIMESTAMP = 0
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Run rqd
|
|
56
|
+
(using the above virtual environment)
|
|
57
|
+
```bash
|
|
58
|
+
rqd -c <path to rqd.conf>
|
|
59
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=OpenCue RQD Service
|
|
3
|
+
Wants=network.target
|
|
4
|
+
After=network.target
|
|
5
|
+
|
|
6
|
+
[Service]
|
|
7
|
+
Environment=OPTIONS=
|
|
8
|
+
Environment=BIN=/usr/bin
|
|
9
|
+
EnvironmentFile=-/etc/sysconfig/opencue-rqd
|
|
10
|
+
ExecStart=/bin/bash -c "${BIN}/rqd ${OPTIONS}"
|
|
11
|
+
ExecStop=/bin/bash -c "${BIN}/rqd --exit_now
|
|
12
|
+
LimitNOFILE=500000
|
|
13
|
+
LimitNPROC=500000
|
|
14
|
+
StandardOutput=syslog+console
|
|
15
|
+
StandardError=syslog+console
|
|
16
|
+
SyslogIdentifier=rqd
|
|
17
|
+
|
|
18
|
+
[Install]
|
|
19
|
+
WantedBy=multi-user.target
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
#
|
|
3
|
+
# RQD3: Start/stop rqd3 services
|
|
4
|
+
#
|
|
5
|
+
# chkconfig: 345 98 02
|
|
6
|
+
# description: Opencue RQD agent
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
# Source function library.
|
|
10
|
+
. /etc/rc.d/init.d/functions
|
|
11
|
+
|
|
12
|
+
IS_ON=/sbin/chkconfig
|
|
13
|
+
|
|
14
|
+
RQD_PATH=/usr/local/spi/rqd3/
|
|
15
|
+
|
|
16
|
+
RQD=${RQD_PATH}rqd.py
|
|
17
|
+
|
|
18
|
+
start()
|
|
19
|
+
{
|
|
20
|
+
[ -f /usr/local/etc/sweatbox.csh ] && echo "Refusing to start RQD3 on a sweatbox" && exit 0
|
|
21
|
+
echo -n $"Starting openrqd services:"
|
|
22
|
+
cd ${RQD_PATH}
|
|
23
|
+
daemon "${RQD}" -d
|
|
24
|
+
echo ""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
stop()
|
|
28
|
+
{
|
|
29
|
+
echo -n "Stopping openrqd services:"
|
|
30
|
+
cd ${RQD_PATH}
|
|
31
|
+
daemon "rqd/cuerqd.py" --exit_now
|
|
32
|
+
echo "Stop Request completed"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
case "$1" in
|
|
36
|
+
start)
|
|
37
|
+
start
|
|
38
|
+
;;
|
|
39
|
+
stop)
|
|
40
|
+
stop
|
|
41
|
+
;;
|
|
42
|
+
restart)
|
|
43
|
+
stop
|
|
44
|
+
sleep 3
|
|
45
|
+
start
|
|
46
|
+
;;
|
|
47
|
+
*)
|
|
48
|
+
echo $"Usage: $0 {start|stop|restart|idle_restart}"
|
|
49
|
+
exit 1
|
|
50
|
+
;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
exit 0
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"hatchling"
|
|
4
|
+
]
|
|
5
|
+
build-backend = "hatchling.build"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "opencue_rqd"
|
|
9
|
+
dynamic = ["version"]
|
|
10
|
+
dependencies = [
|
|
11
|
+
"opencue_proto",
|
|
12
|
+
"psutil==5.9.8",
|
|
13
|
+
"pynput==1.7.6",
|
|
14
|
+
"future==1.0.0"
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.hatch.version]
|
|
18
|
+
source = "code"
|
|
19
|
+
path = "../ci/generate_version_number.py"
|
|
20
|
+
default-version = "0.0.0"
|
|
21
|
+
|
|
22
|
+
[tool.hatch.build.targets.wheel]
|
|
23
|
+
packages = ["rqd"]
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
rqd = "rqd.__main__:main"
|
|
27
|
+
|
|
28
|
+
# --- Pytest configuration ---
|
|
29
|
+
[tool.pytest.ini_options]
|
|
30
|
+
minversion = "6.0" # Set to required pytest version
|
|
31
|
+
testpaths = ["tests", "pytests"] # Relative path(s) where tests are located
|
|
32
|
+
python_files = ["test_*.py", "*_test.py"] # Default test file pattern
|
|
33
|
+
python_functions = ["test_*"] # Default test function pattern
|
|
34
|
+
|
|
35
|
+
# --- Optional Test Dependencies ---
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
test = [
|
|
38
|
+
"mock==2.0.0",
|
|
39
|
+
"pyfakefs==5.2.3",
|
|
40
|
+
"pytest",
|
|
41
|
+
"docker==7.1.0",
|
|
42
|
+
"loki-urllib3-client"
|
|
43
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
# Copyright Contributors to the OpenCue Project
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
"""Pytests for rqd.rqdlogging"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import mock
|
|
22
|
+
import pytest
|
|
23
|
+
import opencue_proto.rqd_pb2
|
|
24
|
+
from rqd.rqlogging import LokiLogger
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
@mock.patch('opencue_proto.rqd_pb2_grpc.RunningFrameStub')
|
|
28
|
+
@mock.patch('opencue_proto.rqd_pb2_grpc.RqdInterfaceStub')
|
|
29
|
+
@mock.patch('grpc.insecure_channel', new=mock.MagicMock())
|
|
30
|
+
def runFrame(stubMock, frameStubMock):
|
|
31
|
+
rf = opencue_proto.rqd_pb2.RunFrame()
|
|
32
|
+
rf.job_id = "SD6F3S72DJ26236KFS"
|
|
33
|
+
rf.job_name = "edu-trn_job-name"
|
|
34
|
+
rf.frame_id = "FD1S3I154O646UGSNN"
|
|
35
|
+
return rf
|
|
36
|
+
|
|
37
|
+
# pylint: disable=redefined-outer-name
|
|
38
|
+
def test_LokiLogger(runFrame):
|
|
39
|
+
ll = LokiLogger("http://localhost:3100", runFrame)
|
|
40
|
+
assert isinstance(ll, LokiLogger)
|
|
41
|
+
|
|
42
|
+
def test_LokiLogger_invalid_runFrame():
|
|
43
|
+
rf = None
|
|
44
|
+
|
|
45
|
+
with pytest.raises(AttributeError) as excinfo:
|
|
46
|
+
LokiLogger("http://localhost:3100", rf)
|
|
47
|
+
assert excinfo.type == AttributeError
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright Contributors to the OpenCue Project
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Copyright Contributors to the OpenCue Project
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Initializes and starts RQD.
|
|
18
|
+
|
|
19
|
+
- RQD allows the cuebot to launch frames on a remote host.
|
|
20
|
+
- RQD monitors the resources on a machine.
|
|
21
|
+
- Frames can be monitored or killed.
|
|
22
|
+
- Status updates are sent to the cuebot every 60 seconds.
|
|
23
|
+
- Nimby built into RQD allows a desktop to be used as a render machine when
|
|
24
|
+
not in use.
|
|
25
|
+
- See the rqnetwork module for a description of ICE interfaces.
|
|
26
|
+
|
|
27
|
+
Optional configuration file:
|
|
28
|
+
----------------------------
|
|
29
|
+
In /etc/opencue/rqd.conf (on Linux) or %LOCALAPPDATA%/OpenCue/rqd.conf (on Windows):
|
|
30
|
+
[Override]
|
|
31
|
+
OVERRIDE_CORES = 2
|
|
32
|
+
OVERRIDE_PROCS = 3
|
|
33
|
+
OVERRIDE_MEMORY = 1000000
|
|
34
|
+
OVERRIDE_CUEBOT = cuebot1 cuebot2 cuebot3
|
|
35
|
+
# True will start nimby, False will keep nimby from starting
|
|
36
|
+
OVERRIDE_NIMBY = False
|
|
37
|
+
# True will check and report gpu memory if cuda capable
|
|
38
|
+
GPU = True
|
|
39
|
+
# True will force 256mb gpu memory
|
|
40
|
+
PLAYBLAST = True
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
from __future__ import print_function
|
|
45
|
+
from __future__ import absolute_import
|
|
46
|
+
from __future__ import division
|
|
47
|
+
|
|
48
|
+
import getopt
|
|
49
|
+
import logging
|
|
50
|
+
import logging.handlers
|
|
51
|
+
import os
|
|
52
|
+
import platform
|
|
53
|
+
import sys
|
|
54
|
+
|
|
55
|
+
import rqd.rqconstants
|
|
56
|
+
import rqd.rqcore
|
|
57
|
+
import rqd.rqutil
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def reopen_stdout_stderr(log_path):
|
|
61
|
+
"""
|
|
62
|
+
Flush sys.stdout and sys.stderr and then reopen the underlying
|
|
63
|
+
file descriptor for both stdout and stderr to the file at
|
|
64
|
+
LOG_PATH. LOG_PATH is opened before stdout and stderr are closed,
|
|
65
|
+
so if LOG_PATH fails to open, stdout and stderr will remain
|
|
66
|
+
unchanged.
|
|
67
|
+
"""
|
|
68
|
+
log_fd = os.open(log_path, os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0o644)
|
|
69
|
+
|
|
70
|
+
for f in [sys.stdout, sys.stderr]:
|
|
71
|
+
fileno = f.fileno()
|
|
72
|
+
f.flush()
|
|
73
|
+
os.close(fileno)
|
|
74
|
+
os.dup2(log_fd, fileno)
|
|
75
|
+
|
|
76
|
+
os.close(log_fd)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def daemonize(log_path=None, chdir_to_root=True):
|
|
80
|
+
"""
|
|
81
|
+
Daemonizes the current process. The process will be in a new session
|
|
82
|
+
with stdin reading from /dev/null and stdout and stderr writing to
|
|
83
|
+
/dev/null with all other file descriptors closed.
|
|
84
|
+
|
|
85
|
+
:type log_path: String
|
|
86
|
+
:param log_path: If LOG_PATH is provided, then stdout and stderr
|
|
87
|
+
write to LOG_PATH. LOG_PATH may be a relative
|
|
88
|
+
path to the process' current working directory
|
|
89
|
+
before calling daemonize().
|
|
90
|
+
:type chdir_to_root: bool
|
|
91
|
+
:param chdir_to_root: If CHDIR_TO_ROOT is True, then the process'
|
|
92
|
+
current working directory will be changed
|
|
93
|
+
to / after opening the log files; if
|
|
94
|
+
CHDIR_TO_ROOT is false, then the current
|
|
95
|
+
working directory is not changed.
|
|
96
|
+
"""
|
|
97
|
+
# pylint: disable=import-outside-toplevel
|
|
98
|
+
import resource
|
|
99
|
+
|
|
100
|
+
if hasattr(os, "devnull"):
|
|
101
|
+
dev_null = os.devnull
|
|
102
|
+
else:
|
|
103
|
+
dev_null = "/dev/null"
|
|
104
|
+
|
|
105
|
+
if not log_path:
|
|
106
|
+
log_path = dev_null
|
|
107
|
+
|
|
108
|
+
# pylint: disable=protected-access
|
|
109
|
+
if os.fork() != 0:
|
|
110
|
+
# Intentionally not using sys.exit here to avoid raising SystemExit,
|
|
111
|
+
# cleaning handlers and flushing stdio buffers
|
|
112
|
+
os._exit(0)
|
|
113
|
+
|
|
114
|
+
os.setsid()
|
|
115
|
+
|
|
116
|
+
if os.fork() != 0:
|
|
117
|
+
# Intentionally not using sys.exit here to avoid raising SystemExit,
|
|
118
|
+
# cleaning handlers and flushing stdio buffers
|
|
119
|
+
os._exit(0)
|
|
120
|
+
# pylint: enable=protected-access
|
|
121
|
+
|
|
122
|
+
os.close(sys.stdin.fileno())
|
|
123
|
+
os.open(dev_null, os.O_RDONLY)
|
|
124
|
+
|
|
125
|
+
# The log file is opened before chdir'ing so a relative path may
|
|
126
|
+
# be used and is opened before stdout and stderr are closed so any
|
|
127
|
+
# errors in opening it will appear on stderr.
|
|
128
|
+
reopen_stdout_stderr(log_path)
|
|
129
|
+
|
|
130
|
+
if chdir_to_root:
|
|
131
|
+
os.chdir('/')
|
|
132
|
+
|
|
133
|
+
max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
|
134
|
+
if max_fd == resource.RLIM_INFINITY:
|
|
135
|
+
max_fd = 1024
|
|
136
|
+
for fd in range(3, max_fd+1):
|
|
137
|
+
try:
|
|
138
|
+
# Ice.loadSlice() function sometimes open /dev/urandom to
|
|
139
|
+
# get random numbers. If daemonize() function is called after
|
|
140
|
+
# Ice.loadSlice(), we should not close /dev/urandom. Or else
|
|
141
|
+
# the child process will get exceptions when trying to access
|
|
142
|
+
# /dev/urandom.
|
|
143
|
+
fn = os.readlink("/proc/%s/%s" % (os.getpid(), fd))
|
|
144
|
+
if fn != "/dev/urandom":
|
|
145
|
+
os.close(fd)
|
|
146
|
+
except OSError:
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
def setupLogging():
|
|
150
|
+
"""Sets up the logging for RQD.
|
|
151
|
+
Logs to /var/log/messages"""
|
|
152
|
+
logger = logging.getLogger()
|
|
153
|
+
logger.setLevel(rqd.rqconstants.CONSOLE_LOG_LEVEL)
|
|
154
|
+
for handler in logger.handlers:
|
|
155
|
+
handler.setFormatter(logging.Formatter(rqd.rqconstants.LOG_FORMAT))
|
|
156
|
+
|
|
157
|
+
if rqd.rqconstants.FILE_LOG_LEVEL is not None:
|
|
158
|
+
if platform.system() in ('Linux', 'Darwin'):
|
|
159
|
+
if platform.system() == 'Linux':
|
|
160
|
+
syslogAddress = '/dev/log'
|
|
161
|
+
else:
|
|
162
|
+
syslogAddress = '/var/run/syslog'
|
|
163
|
+
if os.path.exists(syslogAddress):
|
|
164
|
+
logfile = logging.handlers.SysLogHandler(address=syslogAddress)
|
|
165
|
+
else:
|
|
166
|
+
logfile = logging.handlers.SysLogHandler()
|
|
167
|
+
elif platform.system() == 'Windows':
|
|
168
|
+
logfile = logging.FileHandler(os.path.expandvars('%TEMP%/openrqd.log'))
|
|
169
|
+
else:
|
|
170
|
+
logfile = logging.handlers.SysLogHandler()
|
|
171
|
+
logfile.setLevel(rqd.rqconstants.FILE_LOG_LEVEL)
|
|
172
|
+
logfile.setFormatter(logging.Formatter(rqd.rqconstants.LOG_FORMAT))
|
|
173
|
+
logger.addHandler(logfile)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def setup_sentry():
|
|
177
|
+
"""Set up sentry if a SENTRY_DSN_PATH is configured"""
|
|
178
|
+
sentry_dsn_path = rqd.rqconstants.SENTRY_DSN_PATH
|
|
179
|
+
if sentry_dsn_path is None:
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
# Not importing sentry at the toplevel to avoid an unecessary dependency
|
|
183
|
+
try:
|
|
184
|
+
# pylint: disable=import-outside-toplevel
|
|
185
|
+
import sentry_sdk
|
|
186
|
+
# pylint: enable=import-outside-toplevel
|
|
187
|
+
sentry_sdk.init(sentry_dsn_path)
|
|
188
|
+
except ImportError:
|
|
189
|
+
logging.warning('Sentry support disabled. SENTRY_DSN_PATH is set but '
|
|
190
|
+
'the lib is not available')
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def usage():
|
|
194
|
+
"""Prints command line syntax"""
|
|
195
|
+
usage_msg = f"""SYNOPSIS
|
|
196
|
+
{sys.argv[0]} [options]
|
|
197
|
+
|
|
198
|
+
-d | --daemon => Run as daemon
|
|
199
|
+
--nimbyoff => Disables nimby activation
|
|
200
|
+
-c => Provide an alternate config file
|
|
201
|
+
On Linux: defaults to /etc/opencue/rqd.conf
|
|
202
|
+
On Windows: Defaults to %LOCALAPPDATA%/OpenCue/rqd.conf
|
|
203
|
+
Config file is optional
|
|
204
|
+
"""
|
|
205
|
+
print(usage_msg, file=sys.stderr)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def main():
|
|
209
|
+
"""Entrypoint for RQD."""
|
|
210
|
+
setupLogging()
|
|
211
|
+
logger = logging.getLogger()
|
|
212
|
+
|
|
213
|
+
if platform.system() == 'Linux' and os.getuid() != 0 and \
|
|
214
|
+
rqd.rqconstants.RQD_BECOME_JOB_USER:
|
|
215
|
+
logging.critical("Please run launch as root")
|
|
216
|
+
sys.exit(1)
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
opts, _ = getopt.getopt(sys.argv[1:], 'hdc:', ['help', 'daemon', 'nimbyoff', 'update'])
|
|
220
|
+
except getopt.GetoptError:
|
|
221
|
+
usage()
|
|
222
|
+
sys.exit(1)
|
|
223
|
+
|
|
224
|
+
optNimbyOff = False
|
|
225
|
+
for option, _ in opts:
|
|
226
|
+
if option in ["-h", "--help"]:
|
|
227
|
+
usage()
|
|
228
|
+
sys.exit(0)
|
|
229
|
+
if option in ["-d", "--daemon"] and platform.system() != "Windows":
|
|
230
|
+
daemonize()
|
|
231
|
+
if option in ["--nimbyoff"]:
|
|
232
|
+
optNimbyOff = True
|
|
233
|
+
|
|
234
|
+
rqd.rqutil.permissionsLow()
|
|
235
|
+
|
|
236
|
+
logger.warning('RQD Starting Up')
|
|
237
|
+
|
|
238
|
+
setup_sentry()
|
|
239
|
+
|
|
240
|
+
rqCore = rqd.rqcore.RqCore(optNimbyOff)
|
|
241
|
+
rqCore.start()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
main()
|