def computer_setup(ctx, non_interactive, **kwargs): """Create a new computer.""" from aiida.orm.utils.builders.computer import ComputerBuilder if kwargs['label'] in get_computer_names(): echo.echo_critical( 'A computer called {c} already exists. ' 'Use "verdi computer duplicate {c}" to set up a new ' 'computer starting from the settings of {c}.'.format( c=kwargs['label'])) kwargs['transport'] = kwargs['transport'].name kwargs['scheduler'] = kwargs['scheduler'].name computer_builder = ComputerBuilder(**kwargs) try: computer = computer_builder.new() except (ComputerBuilder.ComputerValidationError, ValidationError) as e: echo.echo_critical(f'{type(e).__name__}: {e}') try: computer.store() except ValidationError as err: echo.echo_critical(f'unable to store the computer: {err}. Exiting...') else: echo.echo_success(f'Computer<{computer.pk}> {computer.label} created') echo.echo_info( 'Note: before the computer can be used, it has to be configured with the command:' ) echo.echo_info( f' verdi computer configure {computer.transport_type} {computer.label}' )
class TestComputerConfigure(AiidaTestCase): """Tests for the configuring of instance of the `Computer` ORM class.""" def setUp(self): """Prepare current user and computer builder with common properties.""" from aiida.orm.utils.builders.computer import ComputerBuilder self.comp_builder = ComputerBuilder(label='test', description='computer', hostname='localhost') self.comp_builder.scheduler = 'direct' self.comp_builder.work_dir = '/tmp/aiida' self.comp_builder.prepend_text = '' self.comp_builder.append_text = '' self.comp_builder.mpiprocs_per_machine = 8 self.comp_builder.mpirun_command = 'mpirun' self.comp_builder.shebang = '#!xonsh' self.user = orm.User.objects.get_default() def test_configure_local(self): """Configure a computer for local transport and check it is configured.""" self.comp_builder.label = 'test_configure_local' self.comp_builder.transport = 'local' comp = self.comp_builder.new() comp.store() comp.configure() self.assertTrue(comp.is_user_configured(self.user)) def test_configure_ssh(self): """Configure a computer for ssh transport and check it is configured.""" self.comp_builder.label = 'test_configure_ssh' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() comp.configure(username='******', port='22') self.assertTrue(comp.is_user_configured(self.user)) def test_configure_ssh_invalid(self): """Try to configure computer with invalid auth params and check it fails.""" self.comp_builder.label = 'test_configure_ssh_invalid' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() with self.assertRaises(ValueError): comp.configure(username='******', invalid_auth_param='TEST')
def on_setup_computer(self, _=None, on_success=None): """Create a new computer.""" with self.setup_compupter_out: clear_output() if self.label.value == "": # check hostname print("Please specify the computer name (for AiiDA)") return try: computer = orm.Computer.objects.get(label=self.label.value) print(f"A computer called {self.label.value} already exists.") if on_success: on_success() return except common.NotExistent: pass items_to_configure = [ "label", "hostname", "description", "work_dir", "mpirun_command", "mpiprocs_per_machine", "transport", "scheduler", "prepend_text", "append_text", "shebang", ] kwargs = { key: getattr(self, key).value for key in items_to_configure } computer_builder = ComputerBuilder(**kwargs) try: computer = computer_builder.new() except ( ComputerBuilder.ComputerValidationError, common.exceptions.ValidationError, ) as err: print(f"{type(err).__name__}: {err}") return try: computer.store() except common.exceptions.ValidationError as err: print(f"Unable to store the computer: {err}.") return if self._configure_computer(): if on_success: on_success() print(f"Computer<{computer.pk}> {computer.label} created")
def computer_setup(ctx, non_interactive, **kwargs): """Create a new computer.""" from aiida.orm.utils.builders.computer import ComputerBuilder if kwargs['label'] in get_computer_names(): echo.echo_critical( 'A computer called {c} already exists. ' 'Use "verdi computer duplicate {c}" to set up a new ' 'computer starting from the settings of {c}.'.format( c=kwargs['label'])) if not non_interactive: try: pre, post = ensure_scripts(kwargs.pop('prepend_text', ''), kwargs.pop('append_text', ''), kwargs) except InputValidationError as exception: raise click.BadParameter( 'invalid prepend and or append text: {}'.format(exception)) kwargs['prepend_text'] = pre kwargs['append_text'] = post kwargs['transport'] = kwargs['transport'].name kwargs['scheduler'] = kwargs['scheduler'].name computer_builder = ComputerBuilder(**kwargs) try: computer = computer_builder.new() except (ComputerBuilder.ComputerValidationError, ValidationError) as e: echo.echo_critical('{}: {}'.format(type(e).__name__, e)) try: computer.store() except ValidationError as err: echo.echo_critical( 'unable to store the computer: {}. Exiting...'.format(err)) else: echo.echo_success('Computer<{}> {} created'.format( computer.pk, computer.name)) echo.echo_info( 'Note: before the computer can be used, it has to be configured with the command:' ) echo.echo_info(' verdi computer configure {} {}'.format( computer.get_transport_type(), computer.name))
def get_cx1_computer(work_dir=None, key_filename=None): """get or create a Computer node, to interface with the ICL Cx1 HPC Parameters ---------- work_dir :str absolute path to the work directory key_filename : str ssh key filename, e.g. /Users/user_name/.ssh/id_rsa Returns ------- aiida.orm.Computer """ try: computer_cx1 = Computer.objects.get(name=_COMPUTER_NAME) except NotExistent: if work_dir is None: raise ValueError('work_dir not specified') computer_builder = ComputerBuilder( label=_COMPUTER_NAME, description='Imperial HPC cx1 computer', transport='ssh', scheduler='pbspro_cx1', hostname='login.cx1.hpc.ic.ac.uk', prepend_text='', append_text='', work_dir=work_dir, shebang='#!/bin/bash', mpiprocs_per_machine=16, mpirun_command='mpiexec') computer_cx1 = computer_builder.new() computer_cx1.store() computer_cx1.configure(look_for_keys=True, key_filename=key_filename, timeout=60, allow_agent=True, compress=True, load_system_host_keys=True, safe_interval=5.0) return computer_cx1
class TestVerdiComputerConfigure(AiidaTestCase): """Test the ``verdi computer configure`` command.""" def setUp(self): """Prepare computer builder with common properties.""" from aiida.orm.utils.builders.computer import ComputerBuilder self.cli_runner = CliRunner() self.user = orm.User.objects.get_default() self.comp_builder = ComputerBuilder(label='test_comp_setup') self.comp_builder.hostname = 'localhost' self.comp_builder.description = 'Test Computer' self.comp_builder.scheduler = 'direct' self.comp_builder.work_dir = '/tmp/aiida' self.comp_builder.prepend_text = '' self.comp_builder.append_text = '' self.comp_builder.mpiprocs_per_machine = 8 self.comp_builder.mpirun_command = 'mpirun' self.comp_builder.shebang = '#!xonsh' def test_top_help(self): """Test help option of verdi computer configure.""" result = self.cli_runner.invoke(computer_configure, ['--help'], catch_exceptions=False) self.assertIn('ssh', result.output) self.assertIn('local', result.output) def test_reachable(self): # pylint: disable=no-self-use """Test reachability of top level and sub commands.""" import subprocess as sp sp.check_output(['verdi', 'computer', 'configure', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'local', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'ssh', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'show', '--help']) def test_local_ni_empty(self): """ Test verdi computer configure local <comp> Test twice, with comp setup for local or ssh. * with computer setup for local: should succeed * with computer setup for ssh: should fail """ self.comp_builder.label = 'test_local_ni_empty' self.comp_builder.transport = 'local' comp = self.comp_builder.new() comp.store() options = ['local', comp.label, '--non-interactive', '--safe-interval', '0'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.comp_builder.label = 'test_local_ni_empty_mismatch' self.comp_builder.transport = 'ssh' comp_mismatch = self.comp_builder.new() comp_mismatch.store() options = ['local', comp_mismatch.label, '--non-interactive'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertIsNotNone(result.exception) self.assertIn('ssh', result.output) self.assertIn('local', result.output) def test_local_interactive(self): """Test computer configuration for local transports.""" self.comp_builder.label = 'test_local_interactive' self.comp_builder.transport = 'local' comp = self.comp_builder.new() comp.store() result = self.cli_runner.invoke(computer_configure, ['local', comp.label], input='\n', catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) def test_ssh_interactive(self): """ Check that the interactive prompt is accepting the correct values. Actually, even passing a shorter set of options should work: ``verdi computer configure ssh`` is able to provide sensible default parameters reading from the ssh config file. We are here therefore only checking some of them. """ self.comp_builder.label = 'test_ssh_interactive' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() remote_username = '******' port = 345 look_for_keys = False key_filename = '' # I just pass the first four arguments: # the username, the port, look_for_keys, and the key_filename # This testing also checks that an empty key_filename is ok command_input = ('{remote_username}\n{port}\n{look_for_keys}\n{key_filename}\n').format( remote_username=remote_username, port=port, look_for_keys='yes' if look_for_keys else 'no', key_filename=key_filename ) result = self.cli_runner.invoke( computer_configure, ['ssh', comp.label], input=command_input, catch_exceptions=False ) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) new_auth_params = comp.get_authinfo(self.user).get_auth_params() self.assertEqual(new_auth_params['username'], remote_username) self.assertEqual(new_auth_params['port'], port) self.assertEqual(new_auth_params['look_for_keys'], look_for_keys) self.assertEqual(new_auth_params['key_filename'], key_filename) def test_local_from_config(self): """Test configuring a computer from a config file""" label = 'test_local_from_config' self.comp_builder.label = label self.comp_builder.transport = 'local' computer = self.comp_builder.new() computer.store() interval = 20 with tempfile.NamedTemporaryFile('w') as handle: handle.write("""--- safe_interval: {interval} """.format(interval=interval)) handle.flush() options = ['local', computer.label, '--config', os.path.realpath(handle.name)] result = self.cli_runner.invoke(computer_configure, options) self.assertClickResultNoException(result) self.assertEqual(computer.get_configuration()['safe_interval'], interval) def test_ssh_ni_empty(self): """ Test verdi computer configure ssh <comp> Test twice, with comp setup for ssh or local. * with computer setup for ssh: should succeed * with computer setup for local: should fail """ self.comp_builder.label = 'test_ssh_ni_empty' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() options = ['ssh', comp.label, '--non-interactive', '--safe-interval', '1'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.comp_builder.label = 'test_ssh_ni_empty_mismatch' self.comp_builder.transport = 'local' comp_mismatch = self.comp_builder.new() comp_mismatch.store() options = ['ssh', comp_mismatch.label, '--non-interactive'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertIsNotNone(result.exception) self.assertIn('local', result.output) self.assertIn('ssh', result.output) def test_ssh_ni_username(self): """Test verdi computer configure ssh <comp> --username=<username>.""" self.comp_builder.label = 'test_ssh_ni_username' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() username = '******' options = ['ssh', comp.label, '--non-interactive', '--username={}'.format(username), '--safe-interval', '1'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.assertEqual( orm.AuthInfo.objects.get(dbcomputer_id=comp.id, aiidauser_id=self.user.id).get_auth_params()['username'], username ) def test_show(self): """Test verdi computer configure show <comp>.""" self.comp_builder.label = 'test_show' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() result = self.cli_runner.invoke(computer_configure, ['show', comp.label], catch_exceptions=False) result = self.cli_runner.invoke(computer_configure, ['show', comp.label, '--defaults'], catch_exceptions=False) self.assertIn('* username', result.output) result = self.cli_runner.invoke( computer_configure, ['show', comp.label, '--defaults', '--as-option-string'], catch_exceptions=False ) self.assertIn('--username='******'ssh', comp.label, '--non-interactive'] config_cmd.extend(result.output.replace("'", '').split(' ')) result_config = self.cli_runner.invoke(computer_configure, config_cmd, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result_config.output) result_cur = self.cli_runner.invoke( computer_configure, ['show', comp.label, '--as-option-string'], catch_exceptions=False ) self.assertIn('--username=', result.output) self.assertEqual(result_cur.output, result.output)
class TestVerdiComputerConfigure(AiidaTestCase): def setUp(self): """Prepare computer builder with common properties.""" from aiida.orm.utils.builders.computer import ComputerBuilder self.cli_runner = CliRunner() self.user = orm.User.objects.get_default() self.comp_builder = ComputerBuilder(label='test_comp_setup') self.comp_builder.hostname = 'localhost' self.comp_builder.description = 'Test Computer' self.comp_builder.scheduler = 'direct' self.comp_builder.work_dir = '/tmp/aiida' self.comp_builder.prepend_text = '' self.comp_builder.append_text = '' self.comp_builder.mpiprocs_per_machine = 8 self.comp_builder.mpirun_command = 'mpirun' self.comp_builder.shebang = '#!xonsh' def test_top_help(self): """Test help option of verdi computer configure.""" result = self.cli_runner.invoke(computer_configure, ['--help'], catch_exceptions=False) self.assertIn('ssh', result.output) self.assertIn('local', result.output) def test_reachable(self): """Test reachability of top level and sub commands.""" import subprocess as sp output = sp.check_output(['verdi', 'computer', 'configure', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'local', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'ssh', '--help']) sp.check_output(['verdi', 'computer', 'configure', 'show', '--help']) def test_local_ni_empty(self): """ Test verdi computer configure local <comp> Test twice, with comp setup for local or ssh. * with computer setup for local: should succeed * with computer setup for ssh: should fail """ self.comp_builder.label = 'test_local_ni_empty' self.comp_builder.transport = 'local' comp = self.comp_builder.new() comp.store() options = [ 'local', comp.label, '--non-interactive', '--safe-interval', '0' ] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.comp_builder.label = 'test_local_ni_empty_mismatch' self.comp_builder.transport = 'ssh' comp_mismatch = self.comp_builder.new() comp_mismatch.store() options = ['local', comp_mismatch.label, '--non-interactive'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertIsNotNone(result.exception) self.assertIn('ssh', result.output) self.assertIn('local', result.output) def test_local_interactive(self): self.comp_builder.label = 'test_local_interactive' self.comp_builder.transport = 'local' comp = self.comp_builder.new() comp.store() result = self.cli_runner.invoke(computer_configure, ['local', comp.label], input='\n', catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) def test_local_from_config(self): """Test configuring a computer from a config file""" label = 'test_local_from_config' self.comp_builder.label = label self.comp_builder.transport = 'local' computer = self.comp_builder.new() computer.store() interval = 20 with tempfile.NamedTemporaryFile('w') as handle: handle.write("""--- safe_interval: {interval} """.format(interval=interval)) handle.flush() options = [ 'local', computer.label, '--config', os.path.realpath(handle.name) ] result = self.cli_runner.invoke(computer_configure, options) self.assertClickResultNoException(result) self.assertEqual(computer.get_configuration()['safe_interval'], interval) def test_ssh_ni_empty(self): """ Test verdi computer configure ssh <comp> Test twice, with comp setup for ssh or local. * with computer setup for ssh: should succeed * with computer setup for local: should fail """ self.comp_builder.label = 'test_ssh_ni_empty' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() options = [ 'ssh', comp.label, '--non-interactive', '--safe-interval', '1' ] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.comp_builder.label = 'test_ssh_ni_empty_mismatch' self.comp_builder.transport = 'local' comp_mismatch = self.comp_builder.new() comp_mismatch.store() options = ['ssh', comp_mismatch.label, '--non-interactive'] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertIsNotNone(result.exception) self.assertIn('local', result.output) self.assertIn('ssh', result.output) def test_ssh_ni_username(self): """Test verdi computer configure ssh <comp> --username=<username>.""" self.comp_builder.label = 'test_ssh_ni_username' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() username = '******' options = [ 'ssh', comp.label, '--non-interactive', '--username={}'.format(username), '--safe-interval', '1' ] result = self.cli_runner.invoke(computer_configure, options, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result.output) self.assertEqual( orm.AuthInfo.objects.get( dbcomputer_id=comp.id, aiidauser_id=self.user.id).get_auth_params()['username'], username) def test_show(self): """Test verdi computer configure show <comp>.""" self.comp_builder.label = 'test_show' self.comp_builder.transport = 'ssh' comp = self.comp_builder.new() comp.store() result = self.cli_runner.invoke(computer_configure, ['show', comp.label], catch_exceptions=False) result = self.cli_runner.invoke(computer_configure, ['show', comp.label, '--defaults'], catch_exceptions=False) self.assertIn('* username', result.output) result = self.cli_runner.invoke( computer_configure, ['show', comp.label, '--defaults', '--as-option-string'], catch_exceptions=False) self.assertIn('--username='******'ssh', comp.label, '--non-interactive'] config_cmd.extend(result.output.replace("'", '').split(' ')) result_config = self.cli_runner.invoke(computer_configure, config_cmd, catch_exceptions=False) self.assertTrue(comp.is_user_configured(self.user), msg=result_config.output) result_cur = self.cli_runner.invoke( computer_configure, ['show', comp.label, '--as-option-string'], catch_exceptions=False) self.assertIn('--username=', result.output) self.assertEqual(result_cur.output, result.output)