Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions cueadmin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,28 @@ Basic CueAdmin commands:
# List jobs
cueadmin -lj

# List job details
cueadmin -lji

# List hosts
cueadmin -lh

# Kill a job
cueadmin -kill-job JOB_NAME

# Set job priority
cueadmin -priority JOB_NAME 100
# Job management
cueadmin -pause JOB_NAME # Pause a job
cueadmin -unpause JOB_NAME # Resume a job
cueadmin -kill JOB_NAME # Kill a job (with confirmation)
cueadmin -retry JOB_NAME # Retry dead frames
cueadmin -priority JOB_NAME 100 # Set job priority
cueadmin -set-min-cores JOB_NAME 4.0 # Set minimum cores
cueadmin -set-max-cores JOB_NAME 16.0 # Set maximum cores
cueadmin -drop-depends JOB_NAME # Drop job dependencies
```

For full documentation, see the [OpenCue Documentation](https://opencue.io/docs/).

## Running Tests

CueAdmin includes a comprehensive test suite covering allocation management, output formatting, and core functionality.
CueAdmin includes a comprehensive test suite with tests covering job management, allocation management, host operations, output formatting, and core functionality.

### Quick Start

Expand All @@ -74,8 +81,11 @@ pytest --cov=cueadmin --cov-report=term-missing

**Test Types:**
- **Unit tests** - Function-level testing (`tests/test_*.py`)
- **Integration tests** - Command workflow testing
- **Integration tests** - Command workflow testing (`tests/integration_tests.py`)
- **Job commands tests** - Job management operations (`tests/test_job_commands.py`)
- **Allocation tests** - Allocation management functionality (`tests/test_allocation_commands.py`)
- **Host commands tests** - Host operations (`tests/test_host_command.py`)
- **Subscription tests** - Subscription management (`tests/test_subscription_commands.py`)

### Running Tests

Expand Down
169 changes: 169 additions & 0 deletions cueadmin/cueadmin/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,77 @@ def getParser():
choices=[mode.lower() for mode in list(opencue.api.host_pb2.ThreadMode.keys())],
)

#
# Job
#
job_grp = parser.add_argument_group("Job Options")
job_grp.add_argument(
"-pause",
action="store",
nargs="+",
metavar="JOB",
help="Pause specified jobs",
)
job_grp.add_argument(
"-unpause",
action="store",
nargs="+",
metavar="JOB",
help="Unpause specified jobs",
)
job_grp.add_argument(
"-kill",
action="store",
nargs="+",
metavar="JOB",
help="Kill specified jobs",
)
job_grp.add_argument(
"-kill-all",
action="store_true",
help="Kill all jobs (requires -force)",
)
job_grp.add_argument(
"-retry",
action="store",
nargs="+",
metavar="JOB",
help="Retry dead frames for specified jobs",
)
job_grp.add_argument(
"-retry-all",
action="store_true",
help="Retry dead frames for all jobs (requires -force)",
)
job_grp.add_argument(
"-drop-depends",
action="store",
nargs="+",
metavar="JOB",
help="Drop all dependencies for specified jobs",
)
job_grp.add_argument(
"-set-min-cores",
action="store",
nargs=2,
metavar=("JOB", "CORES"),
help="Set minimum cores for a job",
)
job_grp.add_argument(
"-set-max-cores",
action="store",
nargs=2,
metavar=("JOB", "CORES"),
help="Set maximum cores for a job",
)
job_grp.add_argument(
"-priority",
action="store",
nargs=2,
metavar=("JOB", "PRIORITY"),
help="Set job priority",
)

return parser


Expand Down Expand Up @@ -1132,6 +1203,104 @@ def setUpState(hosts_):
burst = int(sub.data.size + (sub.data.size * (int(burst[0:-1]) / 100.0)))
sub.setBurst(int(burst))

#
# Job operations
#
elif args.pause:
for job_name in args.pause:
job = opencue.api.findJob(job_name)
logger.debug("pausing job: %s", opencue.rep(job))
job.pause()

elif args.unpause:
for job_name in args.unpause:
job = opencue.api.findJob(job_name)
logger.debug("unpausing job: %s", opencue.rep(job))
job.resume()

elif args.kill:
def killJobs(job_names):
for job_name in job_names:
job = opencue.api.findJob(job_name)
logger.debug("killing job: %s", opencue.rep(job))
job.kill()

confirm("Kill %d job(s)" % len(args.kill), args.force, killJobs, args.kill)

elif args.kill_all:
def killAllJobs():
jobs = opencue.api.getJobs()
for job in jobs:
logger.debug("killing job: %s", opencue.rep(job))
job.kill()

confirm("Kill ALL jobs", args.force, killAllJobs)

elif args.retry:
def retryJobs(job_names):
for job_name in job_names:
job = opencue.api.findJob(job_name)
logger.debug("retrying dead frames for job: %s", opencue.rep(job))
job.retryFrames()

confirm(
"Retry dead frames for %d job(s)" % len(args.retry),
args.force,
retryJobs,
args.retry,
)

elif args.retry_all:
def retryAllJobs():
jobs = opencue.api.getJobs()
for job in jobs:
logger.debug("retrying dead frames for job: %s", opencue.rep(job))
job.retryFrames()

confirm("Retry dead frames for ALL jobs", args.force, retryAllJobs)

elif args.drop_depends:
def dropDepends(job_names):
for job_name in job_names:
DependUtil.dropAllDepends(job_name)

confirm(
"Drop all dependencies for %d job(s)" % len(args.drop_depends),
args.force,
dropDepends,
args.drop_depends,
)

elif args.set_min_cores:
job = opencue.api.findJob(args.set_min_cores[0])
cores = float(args.set_min_cores[1])
confirm(
"Set min cores for %s to %0.2f" % (opencue.rep(job), cores),
args.force,
job.setMinCores,
cores,
)

elif args.set_max_cores:
job = opencue.api.findJob(args.set_max_cores[0])
cores = float(args.set_max_cores[1])
confirm(
"Set max cores for %s to %0.2f" % (opencue.rep(job), cores),
args.force,
job.setMaxCores,
cores,
)

elif args.priority:
job = opencue.api.findJob(args.priority[0])
priority = int(args.priority[1])
confirm(
"Set priority for %s to %d" % (opencue.rep(job), priority),
args.force,
job.setPriority,
priority,
)


def createAllocation(fac, name, tag):
"""Create a new allocation with the given name and tag."""
Expand Down
Loading