Wednesday, July 19, 2017

Experiments with Vagrant and Packer On Fedora

I've had a strange experience with Packer on Fedora 13 (yes, 13). This may prove interesting to anyone encountered the following error from Packer:
==> virtualbox-iso: Error waiting for SSH: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password keyboard-interactive], no supported methods remain
I'm using Packer v0.10.1.

I found that adjusting ssh_timeout did not seem to have any effect. I ended up setting ssh_handshake_attempts equal to 100.

What I learned in investigating this problem is this is the error message you get when your handshake attempts threshold exceeded. This message implies an authentication problem, but in my case it occurred because SSH wasn't running yet.

To remedy this, confirm whether it's an SSH problem or not by executing:
PACKER_LOG=1 PACKER_LOG_PATH=out.log packer build --debug TEMPLATE
Stop at the step:
==> virtualbox-iso: Pausing after run of step 'StepTypeBootCommand'. Press enter to continue.
Run Packer on a template with headless set to false (the default) so you can watch the virtual machine boot. Login once things are up and running. If the install completes you can also "Press enter to continue". If Packer connects over SSH you can rule out an SSH problem.

To confirm whether it's problem with your Packer template check ssh_wait_timeout and ssh_timeoutssh_wait_timeout is deprecated in favour of ssh_timeout.  Curiously, neither seemed to have any effect on Fedora 13. At one point, I set my timeout to hours and watched Packer shutdown the virtual machine because it couldn't connect is the space of a few minutes.

t was successful in using both parameters on CentOS 7.0 and 7.2 as well as Debian 7.11.0 and 8.5.0. 

The problem doesn't appear to be my Packer template (Fedora uses the same template as CentOS and Debian). 

It isn't Packer (it works properly on CentOS and Debian).

Weird.

Thursday, July 13, 2017

A Poor Use of GitPython

I'm working on a project that uses Git. It's written in Python. The initial implementation uses GitPython. GitPython provides abstractions for using Python with Git repositories.

My project uses git-log. I chose a layered approach using this function as a single point of access to the Git repository.

This function is the focal point for access to the git repository.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def cmd(path, *args, **kwargs):
    """
    Generate a git log command using the the provided arguments. Empty git log
    lines are stripped by this function.

    Params:
        [in] path - location of repo
        [in] args - non-keyword arguments to provide to the git log command
        [in] kwargs - keyword arguments to provide to the git log command

    Returns: a list of lines returned from the git log command
    """
    repo = Repo(path)
    assert repo.bare == False
    result = list()
    for line in repo.git.log(*args, **kwargs).split('\n'):
        if len(line) == 0:
     continue
        result.append(line)
    return result

Layering separates the repository interface from the information in the repository. It isolates the GitPython interface from the rest of the project but introduces a different challenge.

Consider this function.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def commitLog(path, commitHash):
    """
    Return the log entry for a single commit hash.

    Params:
        [in] path - location of repo
        [in] commitHash - commit hash

    Returns: log entry for the specified commit hash
    """
    return ' '.join(cmd(path, '-n 1', commitHash)[3:])

My approach to layering moves the command-line options for git-log into the clients of cmd().

A better approach might have used GitPython's object model. Unfortunately the learning curve requires knowledge of git internals. Something I wanted to avoid in the interest of time. In my haste I didn't take advantage of GitPython's power.

The next revision of this project needs to revisit GitPython's object model to help traverse my repository. It will be interesting to see if this model supports obtaining information  provided by git log -n 1 and other porcelain options easily.