Esempio n. 1
0
    def respond_to_client(self, response: HttpResponse):
        with wrap_context('responding to client'):
            self.send_response_only(response.status_code)

            if has_header(response.headers, 'Content-Encoding'):
                del response.headers['Content-Encoding']
                if self.config.verbose >= 2:
                    log.debug('removing Content-Encoding header')

            if not has_header(response.headers, 'Content-Length') and \
                    not has_header(response.headers, 'Transfer-Encoding') and response.content:
                response.headers['Content-Length'] = str(len(response.content))
                log.warn('adding missing Content-Length header')

            if has_header(response.headers, 'Content-Length') and has_header(
                    response.headers, 'Transfer-Encoding'):
                del response.headers['Content-Length']
                log.warn(
                    'removed Content-Length header conflicting with Transfer-Encoding'
                )

            for name, value in response.headers.items():
                self.send_header(name, value)
            self.end_headers()

            if self.config.allow_chunking and response.headers.get(
                    'Transfer-Encoding') == 'chunked':
                send_chunked_response(self.wfile, response.content)
            else:
                self.wfile.write(response.content)
            self.close_connection = True
            if self.config.verbose >= 2:
                log.debug('> response sent',
                          client_addr=self.client_address[0],
                          client_port=self.client_address[1])
Esempio n. 2
0
    def generate_response(self, request_0: HttpRequest) -> HttpResponse:
        with wrap_context('generating response'):
            request = request_0.transform(self.extensions.transform_request)
            if request != request_0 and self.config.verbose >= 2:
                log.debug('request transformed')

            immediate_reponse = self.find_immediate_response(request)
            if immediate_reponse:
                return immediate_reponse.log('> immediate response',
                                             self.config.verbose)

            self.cache.clear_old()
            if self.cache.has_cached_response(request):
                return self.cache.replay_response(request).log(
                    '> Cache: returning cached response', self.config.verbose)

            if self.config.replay and self.config.verbose:
                log.warn('request not found in cache', path=request.path)
            response: HttpResponse = proxy_request(
                request,
                default_url=self.config.dst_url,
                timeout=self.config.timeout,
                verbose=self.config.verbose)

            if self.cache.saving_enabled(request, response):
                self.cache.save_response(request, response)

            return response
Esempio n. 3
0
def match_filename(
    filename: str,
    pattern: str,
    replacement_pattern: Optional[str],
    full: bool = False,
    padding: int = 0,
) -> Optional[Match]:
    re_match = match_regex_string(pattern, filename, full)
    if not re_match:
        log.warn('no match', file=filename)
        return None

    group_dict: Dict[int, Optional[str]] = {
        index + 1: group
        for index, group in enumerate(re_match.groups())
    }
    apply_numeric_padding(group_dict, padding)

    if not replacement_pattern:
        return Match(name_from=filename,
                     name_to=None,
                     groups=group_dict,
                     re_match=re_match)

    validate_replacement(re_match, replacement_pattern)
    new_name = expand_replacement(replacement_pattern, group_dict)
    return Match(name_from=filename,
                 name_to=new_name,
                 groups=group_dict,
                 re_match=re_match)
Esempio n. 4
0
def read_alsa_volume():
    master_volume_regex = r'^.*Mono: Playback \d+ \[(\d+)%\] \[(-?\d+\.?\d*)dB\] \[on\]$'
    for line in shell_output('amixer get Master').split('\n'):
        match = re.match(master_volume_regex, line)
        if match:
            return int(match.group(1))
    log.warn('Master volume could not have been read')
    return None
Esempio n. 5
0
def read_mp3_tags(mp3_file: str) -> Tuple[str, str]:
    with wrap_context('reading mp3 tags'):
        audiofile = eyed3.load(mp3_file)
        if audiofile is None or audiofile.tag is None:
            log.warn('no IDv3 tags read', mp3_file=mp3_file)
            return '', ''

        artist = _oremptystr(audiofile.tag.artist).strip()
        title = _oremptystr(audiofile.tag.title).strip()
        log.info('IDv3 tags read', mp3_file=mp3_file, artist=artist, title=title)
        return artist, title
Esempio n. 6
0
def find_usb_data_partition() -> str:
    candidates = list(
        filter(lambda m: m.endswith('/watchmodules'),
               map(lambda p: p.mountpoint, psutil.disk_partitions())))
    if not candidates:
        log.warn('cant find any mounted watchmodules partition')
        return '/mnt/watchmaker/watchmodules'
    assert len(
        candidates
    ) <= 1, f'there are more than one partitions matching watchmodules: {candidates}'
    return candidates[0]
Esempio n. 7
0
def read_pulseaudio_volume():
    master_volume_regex = r'^(.*)Volume: front-left: \d+ / +(\d+)% / (.*)$'
    sink_volumes = []
    for line in shell_output('pactl list sinks').split('\n'):
        match = re.match(master_volume_regex, line)
        if match:
            sink_volumes.append(int(match.group(2)))
    if sink_volumes:
        return sink_volumes[-1]
    log.warn('Master volume could not have been read')
    return None
Esempio n. 8
0
def get_pulseaudio_sink_number():
    master_volume_regex = r'^(\d+)(.*)RUNNING$'
    matches = []
    aux_matches = []
    for line in shell_output('pactl list sinks short').split('\n'):
        match = re.match(master_volume_regex, line)
        if match:
            matches.append(int(match.group(1)))
        aux_match = re.match(r'^(\d+)(.*)$', line)
        if aux_match:
            aux_matches.append(int(aux_match.group(1)))
    if matches:
        return matches[-1]
    log.warn('Running sink number not found, getting last')
    if aux_matches:
        return aux_matches[-1]
    log.warn('No sink found')
    return None
Esempio n. 9
0
def flash_disk(disk: str, persistence: bool, boot_storage_surplus: int, modules: List[str], skip_fs: bool):
    set_workdir(os.path.join(script_real_dir(), '..'))

    log.info(f'checking required files existence')
    assert os.path.exists('squash/filesystem.squashfs')
    assert os.path.exists('content/boot-files')
    assert os.path.exists('content/grub')
    assert os.path.exists('modules/init')

    # TODO unmount disk partitions

    log.warn(f'writing to disk {disk}')
    wrap_shell(f'df {disk}')

    log.info('creating MBR')
    wrap_shell(f'''sudo wipefs {disk}''')
    wrap_shell(f'''sudo dd if=/dev/zero of={disk} seek=1 count=2047''')
    wrap_shell(f'''
sudo parted --script {disk} \\
    mklabel msdos
    ''')

    log.info('calculating partitions size')
    # depend on filesystem.squash size, expand by some surplus (for storage)
    squashfs_size = os.path.getsize('squash/filesystem.squashfs')
    boot_part_min_size = squashfs_size + dir_size('content/boot-files') + dir_size('content/grub')
    boot_part_end_mib = boot_part_min_size / 1024 ** 2 + boot_storage_surplus
    efi_part_end_mib = boot_part_end_mib + efi_part_size
    persistence_part_end_mib = efi_part_end_mib + persistence_part_size
    log.info(f'boot partition size: {boot_part_end_mib}MiB ({boot_storage_surplus}MiB surplus)')

    log.info('creating partitions space')
    if persistence:
        wrap_shell(f'''
sudo parted --script {disk} \\
    mkpart primary fat32 1MiB {boot_part_end_mib}MiB \\
    set 1 lba on \\
    set 1 boot on \\
    mkpart primary fat32 {boot_part_end_mib}MiB {efi_part_end_mib}MiB \\
    set 2 esp on \\
    mkpart primary ext4 {efi_part_end_mib}MiB {persistence_part_end_mib}MiB \\
    mkpart primary ext4 {persistence_part_end_mib}MiB 100%
        ''')
    else:
        wrap_shell(f'''
sudo parted --script {disk} \\
    mkpart primary fat32 1MiB {boot_part_end_mib}MiB \\
    set 1 lba on \\
    set 1 boot on \\
    mkpart primary fat32 {boot_part_end_mib}MiB {efi_part_end_mib}MiB \\
    set 2 esp on \\
    mkpart primary ext4 {efi_part_end_mib}MiB 100%
        ''')
    wrap_shell('sync')

    log.info('making boot partition filesystem')
    wrap_shell(f'''sudo mkfs.fat -F32 {disk}1''')
    log.info('making EFI partition filesystem')
    wrap_shell(f'''sudo mkfs.fat -F32 {disk}2''')
    if persistence:
        log.info('making persistence partition filesystem')
        wrap_shell(f'''sudo mkfs.ext4 -F {disk}3''')
        log.info('making watchmodules partition filesystem')
        wrap_shell(f'''sudo mkfs.ext4 -F {disk}4''')
    else:
        log.info('making watchmodules partition filesystem')
        wrap_shell(f'''sudo mkfs.ext4 -F {disk}3''')
    wrap_shell('sync')

    log.info('setting partition names')
    if persistence:
        wrap_shell(f'''
sudo mlabel -i {disk}1 ::boot
sudo mlabel -i {disk}2 ::EFI
sudo e2label {disk}3 persistence
sudo e2label {disk}4 watchmodules
        ''')
    else:
        wrap_shell(f'''
sudo mlabel -i {disk}1 ::boot
sudo mlabel -i {disk}2 ::EFI
sudo e2label {disk}3 watchmodules
        ''')
    wrap_shell('sync')

    log.info('mounting partitions')
    wrap_shell(f'''sudo mkdir -p /mnt/watchmaker''')
    wrap_shell(f'''
sudo mkdir -p /mnt/watchmaker/boot
sudo mount {disk}1 /mnt/watchmaker/boot
        ''')
    wrap_shell(f'''
sudo mkdir -p /mnt/watchmaker/efi
sudo mount {disk}2 /mnt/watchmaker/efi
        ''')

    wrap_shell(f'''sudo mkdir -p /mnt/watchmaker/watchmodules''')
    if persistence:
        wrap_shell(f'''
sudo mkdir -p /mnt/watchmaker/persistence
sudo mount {disk}3 /mnt/watchmaker/persistence
        ''')
        wrap_shell(f'''sudo mount {disk}4 /mnt/watchmaker/watchmodules''')
    else:
        wrap_shell(f'''sudo mount {disk}3 /mnt/watchmaker/watchmodules''')

    log.info('installing GRUB EFI bootloaders')
    wrap_shell(f'''
sudo grub-install \\
    --target=x86_64-efi \\
    --efi-directory=/mnt/watchmaker/boot \\
    --boot-directory=/mnt/watchmaker/boot/boot \\
    --removable --recheck
    ''')
    wrap_shell(f'''
sudo grub-install \\
    --target=x86_64-efi \\
    --efi-directory=/mnt/watchmaker/efi \\
    --boot-directory=/mnt/watchmaker/boot/boot \\
    --removable --recheck
    ''')

    log.info('installing GRUB i386-pc bootloader')
    wrap_shell(f'''
sudo grub-install \\
    --target=i386-pc \\
    --boot-directory=/mnt/watchmaker/boot/boot \\
    --recheck \\
    {disk}
    ''')

    wrap_shell('sync')

    log.info('Fixing GRUB EFI by replacing with Debian GRUB')
    wrap_shell(f'''
sudo rm /mnt/watchmaker/efi/EFI/BOOT/*
sudo cp -r content/efi/* /mnt/watchmaker/efi/EFI/BOOT/
sudo rm /mnt/watchmaker/boot/EFI/BOOT/*
sudo cp -r content/efi/* /mnt/watchmaker/boot/EFI/BOOT/
sudo cp -r /mnt/watchmaker/efi/EFI/BOOT /mnt/watchmaker/efi/EFI/debian
sudo cp -r /mnt/watchmaker/boot/EFI/BOOT /mnt/watchmaker/boot/EFI/debian

sudo cp -r content/grub/x86_64-efi /mnt/watchmaker/boot/boot/grub/
    ''')

    log.info('making EFI Microsoft workaround')
    wrap_shell(f'''
sudo cp -r /mnt/watchmaker/efi/EFI/BOOT /mnt/watchmaker/efi/EFI/Microsoft
sudo cp -r /mnt/watchmaker/boot/EFI/BOOT /mnt/watchmaker/boot/EFI/Microsoft
    ''')

    log.info('GRUB config')
    wrap_shell(f'''
sudo cp content/grub/grub.cfg /mnt/watchmaker/boot/boot/grub/
sudo cp content/grub/background.png /mnt/watchmaker/boot/boot/grub/
sudo cp content/grub/font.pf2 /mnt/watchmaker/boot/boot/grub/
sudo cp content/grub/loopback.cfg /mnt/watchmaker/boot/boot/grub/
sudo cp content/grub/GRUB_FINDME /mnt/watchmaker/boot/
    ''')

    log.info('Boot base files')
    wrap_shell(f'''
sudo cp -r content/boot-files/[BOOT] /mnt/watchmaker/boot/
sudo cp -r content/boot-files/d-i /mnt/watchmaker/boot/
sudo cp -r content/boot-files/dists /mnt/watchmaker/boot/
sudo cp -r content/boot-files/live /mnt/watchmaker/boot/
sudo cp -r content/boot-files/pool /mnt/watchmaker/boot/
sudo cp -r content/boot-files/.disk /mnt/watchmaker/boot/
    ''')
    wrap_shell(f'''sudo mkdir -p /mnt/watchmaker/boot/storage''')

    log.info('EFI base files')
    wrap_shell(f'''
    sudo cp -r content/boot-files/[BOOT] /mnt/watchmaker/efi/
    sudo cp -r content/boot-files/d-i /mnt/watchmaker/efi/
    sudo cp -r content/boot-files/dists /mnt/watchmaker/efi/
    sudo cp -r content/boot-files/live /mnt/watchmaker/efi/
    sudo cp -r content/boot-files/pool /mnt/watchmaker/efi/
    sudo cp -r content/boot-files/.disk /mnt/watchmaker/efi/
        ''')

    if persistence:
        log.info('Persistence configuration')
        wrap_shell(f'''sudo cp -r content/persistence/persistence.conf /mnt/watchmaker/persistence/''')

    log.info('Copying squash filesystem')
    if not skip_fs:
        wrap_shell(f'''sudo cp squash/filesystem.squashfs /mnt/watchmaker/boot/live/''')

    log.info('Adding init module')
    wrap_shell(f'''sudo cp -r modules/init /mnt/watchmaker/watchmodules/''')
    log.info('Adding dev module')
    wrap_shell(f'''sudo mkdir -p /mnt/watchmaker/watchmodules/dev''')

    log.info('make watchmodules writable to non-root user')
    wrap_shell(f'''sudo chown igrek /mnt/watchmaker/watchmodules -R''')

    if modules:
        log.info(f'Adding optional modules: {modules}')
        target_path = '/mnt/watchmaker/watchmodules'
        for module in modules:
            install_module.add_module(module, target_path)

    log.info('unmounting')
    wrap_shell('sync')
    wrap_shell(f'''sudo umount /mnt/watchmaker/boot''')
    wrap_shell(f'''sudo umount /mnt/watchmaker/efi''')
    wrap_shell(f'''sudo umount /mnt/watchmaker/watchmodules''')
    if persistence:
        wrap_shell(f'''sudo umount /mnt/watchmaker/persistence''')
    wrap_shell('sync')

    log.info('Success')
Esempio n. 10
0
def confirm(yes: bool, msg: str):
    if not yes:
        log.warn(msg)
        while input_required('[yes/no]... ') != 'yes':
            pass