Compare commits

...

2 Commits

Author SHA1 Message Date
5c2ec9ce78 Standardize names and lock config 2022-10-25 19:25:38 +00:00
f2a6a4ac1f Add locking to git commands
Avoids conflicting attempts when multiple hosts check in at once.
2022-10-25 19:25:38 +00:00
6 changed files with 56 additions and 48 deletions

View File

@@ -66,7 +66,7 @@ pvc:
path: "/var/home/joshua/pvc" path: "/var/home/joshua/pvc"
# Path to the deploy key (if applicable) used to clone and pull the repository # Path to the deploy key (if applicable) used to clone and pull the repository
keyfile: "/var/home/joshua/id_ed25519.joshua.key" key_file: "/var/home/joshua/id_ed25519.joshua.key"
# Git remote URI for the repository # Git remote URI for the repository
remote: "ssh://git@git.bonifacelabs.ca:2222/bonifacelabs/pvc.git" remote: "ssh://git@git.bonifacelabs.ca:2222/bonifacelabs/pvc.git"
@@ -77,6 +77,9 @@ pvc:
# Clusters configuration file # Clusters configuration file
clusters_file: "clusters.yml" clusters_file: "clusters.yml"
# Lock file to use for Git interaction
lock_file: "/run/pvcbootstrapd.lock"
# Filenames of the various group_vars components of a cluster # Filenames of the various group_vars components of a cluster
# Generally with pvc-ansible this will contain 2 files: "base.yml", and "pvc.yml"; refer to the # Generally with pvc-ansible this will contain 2 files: "base.yml", and "pvc.yml"; refer to the
# pvc-ansible documentation and examples for details on these files. # pvc-ansible documentation and examples for details on these files.

View File

@@ -179,7 +179,7 @@ def read_config():
) )
# Get the Ansible configuration # Get the Ansible configuration
for key in ["path", "keyfile", "remote", "branch", "clusters_file"]: for key in ["path", "key_file", "remote", "branch", "clusters_file", "lock_file"]:
try: try:
config[f"ansible_{key}"] = o_ansible[key] config[f"ansible_{key}"] = o_ansible[key]
except Exception: except Exception:

View File

@@ -66,7 +66,7 @@ def run_bootstrap(config, cspec, cluster, nodes):
limit=f"{cluster.name}", limit=f"{cluster.name}",
playbook=f"{config['ansible_path']}/pvc.yml", playbook=f"{config['ansible_path']}/pvc.yml",
extravars={ extravars={
"ansible_ssh_private_key_file": config["ansible_keyfile"], "ansible_ssh_private_key_file": config["ansible_key_file"],
"bootstrap": "yes", "bootstrap": "yes",
}, },
forks=len(nodes), forks=len(nodes),

View File

@@ -22,6 +22,7 @@
import os.path import os.path
import git import git
import yaml import yaml
from filelock import FileLock
import pvcbootstrapd.lib.notifications as notifications import pvcbootstrapd.lib.notifications as notifications
@@ -36,7 +37,7 @@ def init_repository(config):
Clone the Ansible git repository Clone the Ansible git repository
""" """
try: try:
git_ssh_cmd = f"ssh -i {config['ansible_keyfile']} -o StrictHostKeyChecking=no" git_ssh_cmd = f"ssh -i {config['ansible_key_file']} -o StrictHostKeyChecking=no"
if not os.path.exists(config["ansible_path"]): if not os.path.exists(config["ansible_path"]):
print( print(
f"First run: cloning repository {config['ansible_remote']} branch {config['ansible_branch']} to {config['ansible_path']}" f"First run: cloning repository {config['ansible_remote']} branch {config['ansible_branch']} to {config['ansible_path']}"
@@ -60,61 +61,65 @@ def pull_repository(config):
""" """
Pull (with rebase) the Ansible git repository Pull (with rebase) the Ansible git repository
""" """
logger.info(f"Updating local configuration repository {config['ansible_path']}") with FileLock(config['ansible_lock_file']):
try: logger.info(f"Updating local configuration repository {config['ansible_path']}")
git_ssh_cmd = f"ssh -i {config['ansible_keyfile']} -o StrictHostKeyChecking=no" try:
g = git.cmd.Git(f"{config['ansible_path']}") git_ssh_cmd = f"ssh -i {config['ansible_key_file']} -o StrictHostKeyChecking=no"
g.pull(rebase=True, env=dict(GIT_SSH_COMMAND=git_ssh_cmd)) g = git.cmd.Git(f"{config['ansible_path']}")
g.submodule("update", "--init", env=dict(GIT_SSH_COMMAND=git_ssh_cmd)) logger.debug("Performing git pull")
except Exception as e: g.pull(rebase=True, env=dict(GIT_SSH_COMMAND=git_ssh_cmd))
logger.warn(e) logger.debug("Performing git submodule update")
notifications.send_webhook(config, "failure", "Failed to update Git repository") g.submodule("update", "--init", env=dict(GIT_SSH_COMMAND=git_ssh_cmd))
except Exception as e:
logger.warn(e)
notifications.send_webhook(config, "failure", "Failed to update Git repository")
logger.info("Completed repository synchonization")
def commit_repository(config): def commit_repository(config):
""" """
Commit uncommitted changes to the Ansible git repository Commit uncommitted changes to the Ansible git repository
""" """
logger.info( with FileLock(config['ansible_lock_file']):
f"Committing changes to local configuration repository {config['ansible_path']}" logger.info(
) f"Committing changes to local configuration repository {config['ansible_path']}"
try:
g = git.cmd.Git(f"{config['ansible_path']}")
g.add("--all")
commit_env = {
"GIT_COMMITTER_NAME": "PVC Bootstrap",
"GIT_COMMITTER_EMAIL": "git@pvcbootstrapd",
}
g.commit(
"-m",
"Automated commit from PVC Bootstrap Ansible subsystem",
author="PVC Bootstrap <git@pvcbootstrapd>",
env=commit_env,
) )
notifications.send_webhook(config, "success", "Successfully committed to Git repository") try:
except Exception as e: g = git.cmd.Git(f"{config['ansible_path']}")
logger.warn(e) g.add("--all")
notifications.send_webhook(config, "failure", "Failed to commit to Git repository") commit_env = {
"GIT_COMMITTER_NAME": "PVC Bootstrap",
"GIT_COMMITTER_EMAIL": "git@pvcbootstrapd",
}
g.commit(
"-m",
"Automated commit from PVC Bootstrap Ansible subsystem",
author="PVC Bootstrap <git@pvcbootstrapd>",
env=commit_env,
)
notifications.send_webhook(config, "success", "Successfully committed to Git repository")
except Exception as e:
logger.warn(e)
notifications.send_webhook(config, "failure", "Failed to commit to Git repository")
def push_repository(config): def push_repository(config):
""" """
Push changes to the default remote Push changes to the default remote
""" """
logger.info( with FileLock(config['ansible_lock_file']):
f"Pushing changes from local configuration repository {config['ansible_path']}" logger.info(
) f"Pushing changes from local configuration repository {config['ansible_path']}"
)
try: try:
git_ssh_cmd = f"ssh -i {config['ansible_keyfile']} -o StrictHostKeyChecking=no" git_ssh_cmd = f"ssh -i {config['ansible_key_file']} -o StrictHostKeyChecking=no"
g = git.Repo(f"{config['ansible_path']}") g = git.Repo(f"{config['ansible_path']}")
origin = g.remote(name="origin") origin = g.remote(name="origin")
origin.push(env=dict(GIT_SSH_COMMAND=git_ssh_cmd)) origin.push(env=dict(GIT_SSH_COMMAND=git_ssh_cmd))
notifications.send_webhook(config, "success", "Successfully pushed Git repository") notifications.send_webhook(config, "success", "Successfully pushed Git repository")
except Exception as e: except Exception as e:
logger.warn(e) logger.warn(e)
notifications.send_webhook(config, "failure", "Failed to push Git repository") notifications.send_webhook(config, "failure", "Failed to push Git repository")
def load_cspec_yaml(config): def load_cspec_yaml(config):

View File

@@ -43,7 +43,7 @@ def run_paramiko(config, node_address):
ssh_client.connect( ssh_client.connect(
hostname=node_address, hostname=node_address,
username=config["deploy_username"], username=config["deploy_username"],
key_filename=config["ansible_keyfile"], key_filename=config["ansible_key_file"],
) )
yield ssh_client yield ssh_client
ssh_client.close() ssh_client.close()

View File

@@ -43,7 +43,7 @@ def init_tftp(config):
os.makedirs(config["tftp_root_path"]) os.makedirs(config["tftp_root_path"])
os.makedirs(config["tftp_host_path"]) os.makedirs(config["tftp_host_path"])
shutil.copyfile( shutil.copyfile(
f"{config['ansible_keyfile']}.pub", f"{config['tftp_root_path']}/keys.txt" f"{config['ansible_key_file']}.pub", f"{config['tftp_root_path']}/keys.txt"
) )
build_tftp_repository(config) build_tftp_repository(config)