Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into rc1.5.11
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwjn committed Oct 31, 2022
2 parents 299007e + 8d02e36 commit e123bdd
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 55 deletions.
20 changes: 13 additions & 7 deletions codalab/model/bundle_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,11 @@ def transition_bundle_running(self, bundle, worker_run, row, user_id, worker_id,
'memory_usage': memory_usage,
}

# Increment user time as we go to ensure user doesn't go over time quota.
if user_id == self.root_user_id and hasattr(bundle.metadata, 'time'):
time_increment = worker_run.container_time_total - bundle.metadata.time
self.increment_user_time_used(bundle.owner_id, time_increment)

if worker_run.docker_image is not None:
metadata_update['docker_image'] = worker_run.docker_image

Expand Down Expand Up @@ -1066,7 +1071,7 @@ def transition_bundle_worker_offline(self, bundle):
self.update_bundle(bundle, bundle_update, connection)
return True

def transition_bundle_finalizing(self, bundle, worker_run, connection):
def transition_bundle_finalizing(self, bundle, worker_run, user_id, connection):
"""
Transitions bundle to FINALIZING state:
Saves the failure message and exit code from the worker
Expand All @@ -1076,6 +1081,11 @@ def transition_bundle_finalizing(self, bundle, worker_run, connection):
failure_message, exitcode = worker_run.failure_message, worker_run.exitcode
if failure_message is None and exitcode is not None and exitcode != 0:
failure_message = 'Exit code %d' % exitcode

if user_id == self.root_user_id:
time_increment = worker_run.container_time_total - bundle.metadata.time
self.increment_user_time_used(bundle.owner_id, time_increment)

# Build metadata
metadata = {}
if failure_message is not None:
Expand All @@ -1098,15 +1108,11 @@ def transition_bundle_finished(self, bundle, bundle_location):
failure_message = metadata.get('failure_message', None)
exitcode = metadata.get('exitcode', 0)
state = State.FAILED if failure_message or exitcode else State.READY
if failure_message == 'Kill requested':
if failure_message and 'Kill requested' in failure_message:
state = State.KILLED

worker = self.get_bundle_worker(bundle.uuid)

# Increment the amount of time used for the user whose bundles run on CodaLab's public instances
if worker['user_id'] == self.root_user_id:
self.increment_user_time_used(bundle.owner_id, metadata.get('time', 0))

if worker['shared_file_system']:
# TODO(Ashwin): fix for --link.
self.update_disk_metadata(bundle, bundle_location)
Expand Down Expand Up @@ -1170,7 +1176,7 @@ def bundle_checkin(self, bundle, worker_run, user_id, worker_id):
self.transition_bundle_running(
bundle, worker_run, row, user_id, worker_id, connection
)
return self.transition_bundle_finalizing(bundle, worker_run, connection)
return self.transition_bundle_finalizing(bundle, worker_run, user_id, connection)

if worker_run.state in [State.PREPARING, State.RUNNING]:
return self.transition_bundle_running(
Expand Down
20 changes: 17 additions & 3 deletions codalab/rest/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import http.client
import json
from datetime import datetime
import logging

from bottle import abort, get, local, post, request, response

Expand All @@ -14,6 +15,8 @@
from codalab.worker.bundle_state import BundleCheckinState
from codalab.worker.main import DEFAULT_EXIT_AFTER_NUM_RUNS

logger = logging.getLogger(__name__)


@post("/workers/<worker_id>/checkin", name="worker_checkin", apply=AuthenticatedProtectedPlugin())
def checkin(worker_id):
Expand Down Expand Up @@ -42,16 +45,27 @@ def checkin(worker_id):
request.json.get("preemptible", False),
)

messages = []
for run in request.json["runs"]:
try:
worker_run = BundleCheckinState.from_dict(run)
bundle = local.model.get_bundle(worker_run.uuid)
local.model.bundle_checkin(bundle, worker_run, request.user.user_id, worker_id)
except Exception:
pass

if local.model.get_user_time_quota_left(bundle.owner_id) <= 0:
# Then, user has gone over their time quota and we kill the job.
kill_message = (
'Kill requested: User time quota exceeded. To apply for more quota, please visit the following link: '
'https://codalab-worksheets.readthedocs.io/en/latest/FAQ/#how-do-i-request-more-disk-quota-or-time-quota'
)
messages.append({'type': 'kill', 'uuid': bundle.uuid, 'kill_message': kill_message})
except Exception as e:
logger.info("Exception in REST checkin: {}".format(e))

with closing(local.worker_model.start_listening(socket_id)) as sock:
return local.worker_model.get_json_message(sock, WAIT_TIME_SECS)
messages.append(local.worker_model.get_json_message(sock, WAIT_TIME_SECS))
response.content_type = 'application/json'
return json.dumps(messages)


def check_reply_permission(worker_id, socket_id):
Expand Down
56 changes: 32 additions & 24 deletions codalab/worker/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,29 +451,37 @@ def checkin(self):
# Stop processing any new runs received from server
if not response or self.terminate_and_restage or self.terminate:
return
action_type = response['type']
logger.debug('Received %s message: %s', action_type, response)
if action_type == 'run':
self.initialize_run(response['bundle'], response['resources'])
else:
uuid = response['uuid']
socket_id = response.get('socket_id', None)
if uuid not in self.runs:
if action_type in ['read', 'netcat']:
self.read_run_missing(socket_id)
return
if action_type == 'kill':
self.kill(uuid)
elif action_type == 'mark_finalized':
self.mark_finalized(uuid)
elif action_type == 'read':
self.read(socket_id, uuid, response['path'], response['read_args'])
elif action_type == 'netcat':
self.netcat(socket_id, uuid, response['port'], response['message'])
elif action_type == 'write':
self.write(uuid, response['subpath'], response['string'])
if type(response) is not list:
response = [response]
for action in response:
if not action:
continue
action_type = action['type']
logger.debug('Received %s message: %s', action_type, action)
if action_type == 'run':
self.initialize_run(action['bundle'], action['resources'])
else:
logger.warning("Unrecognized action type from server: %s", action_type)
uuid = action['uuid']
socket_id = action.get('socket_id', None)
if uuid not in self.runs:
if action_type in ['read', 'netcat']:
self.read_run_missing(socket_id)
return
if action_type == 'kill':
kill_message = 'Kill requested'
if 'kill_message' in action:
kill_message = action['kill_message']
self.kill(uuid, kill_message)
elif action_type == 'mark_finalized':
self.mark_finalized(uuid)
elif action_type == 'read':
self.read(socket_id, uuid, action['path'], action['read_args'])
elif action_type == 'netcat':
self.netcat(socket_id, uuid, action['port'], action['message'])
elif action_type == 'write':
self.write(uuid, action['subpath'], action['string'])
else:
logger.warning("Unrecognized action type from server: %s", action_type)

def process_runs(self):
""" Transition each run then filter out finished runs """
Expand Down Expand Up @@ -680,11 +688,11 @@ def initialize_run(self, bundle, resources):
file=sys.stdout,
)

def kill(self, uuid):
def kill(self, uuid, kill_message='Kill requested'):
"""
Marks the run as killed so that the next time its state is processed it is terminated.
"""
self.runs[uuid] = self.runs[uuid]._replace(kill_message='Kill requested', is_killed=True)
self.runs[uuid] = self.runs[uuid]._replace(kill_message=kill_message, is_killed=True)

def restage_bundle(self, uuid):
"""
Expand Down
10 changes: 10 additions & 0 deletions docker_config/compose_files/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ services:
stdin_open: true
tty: true
rest-server:
stdin_open: true
tty: true
volumes:
# Mount the alembic directory so that we can create new database migrations with the alembic version files mounted.
- ./../../alembic/:/opt/codalab-worksheets/alembic/
Expand All @@ -19,3 +21,11 @@ services:
- ./../../tests/:/opt/codalab-worksheets/tests/
- ./../../scripts/:/opt/codalab-worksheets/scripts/
- ./../../codalab/:/opt/codalab-worksheets/codalab/

# Allow developers to use PDB to debug programs in Docker containers.
bundle-manager:
stdin_open: true
tty: true
worker:
stdin_open: true
tty: true
4 changes: 2 additions & 2 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ If you have used up your disk quota and want to reduce your disk usage, here are
- If you have intermediate bundles whose contents you don't need, you can use `cl rm -d <bundle>` to delete only the contents of the bundle but keep the metadata. This way, you keep the provenance and can regenerate this bundle in the future.
- If there are selected files that you wish to keep in a bundle, you can use `cl make <bundle>/<important-file>` to make a new bundle that only has a copy of the desired file and then you can do `cl rm -d <bundle>` to remove all the other files in that bundle.

### How do I request more disk quota?
### How do I request more disk quota or time quota?

If you have tried the steps above and still need more disk quota, please fill out this [form](https://docs.google.com/forms/d/e/1FAIpQLSdS22MaLyE1kx0JL-w2a8f8IasDyc36H_ZuidNBVAE_afMCpw/viewform).
If you have tried the steps above and still need more **disk quota** or **time quota**, please fill out this [form](https://docs.google.com/forms/d/e/1FAIpQLSebCBrglB7z2R7OeHJ_NsVWcUcHVMAW4AQnFxNt0YvTS-rDNA/viewform).

### How do I upload large bundles?

Expand Down
5 changes: 1 addition & 4 deletions frontend/src/components/worksheets/Worksheet/Worksheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,7 @@ class Worksheet extends React.Component {
) {
return;
}
if (!(uuid in bundlesCount)) {
bundlesCount[uuid] = 0;
}
bundlesCount[uuid] += 1;
bundlesCount[uuid] = 1;
let checkedBundles = this.state.checkedBundles;
if (!(uuid in checkedBundles)) {
checkedBundles[uuid] = {};
Expand Down
71 changes: 57 additions & 14 deletions frontend/src/components/worksheets/items/TableItem/TableItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import React, { useEffect } from 'react';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core';
import Checkbox from '@material-ui/core/Checkbox';
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
import CheckBoxIcon from '@material-ui/icons/CheckBox';
import Table from '@material-ui/core/Table';
import TableHead from '@material-ui/core/TableHead';
import TableCell from './TableCell';
Expand Down Expand Up @@ -39,6 +42,7 @@ class TableItem extends React.Component<{
indeterminateCheckState: false,
curSchemaNames: this.props.item.using_schemas.join(' '),
openSchemaTextBox: false,
tableIsSelected: false,
};
this.copyCheckedBundleRows = this.copyCheckedBundleRows.bind(this);
this.showCheckedBundleRowsContents = this.showCheckedBundleRowsContents.bind(this);
Expand All @@ -57,6 +61,7 @@ class TableItem extends React.Component<{
childrenCheckState: childrenStatus,
indeterminateCheckState: false,
checked: false,
tableIsSelected: false,
});
};

Expand Down Expand Up @@ -131,6 +136,26 @@ class TableItem extends React.Component<{
});
};

toggleTableSelect = () => {
const bundles = this.props.item.bundles_spec.bundle_infos;
const tableIsSelected = !this.state.tableIsSelected;

// update the table checkbox state
this.setState({ tableIsSelected });

// update the checkbox state for each bundle row
bundles.forEach((bundle, i) => {
const identifier = Math.random() * 10000; // see handleCheckBundle() for identifier implementation details
this.props.handleCheckBundle(
bundle.uuid,
identifier,
tableIsSelected,
this.refreshCheckBox,
);
this.childrenCheck(i, tableIsSelected);
});
};

// BULK OPERATION RELATED CODE ABOVE

updateRowIndex = (rowIndex) => {
Expand All @@ -150,6 +175,7 @@ class TableItem extends React.Component<{
this.showCheckedBundleRowsContents,
);
let tableClassName = this.props.focused ? 'table focused' : 'table';
let checkboxVariant = this.props.focused || this.state.hovered ? 'action' : 'disabled';
let item = this.props.item;
let bundleInfos = item.bundles_spec.bundle_infos;
let headerItems = item.header;
Expand All @@ -169,26 +195,40 @@ class TableItem extends React.Component<{
style={
index === 0
? {
paddingLeft: editPermission ? '30px' : '70px',
paddingLeft: editPermission ? '6px' : '70px',
paddingBottom: 0,
paddingTop: 0,
}
: {}
}
>
{editPermission && index === 0 && (
<Tooltip title={'Change the schemas of this table'}>
<IconButton>
<ViewListIcon
style={{ padding: '0px', height: 15 }}
onClick={() => {
this.setState({
openSchemaTextBox: !this.state.openSchemaTextBox,
});
}}
/>
</IconButton>
</Tooltip>
<>
<Checkbox
icon={
<CheckBoxOutlineBlankIcon
color={checkboxVariant}
fontSize='small'
/>
}
checkedIcon={<CheckBoxIcon fontSize='small' />}
classes={{ root: classes.tableCheckbox }}
onChange={this.toggleTableSelect}
checked={this.state.tableIsSelected}
/>
<Tooltip title={'Change the schemas of this table'}>
<IconButton>
<ViewListIcon
style={{ padding: '0px', height: 15 }}
onClick={() => {
this.setState({
openSchemaTextBox: !this.state.openSchemaTextBox,
});
}}
/>
</IconButton>
</Tooltip>
</>
)}
{item}
{showStateTooltip && <BundleStateTooltip />}
Expand Down Expand Up @@ -217,7 +257,7 @@ class TableItem extends React.Component<{
worksheetUUID={worksheetUUID}
item={rowItem}
rowIndex={rowIndex}
focused={rowFocused}
focused={this.state.tableIsSelected || rowFocused}
focusIndex={this.props.focusIndex}
setFocus={setFocus}
showNewRerun={this.props.showNewRerun}
Expand Down Expand Up @@ -379,6 +419,9 @@ const styles = () => ({
color: '#000000',
height: 26,
},
tableCheckbox: {
paddingRight: 2,
},
});

const TableContainer = withStyles(styles)(_TableContainer);
Expand Down
Loading

0 comments on commit e123bdd

Please sign in to comment.