Commit e1d791d2 authored by one's avatar one
Browse files

Add --container-name for custom docker container name

parent f57d86f4
...@@ -90,7 +90,8 @@ sb benchmark list-parameters --name pytorch-[a-z]+ ...@@ -90,7 +90,8 @@ sb benchmark list-parameters --name pytorch-[a-z]+
Deploy the SuperBench environments to all managed nodes. Deploy the SuperBench environments to all managed nodes.
```bash title="SB CLI" ```bash title="SB CLI"
sb deploy [--docker-image] sb deploy [--container-name]
[--docker-image]
[--docker-password] [--docker-password]
[--docker-username] [--docker-username]
[--host-file] [--host-file]
...@@ -106,6 +107,7 @@ sb deploy [--docker-image] ...@@ -106,6 +107,7 @@ sb deploy [--docker-image]
| Name | Default | Description | | Name | Default | Description |
|-----------------------|-------------------------|-----------------------------------------------------------------------------------| |-----------------------|-------------------------|-----------------------------------------------------------------------------------|
| `--container-name` | `sb-workspace` | Docker container name. |
| `--docker-image` `-i` | `superbench/superbench` | Docker image URI, [here](./user-tutorial/container-images.mdx) listed all images. | | `--docker-image` `-i` | `superbench/superbench` | Docker image URI, [here](./user-tutorial/container-images.mdx) listed all images. |
| `--docker-password` | `None` | Docker registry password if authentication is needed. | | `--docker-password` | `None` | Docker registry password if authentication is needed. |
| `--docker-username` | `None` | Docker registry username if authentication is needed. | | `--docker-username` | `None` | Docker registry username if authentication is needed. |
...@@ -130,6 +132,11 @@ Deploy default image on local GPU node: ...@@ -130,6 +132,11 @@ Deploy default image on local GPU node:
sb deploy --host-list localhost sb deploy --host-list localhost
``` ```
Deploy using custom container name:
```bash title="SB CLI"
sb deploy --host-list localhost --container-name my-benchmark
```
Deploy image `superbench/cuda:11.1` to all nodes in `./host.ini`: Deploy image `superbench/cuda:11.1` to all nodes in `./host.ini`:
```bash title="SB CLI" ```bash title="SB CLI"
sb deploy --docker-image superbench/cuda:11.1 --host-file ./host.ini sb deploy --docker-image superbench/cuda:11.1 --host-file ./host.ini
...@@ -348,6 +355,7 @@ Run the SuperBench benchmarks distributedly. ...@@ -348,6 +355,7 @@ Run the SuperBench benchmarks distributedly.
```bash title="SB CLI" ```bash title="SB CLI"
sb run [--config-file] sb run [--config-file]
[--config-override] [--config-override]
[--container-name]
[--docker-image] [--docker-image]
[--docker-password] [--docker-password]
[--docker-username] [--docker-username]
...@@ -367,6 +375,7 @@ sb run [--config-file] ...@@ -367,6 +375,7 @@ sb run [--config-file]
|--------------------------|-------------------------|-----------------------------------------------------------------------------| |--------------------------|-------------------------|-----------------------------------------------------------------------------|
| `--config-file` `-c` | `None` | Path to SuperBench config file. | | `--config-file` `-c` | `None` | Path to SuperBench config file. |
| `--config-override` `-C` | `None` | Extra arguments to override config_file. | | `--config-override` `-C` | `None` | Extra arguments to override config_file. |
| `--container-name` | `sb-workspace` | Docker container name. |
| `--docker-image` `-i` | `superbench/superbench` | Docker image URI. | | `--docker-image` `-i` | `superbench/superbench` | Docker image URI. |
| `--docker-password` | `None` | Docker registry password if authentication is needed. | | `--docker-password` | `None` | Docker registry password if authentication is needed. |
| `--docker-username` | `None` | Docker registry username if authentication is needed. | | `--docker-username` | `None` | Docker registry username if authentication is needed. |
...@@ -392,6 +401,11 @@ Run all benchmarks on local GPU node: ...@@ -392,6 +401,11 @@ Run all benchmarks on local GPU node:
sb run --host-list localhost sb run --host-list localhost
``` ```
Run all benchmarks using custom container name:
```bash title="SB CLI"
sb run --host-list localhost --container-name my-benchmark
```
Run all benchmarks on all managed nodes in `./host.ini` using image `superbench/cuda:11.1` Run all benchmarks on all managed nodes in `./host.ini` using image `superbench/cuda:11.1`
and default benchmarking configuration: and default benchmarking configuration:
```bash title="SB CLI" ```bash title="SB CLI"
......
...@@ -42,6 +42,12 @@ def load_arguments(self, command): ...@@ -42,6 +42,12 @@ def load_arguments(self, command):
""" """
with ArgumentsContext(self, '') as ac: with ArgumentsContext(self, '') as ac:
ac.argument('docker_image', options_list=('--docker-image', '-i'), type=str, help='Docker image URI.') ac.argument('docker_image', options_list=('--docker-image', '-i'), type=str, help='Docker image URI.')
ac.argument(
'container_name',
options_list=('--container-name',),
type=str,
help='Docker container name. Defaults to sb-workspace.'
)
ac.argument('docker_username', type=str, help='Docker registry username if authentication is needed.') ac.argument('docker_username', type=str, help='Docker registry username if authentication is needed.')
ac.argument('docker_password', type=str, help='Docker registry password if authentication is needed.') ac.argument('docker_password', type=str, help='Docker registry password if authentication is needed.')
ac.argument('no_docker', action='store_true', help='Run on host directly without Docker.') ac.argument('no_docker', action='store_true', help='Run on host directly without Docker.')
......
...@@ -96,6 +96,7 @@ def process_config_arguments(config_file=None, config_override=None, output_dir= ...@@ -96,6 +96,7 @@ def process_config_arguments(config_file=None, config_override=None, output_dir=
def process_runner_arguments( def process_runner_arguments(
docker_image='superbench/superbench', docker_image='superbench/superbench',
container_name='sb-workspace',
docker_username=None, docker_username=None,
docker_password=None, docker_password=None,
no_docker=False, no_docker=False,
...@@ -113,6 +114,7 @@ def process_runner_arguments( ...@@ -113,6 +114,7 @@ def process_runner_arguments(
Args: Args:
docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest. docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest.
container_name (str, optional): Docker container name. Defaults to sb-workspace.
docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None. docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None.
docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None. docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None.
no_docker (bool, optional): Run on host directly without Docker. Defaults to False. no_docker (bool, optional): Run on host directly without Docker. Defaults to False.
...@@ -138,6 +140,8 @@ def process_runner_arguments( ...@@ -138,6 +140,8 @@ def process_runner_arguments(
""" """
if bool(docker_username) != bool(docker_password): if bool(docker_username) != bool(docker_password):
raise CLIError('Must specify both docker_username and docker_password if authentication is needed.') raise CLIError('Must specify both docker_username and docker_password if authentication is needed.')
if not container_name or not container_name.strip():
raise CLIError('container_name cannot be empty.')
if not (host_file or host_list): if not (host_file or host_list):
raise CLIError('Must specify one of host_file or host_list.') raise CLIError('Must specify one of host_file or host_list.')
host_file = check_argument_file('host_file', host_file) host_file = check_argument_file('host_file', host_file)
...@@ -147,6 +151,7 @@ def process_runner_arguments( ...@@ -147,6 +151,7 @@ def process_runner_arguments(
docker_config = OmegaConf.create( docker_config = OmegaConf.create(
{ {
'image': docker_image, 'image': docker_image,
'container_name': container_name.strip(),
'username': docker_username, 'username': docker_username,
'password': docker_password, 'password': docker_password,
'registry': split_docker_domain(docker_image)[0], 'registry': split_docker_domain(docker_image)[0],
...@@ -210,6 +215,7 @@ def exec_command_handler(config_file=None, config_override=None, output_dir=None ...@@ -210,6 +215,7 @@ def exec_command_handler(config_file=None, config_override=None, output_dir=None
def deploy_command_handler( def deploy_command_handler(
docker_image='superbench/superbench', docker_image='superbench/superbench',
container_name='sb-workspace',
docker_username=None, docker_username=None,
docker_password=None, docker_password=None,
no_image_pull=False, no_image_pull=False,
...@@ -230,6 +236,7 @@ def deploy_command_handler( ...@@ -230,6 +236,7 @@ def deploy_command_handler(
Args: Args:
docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest. docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest.
container_name (str, optional): Docker container name. Defaults to sb-workspace.
docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None. docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None.
docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None. docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None.
no_image_pull (bool, optional): Skip pull and use local Docker image. Defaults to False. no_image_pull (bool, optional): Skip pull and use local Docker image. Defaults to False.
...@@ -245,6 +252,7 @@ def deploy_command_handler( ...@@ -245,6 +252,7 @@ def deploy_command_handler(
""" """
docker_config, ansible_config, sb_config, sb_output_dir = process_runner_arguments( docker_config, ansible_config, sb_config, sb_output_dir = process_runner_arguments(
docker_image=docker_image, docker_image=docker_image,
container_name=container_name,
docker_username=docker_username, docker_username=docker_username,
docker_password=docker_password, docker_password=docker_password,
no_docker=False, no_docker=False,
...@@ -265,6 +273,7 @@ def deploy_command_handler( ...@@ -265,6 +273,7 @@ def deploy_command_handler(
def run_command_handler( def run_command_handler(
docker_image='superbench/superbench', docker_image='superbench/superbench',
container_name='sb-workspace',
docker_username=None, docker_username=None,
docker_password=None, docker_password=None,
no_docker=False, no_docker=False,
...@@ -284,6 +293,7 @@ def run_command_handler( ...@@ -284,6 +293,7 @@ def run_command_handler(
Args: Args:
docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest. docker_image (str, optional): Docker image URI. Defaults to superbench/superbench:latest.
container_name (str, optional): Docker container name. Defaults to sb-workspace.
docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None. docker_username (str, optional): Docker registry username if authentication is needed. Defaults to None.
docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None. docker_password (str, optional): Docker registry password if authentication is needed. Defaults to None.
no_docker (bool, optional): Run on host directly without Docker. Defaults to False. no_docker (bool, optional): Run on host directly without Docker. Defaults to False.
...@@ -303,6 +313,7 @@ def run_command_handler( ...@@ -303,6 +313,7 @@ def run_command_handler(
""" """
docker_config, ansible_config, sb_config, sb_output_dir = process_runner_arguments( docker_config, ansible_config, sb_config, sb_output_dir = process_runner_arguments(
docker_image=docker_image, docker_image=docker_image,
container_name=container_name,
docker_username=docker_username, docker_username=docker_username,
docker_password=docker_password, docker_password=docker_password,
no_docker=no_docker, no_docker=no_docker,
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
examples: examples:
- name: deploy default image on local GPU node - name: deploy default image on local GPU node
text: {cli_name} deploy --host-list localhost text: {cli_name} deploy --host-list localhost
- name: deploy using custom container name
text: {cli_name} deploy --host-list localhost --container-name my-benchmark
- name: deploy image "superbench/cuda:11.1" to all nodes in ./host.ini - name: deploy image "superbench/cuda:11.1" to all nodes in ./host.ini
text: {cli_name} deploy --docker-image superbench/cuda:11.1 --host-file ./host.ini text: {cli_name} deploy --docker-image superbench/cuda:11.1 --host-file ./host.ini
- name: deploy image "superbench/rocm:4.0" to node-0 and node-2, using key file id_rsa for ssh - name: deploy image "superbench/rocm:4.0" to node-0 and node-2, using key file id_rsa for ssh
...@@ -56,6 +58,8 @@ ...@@ -56,6 +58,8 @@
examples: examples:
- name: run all benchmarks on local GPU node - name: run all benchmarks on local GPU node
text: {cli_name} run --host-list localhost text: {cli_name} run --host-list localhost
- name: run all benchmarks using custom container name
text: {cli_name} run --host-list localhost --container-name my-benchmark
- name: run all benchmarks on all nodes in ./host.ini using image "superbench/cuda:11.1" - name: run all benchmarks on all nodes in ./host.ini using image "superbench/cuda:11.1"
and default benchmarking configuration and default benchmarking configuration
text: {cli_name} run --docker-image superbench/cuda:11.1 --host-file ./host.ini text: {cli_name} run --docker-image superbench/cuda:11.1 --host-file ./host.ini
......
...@@ -52,6 +52,11 @@ def __init__(self, sb_config, docker_config, ansible_config, sb_output_dir): ...@@ -52,6 +52,11 @@ def __init__(self, sb_config, docker_config, ansible_config, sb_output_dir):
self._sb_enabled_benchmarks = self.__get_enabled_benchmarks() self._sb_enabled_benchmarks = self.__get_enabled_benchmarks()
logger.info('Runner will run: %s', self._sb_enabled_benchmarks) logger.info('Runner will run: %s', self._sb_enabled_benchmarks)
@property
def _container_name(self):
"""Get docker container name with backward-compatible default."""
return getattr(self._docker_config, 'container_name', 'sb-workspace')
def __set_logger(self, filename): def __set_logger(self, filename):
"""Set logger and add file handler. """Set logger and add file handler.
...@@ -268,6 +273,7 @@ def deploy(self): # pragma: no cover ...@@ -268,6 +273,7 @@ def deploy(self): # pragma: no cover
extravars = { extravars = {
'ssh_port': random.randint(1 << 14, (1 << 15) - 1), 'ssh_port': random.randint(1 << 14, (1 << 15) - 1),
'output_dir': str(self._output_path), 'output_dir': str(self._output_path),
'container': self._container_name,
'docker_image': self._docker_config.image, 'docker_image': self._docker_config.image,
'docker_pull': bool(self._docker_config.pull), 'docker_pull': bool(self._docker_config.pull),
} }
...@@ -287,7 +293,7 @@ def run_sys_info(self): ...@@ -287,7 +293,7 @@ def run_sys_info(self):
logger.info('Runner is going to get node system info.') logger.info('Runner is going to get node system info.')
fcmd = "docker exec sb-workspace bash -lc '{command}'" fcmd = "docker exec {container} bash -lc '{{command}}'".format(container=self._container_name)
if 'skip' not in self._docker_config: if 'skip' not in self._docker_config:
self._docker_config.skip = False self._docker_config.skip = False
...@@ -310,6 +316,7 @@ def check_env(self): # pragma: no cover ...@@ -310,6 +316,7 @@ def check_env(self): # pragma: no cover
self._ansible_client.get_playbook_config( self._ansible_client.get_playbook_config(
'check_env.yaml', 'check_env.yaml',
extravars={ extravars={
'container': self._container_name,
'no_docker': False if 'skip' not in self._docker_config else self._docker_config.skip, 'no_docker': False if 'skip' not in self._docker_config else self._docker_config.skip,
'output_dir': str(self._output_path), 'output_dir': str(self._output_path),
'env': '\n'.join(f'{k}={v}' for k, v in self._sb_config.superbench.env.items()), 'env': '\n'.join(f'{k}={v}' for k, v in self._sb_config.superbench.env.items()),
...@@ -550,7 +557,7 @@ def _run_proc(self, benchmark_name, mode, vars): ...@@ -550,7 +557,7 @@ def _run_proc(self, benchmark_name, mode, vars):
if mode_env_cmds: if mode_env_cmds:
env_list = f"{env_list} && {' && '.join(mode_env_cmds)}" env_list = f"{env_list} && {' && '.join(mode_env_cmds)}"
fcmd = "docker exec sb-workspace bash -lc '{env_list} && {command}'" fcmd = "docker exec {container} bash -lc '{{env_list}} && {{command}}'".format(container=self._container_name)
if self._docker_config.skip: if self._docker_config.skip:
fcmd = "bash -c '{env_list} && cd $SB_WORKSPACE && {command}'" fcmd = "bash -c '{env_list} && cd $SB_WORKSPACE && {command}'"
ansible_runner_config = self._ansible_client.get_shell_config( ansible_runner_config = self._ansible_client.get_shell_config(
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import unittest import unittest
from knack.util import CLIError
import superbench.cli._handler as cli_handler import superbench.cli._handler as cli_handler
...@@ -78,3 +80,19 @@ def test_split_docker_domain(self): ...@@ -78,3 +80,19 @@ def test_split_docker_domain(self):
domain, name = cli_handler.split_docker_domain(test_case['input']) domain, name = cli_handler.split_docker_domain(test_case['input'])
self.assertEqual(domain, test_case['domain']) self.assertEqual(domain, test_case['domain'])
self.assertEqual(name, test_case['name']) self.assertEqual(name, test_case['name'])
def test_process_runner_arguments_container_name(self):
"""Test process_runner_arguments saves custom container name."""
docker_config, _, _, _ = cli_handler.process_runner_arguments(
host_list='localhost',
container_name='sb-custom',
)
self.assertEqual(docker_config.container_name, 'sb-custom')
def test_process_runner_arguments_empty_container_name(self):
"""Test process_runner_arguments rejects empty container name."""
with self.assertRaises(CLIError):
cli_handler.process_runner_arguments(
host_list='localhost',
container_name=' ',
)
...@@ -511,6 +511,30 @@ def fake_get_shell_config(cmd): ...@@ -511,6 +511,30 @@ def fake_get_shell_config(cmd):
self.assertIn('-x PATH', captured['cmd']) self.assertIn('-x PATH', captured['cmd'])
self.assertNotIn('export "PATH=', captured['cmd']) self.assertNotIn('export "PATH=', captured['cmd'])
@mock.patch('superbench.runner.ansible.AnsibleClient.run')
def test_run_proc_uses_custom_container_name(self, mock_ansible_client_run):
"""Test _run_proc uses configured docker container name."""
mock_ansible_client_run.return_value = 0
self.runner._sb_benchmarks = {'foo': {}}
self.runner._docker_config.container_name = 'sb-custom'
captured = {}
def fake_get_shell_config(cmd):
captured['cmd'] = cmd
return {'module_args': cmd, 'cmdline': '', 'host_pattern': 'localhost', 'module': 'shell'}
self.runner._ansible_client.get_shell_config = fake_get_shell_config
mode = OmegaConf.create({
'name': 'local',
'proc_num': 1,
'env': {},
'prefix': '',
})
self.runner._run_proc('foo', mode, {'proc_rank': 0})
self.assertIn('docker exec sb-custom bash -lc', captured['cmd'])
@mock.patch('superbench.runner.ansible.AnsibleClient.run') @mock.patch('superbench.runner.ansible.AnsibleClient.run')
def test_run_proc_no_docker_keeps_tmp_env_source(self, mock_ansible_client_run): def test_run_proc_no_docker_keeps_tmp_env_source(self, mock_ansible_client_run):
"""Test _run_proc still sources /tmp/sb.env in no_docker mode.""" """Test _run_proc still sources /tmp/sb.env in no_docker mode."""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment