def ssh_copy_id(cls,  # pylint: disable=too-many-arguments
                 instance: object,
                 name: str,
                 user: str,
                 key_file: str,
                 comment: str = "test@local") -> None:
     container = cls.get_container(instance, name)
     pub_key = pub_key_from_private_key_file(key_file)
     shell_command = f"umask 077 && echo 'ssh-rsa {pub_key} {comment}' >> ~/.ssh/authorized_keys"
     res = container.exec_run(["sh", "-c", shell_command], user=user)
     if res.exit_code:
         raise DockerException(f"{container}: {res.output.decode('utf-8')}")
    def _create_instance(self, node_index, dc_idx, spot=False):
        # if size of disk is larget than 80G, then
        # change the timeout of job completion to default * 3.

        gce_job_default_timeout = None
        if self._gce_image_size and int(self._gce_image_size) > 80:
            gce_job_default_timeout = self._gce_services[
                dc_idx].connection.timeout
            self._gce_services[
                dc_idx].connection.timeout = gce_job_default_timeout * 3
            self.log.info("Job complete timeout is set to %ss" %
                          self._gce_services[dc_idx].connection.timeout)
        name = f"{self.node_prefix}-{dc_idx}-{node_index}".lower()
        gce_disk_struct = self._get_disks_struct(name=name, dc_idx=dc_idx)
        # Name must start with a lowercase letter followed by up to 63
        # lowercase letters, numbers, or hyphens, and cannot end with a hyphen
        assert len(name) <= 63, "Max length of instance name is 63"
        startup_script = self.test_config.get_startup_script()

        if self.params.get("scylla_linux_distro") in (
                "ubuntu-bionic",
                "ubuntu-xenial",
                "ubuntu-focal",
        ):
            # we need to disable sshguard to prevent blocking connections from the builder
            startup_script += dedent("""
                sudo systemctl disable sshguard
                sudo systemctl stop sshguard
            """)
        username = self.params.get("gce_image_username")
        public_key = pub_key_from_private_key_file(
            self.params.get("user_credentials_path"))
        create_node_params = dict(
            name=name,
            size=self._gce_instance_type,
            image=self._gce_image,
            ex_network=self._gce_network,
            ex_disks_gce_struct=gce_disk_struct,
            ex_metadata={
                **self.tags,
                "Name":
                name,
                "NodeIndex":
                node_index,
                "startup-script":
                startup_script,
                "user-data":
                json.dumps(
                    dict(scylla_yaml=dict(cluster_name=self.name),
                         start_scylla_on_first_boot=False)),
                "block-project-ssh-keys":
                "true",
                "ssh-keys":
                f"{username}:ssh-rsa {public_key}",
            },
            ex_service_accounts=self._service_accounts,
            ex_preemptible=spot)

        instance = self._create_node_with_retries(
            name=name,
            dc_idx=dc_idx,
            create_node_params=create_node_params,
            spot=spot)

        self.log.info('Created %s instance %s',
                      'spot' if spot else 'on-demand', instance)
        if gce_job_default_timeout:
            self.log.info('Restore default job timeout %s' %
                          gce_job_default_timeout)
            self._gce_services[
                dc_idx].connection.timeout = gce_job_default_timeout
        return instance
Exemplo n.º 3
0
    def _create_instance(self, node_index, dc_idx, spot=False):
        # if size of disk is larget than 80G, then
        # change the timeout of job completion to default * 3.

        gce_job_default_timeout = None
        if self._gce_image_size and int(self._gce_image_size) > 80:
            gce_job_default_timeout = self._gce_services[
                dc_idx].connection.timeout
            self._gce_services[
                dc_idx].connection.timeout = gce_job_default_timeout * 3
            self.log.info("Job complete timeout is set to %ss" %
                          self._gce_services[dc_idx].connection.timeout)
        name = f"{self.node_prefix}-{dc_idx}-{node_index}".lower()
        gce_disk_struct = list()
        gce_disk_struct.append(
            self._get_root_disk_struct(name=name,
                                       disk_type=self._gce_image_type,
                                       dc_idx=dc_idx))
        for i in range(self._gce_n_local_ssd):
            gce_disk_struct.append(
                self._get_local_ssd_disk_struct(name=name,
                                                index=i,
                                                dc_idx=dc_idx))
        if self._add_disks:
            for disk_type, disk_size in self._add_disks.items():
                disk_size = int(disk_size)
                if disk_size:
                    gce_disk_struct.append(
                        self._get_persistent_disk_struct(name=name,
                                                         disk_size=disk_size,
                                                         disk_type=disk_type,
                                                         dc_idx=dc_idx))
        self.log.info(gce_disk_struct)
        # Name must start with a lowercase letter followed by up to 63
        # lowercase letters, numbers, or hyphens, and cannot end with a hyphen
        assert len(name) <= 63, "Max length of instance name is 63"
        startup_script = cluster.Setup.get_startup_script()

        if self.params.get("scylla_linux_distro") in (
                "ubuntu-bionic",
                "ubuntu-xenial",
                "ubuntu-focal",
        ):
            # we need to disable sshguard to prevent blocking connections from the builder
            startup_script += dedent("""
                sudo systemctl disable sshguard
                sudo systemctl stop sshguard
            """)
        username = self.params.get("gce_image_username")
        public_key = pub_key_from_private_key_file(
            self.params.get("user_credentials_path"))
        create_node_params = dict(
            name=name,
            size=self._gce_instance_type,
            image=self._gce_image,
            ex_network=self._gce_network,
            ex_disks_gce_struct=gce_disk_struct,
            ex_metadata={
                **self.tags,
                "Name":
                name,
                "NodeIndex":
                node_index,
                "startup-script":
                startup_script,
                "user-data":
                json.dumps(
                    dict(scylla_yaml=dict(cluster_name=self.name),
                         start_scylla_on_first_boot=False)),
                "block-project-ssh-keys":
                "true",
                "ssh-keys":
                f"{username}:ssh-rsa {public_key}",
            },
            ex_service_accounts=self._service_accounts,
            ex_preemptible=spot)
        try:
            instance = self._gce_services[dc_idx].create_node(
                **create_node_params)
        except GoogleBaseError as details:
            if not spot:
                raise
            self.log.warning(
                'Unable to create a spot instance, try to create an on-demand one: %s',
                details)

            # May happen that spot instance was preempted during instance creating. This instance won't be
            # destroyed but stopped and stays with the name in the instances pool. In this case we should destroy this
            # instance before creating new one
            if "Instance failed to start due to preemption" in str(details) and \
                    (failed_instance := self._get_instances_by_name(dc_idx=dc_idx, name=name)):
                self._gce_services[dc_idx].destroy_node(node=failed_instance,
                                                        destroy_boot_disk=True)

            create_node_params['ex_preemptible'] = spot = False
            instance = self._gce_services[dc_idx].create_node(
                **create_node_params)