コード例 #1
0
ファイル: ssh.py プロジェクト: mpaepper/spotty
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']

        project_name = project_config['name']
        region = instance_config['region']
        local_ssh_port = instance_config['localSshPort']

        # get instance IP address
        stack = StackResource(None, project_name, region)
        ec2 = boto3.client('ec2', region_name=region)
        ip_address = get_instance_ip_address(ec2, stack.name)

        if self._args.host_os:
            # connect to the host OS
            session_name = self._args.session_name if self._args.session_name else 'spotty-ssh-host-os'
            remote_cmd = ['tmux', 'new', '-s', session_name, '-A']
        else:
            # connect to the container
            session_name = self._args.session_name if self._args.session_name else 'spotty-ssh-container'
            remote_cmd = ['tmux', 'new', '-s', session_name, '-A', 'sudo', '/scripts/container_bash.sh']

        remote_cmd = subprocess.list2cmdline(remote_cmd)

        # connect to the instance
        ssh_command = get_ssh_command(project_name, region, ip_address, remote_cmd, local_ssh_port)
        subprocess.call(ssh_command)
コード例 #2
0
ファイル: sync.py プロジェクト: mpaepper/spotty
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']

        region = instance_config['region']
        project_name = project_config['name']
        local_ssh_port = instance_config['localSshPort']

        output.write('Syncing the project with S3 bucket...')

        # sync the project with S3 bucket
        sync_filters = project_config['syncFilters']
        sync_project_with_s3(self._project_dir, project_name, region, sync_filters, output)

        output.write('Syncing S3 bucket with the instance...')

        # get instance IP address
        stack = StackResource(None, project_name, region)
        ec2 = boto3.client('ec2', region_name=region)
        ip_address = get_instance_ip_address(ec2, stack.name)

        # sync S3 with the instance
        sync_instance_with_s3(ip_address, project_name, region, local_ssh_port)

        output.write('Done')
コード例 #3
0
ファイル: ssh.py プロジェクト: ZohaibAhmed/spotty
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']

        project_name = project_config['name']
        region = instance_config['region']

        # get instance IP address
        stack = StackResource(None, project_name, region)
        ec2 = boto3.client('ec2', region_name=region)
        ip_address = get_instance_ip_address(ec2, stack.name)

        # connect to the instance
        host = 'ubuntu@%s' % ip_address
        key_path = KeyPairResource(None, project_name, region).key_path
        ssh_command = [
            'ssh', '-i', key_path, '-o', 'StrictHostKeyChecking no', '-t', host
        ]

        if self._args.host_os:
            session_name = self._args.session_name if self._args.session_name else 'spotty-ssh-host-os'
            ssh_command += ['tmux', 'new', '-s', session_name, '-A']
        else:
            session_name = self._args.session_name if self._args.session_name else 'spotty-ssh-container'
            ssh_command += [
                'tmux', 'new', '-s', session_name, '-A', 'sudo',
                '/scripts/container_bash.sh'
            ]

        subprocess.call(ssh_command)
コード例 #4
0
ファイル: run.py プロジェクト: ZohaibAhmed/spotty
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']
        project_name = project_config['name']
        region = instance_config['region']

        script_name = self._args.script_name
        if script_name not in self._config['scripts']:
            raise ValueError('Script "%s" is not defined in the configuration file.' % script_name)

        # get instance IP address
        stack = StackResource(None, project_name, region)
        ec2 = boto3.client('ec2', region_name=region)
        ip_address = get_instance_ip_address(ec2, stack.name)

        # tmux session name
        session_name = self._args.session_name if self._args.session_name else 'spotty-script-%s' % script_name

        # base64 encoded user script from the configuration file
        script_base64 = base64.b64encode(self._config['scripts'][script_name].encode('utf-8')).decode('utf-8')

        # remote path where the script will be uploaded
        script_path = '/tmp/docker/%s.sh' % script_name

        # log file for the script outputs
        script_log_file = '/var/log/spotty-run/%s.log' % script_name

        # command to attach user to existing tmux session
        attach_session_cmd = subprocess.list2cmdline(['tmux', 'attach', '-t', session_name, '>', '/dev/null', '2>&1'])

        # command to upload user script to the instance
        upload_script_cmd = subprocess.list2cmdline(['echo', script_base64, '|', 'base64', '-d', '>', script_path])

        # command to log the time when user script started
        start_time_cmd = subprocess.list2cmdline(['echo', '-e', '\\nScript started: `date \'+%Y-%m-%d %H:%M:%S\'`\\n',
                                                  '>>', script_log_file])

        # command to run user script inside the docker container
        docker_cmd = subprocess.list2cmdline(['sudo', '/scripts/container_bash.sh', '-xe', script_path, '2>&1',
                                              '|', 'tee', '-a', script_log_file])

        # command to create new tmux session and run user script
        new_session_cmd = subprocess.list2cmdline(['tmux', 'new', '-s', session_name,
                                                   '%s && %s' % (start_time_cmd, docker_cmd)])

        # composition of the commands: if user cannot be attached to the tmux session (assume the session doesn't
        # exist), then we uploading user script to the instance, creating new tmux session and running that script
        # inside the Docker container
        remote_cmd = '%s || (%s && %s)' % (attach_session_cmd, upload_script_cmd, new_session_cmd)

        # connect to the instance and run the command above
        host = 'ubuntu@%s' % ip_address
        key_path = KeyPairResource(None, project_name, region).key_path
        ssh_command = ['ssh', '-i', key_path, '-o', 'StrictHostKeyChecking no', host, '-t', remote_cmd]

        subprocess.call(ssh_command)
コード例 #5
0
ファイル: sync.py プロジェクト: ZohaibAhmed/spotty
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']

        region = instance_config['region']
        project_name = project_config['name']

        # create bucket for the project
        s3 = boto3.client('s3', region_name=region)
        project_bucket = BucketResource(s3, project_name, region)
        bucket_name = project_bucket.create_bucket(output)

        output.write('Syncing the project with S3 bucket...')

        # sync the project with S3
        project_filters = project_config['syncFilters']
        AwsCli(region=region).s3_sync(self._project_dir,
                                      's3://%s/project' % bucket_name,
                                      delete=True,
                                      filters=project_filters,
                                      capture_output=False)

        # get instance IP address
        stack = StackResource(None, project_name, region)
        ec2 = boto3.client('ec2', region_name=region)
        ip_address = get_instance_ip_address(ec2, stack.name)

        output.write('Syncing S3 bucket with the instance...')

        # sync S3 with the instance
        remote_cmd = subprocess.list2cmdline([
            'sudo', '-i', '/bin/bash', '-e', '/tmp/scripts/sync_project.sh',
            '>', '/dev/null'
        ])

        # connect to the instance and run remote command
        host = 'ubuntu@%s' % ip_address
        key_path = KeyPairResource(None, project_name, region).key_path
        ssh_command = [
            'ssh', '-i', key_path, '-o', 'StrictHostKeyChecking no', '-tq',
            host, remote_cmd
        ]

        subprocess.call(ssh_command)

        output.write('Done')
コード例 #6
0
    def run(self, output: AbstractOutputWriter):
        project_config = self._config['project']
        instance_config = self._config['instance']

        region = instance_config['region']
        availability_zone = instance_config['availabilityZone']
        subnet_id = instance_config['subnetId']

        cf = boto3.client('cloudformation', region_name=region)
        ec2 = boto3.client('ec2', region_name=region)

        project_name = project_config['name']
        stack = StackResource(cf, project_name, region)

        # check if the stack already exists
        if stack.stack_exists():
            raise ValueError('Stack "%s" already exists.\n'
                             'Use "spotty stop" command to delete the stack.' %
                             stack.name)

        # check availability zone and subnet
        check_az_and_subnet(ec2, availability_zone, subnet_id, region)

        # sync the project with S3
        output.write('Syncing the project with S3...')
        sync_filters = project_config['syncFilters']
        bucket_name = sync_project_with_s3(self._project_dir, project_name,
                                           region, sync_filters, output)

        # create or update instance profile
        instance_profile_arn = create_or_update_instance_profile(cf, output)

        # prepare CloudFormation template
        output.write('Preparing CloudFormation template...')

        instance_type = instance_config['instanceType']
        volumes = instance_config['volumes']
        ports = instance_config['ports']
        max_price = instance_config['maxPrice']
        docker_commands = instance_config['docker']['commands']

        template = stack.prepare_template(ec2, availability_zone, subnet_id,
                                          instance_type, volumes, ports,
                                          max_price, docker_commands)

        # create stack
        ami_name = instance_config['amiName']
        root_volume_size = instance_config['rootVolumeSize']
        mount_dirs = [volume['directory'] for volume in volumes]
        docker_config = instance_config['docker']
        remote_project_dir = project_config['remoteDir']

        res = stack.create_stack(ec2, template, instance_profile_arn,
                                 instance_type, ami_name, root_volume_size,
                                 mount_dirs, bucket_name, remote_project_dir,
                                 project_name, self._project_dir,
                                 docker_config)

        output.write('Waiting for the stack to be created...')

        resource_messages = [
            ('SpotInstance', 'launching the instance'),
            ('DockerReadyWaitCondition',
             'waiting for the Docker container to be ready'),
        ]

        # wait for the stack to be created
        status, info = wait_stack_status_changed(
            cf,
            stack_id=res['StackId'],
            waiting_status='CREATE_IN_PROGRESS',
            resource_messages=resource_messages,
            resource_success_status='CREATE_COMPLETE',
            output=output)

        if status == 'CREATE_COMPLETE':
            ip_address = get_instance_ip_address(ec2, stack.name)
            availability_zone = [
                row['OutputValue'] for row in info['Outputs']
                if row['OutputKey'] == 'AvailabilityZone'
            ][0]

            # get the current spot price
            current_price = get_current_spot_price(ec2, instance_type,
                                                   availability_zone)

            output.write(
                '\n'
                '--------------------\n'
                'Instance is running.\n'
                '\n'
                'IP address: %s\n'
                'Current Spot price: $%.04f\n'
                '\n'
                'Use "spotty ssh" command to connect to the Docker container.\n'
                '--------------------' % (ip_address, current_price))
        else:
            raise ValueError(
                'Stack "%s" was not created.\n'
                'Please, see CloudFormation and CloudWatch logs for the details.'
                % stack.name)