Skip to content
This repository has been archived by the owner on Sep 12, 2022. It is now read-only.

ATMO-2149: Atmosphere deploy without Subspace #631

Merged
merged 4 commits into from
Jul 12, 2018

Conversation

calvinmclean
Copy link
Contributor

@calvinmclean calvinmclean commented Jun 29, 2018

Description

Replace Subspace by using Ansible's PlaybookCLI to deploy instances.

The main purpose of this PR was to reduce the amount of core Ansible code that had to be modified by Subspace in order to make it easier to update the program to work with newer Ansible versions. In the end, Subspace was completely removed.

In the place of Subspace, we use Ansible's PlaybookCLI object. The execute_playbooks() function adds two attributes to ansible.constants (ansible.cfg values) to suppress Ansible playbook stdout and set the directory used for logging. This is done here because ansible.cfg expects a file path, not a directory path, and would cause errors on regular runs of ansible-playbook and we do not want to suppress stdout on regular ansible-playbook runs. Then, it loops through playbook files and for each one:

  1. Creates a list of arguments identical to those that would be used with the ansible-playbook command (--inventory-file, --limit, --extra-vars, and the playbook path)
  2. Creates the PlaybookCLI object and parses the arguments
  3. Runs the playbook and exits the loop if there is a failure

It returns a list of return codes from each playbook.

More changes were made to the functions that handle the return values to expect integers instead of playbook stats. This greatly simplifies the process and allows for easy upgrades to newer Ansible versions.

Related PRs:

requirements.txt Outdated
@@ -5,7 +5,7 @@
# pip-compile --output-file requirements.txt requirements.in
#
amqp==2.2.2 # via kombu
ansible==2.3.2.0 # via subspace
ansible>=2.5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is generated. The requirements.in needs to be edited instead. This is documented in REQUIREMENTS.md.

@@ -34,14 +35,16 @@ def ansible_deployment(
"""
Use service.ansible to deploy to an instance.
"""
username = str(username)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being coerced to a string?


(unmount_rc, unmount_stdout, unmount_stderr) = _extract_ansible_register(playbook_results, 'unmount_result')
if unmount_rc != 0:
_raise_unmount_playbook_failure(unmount_rc, unmount_stdout, unmount_stderr)

This comment was marked as resolved.

@@ -289,22 +257,17 @@ def user_deploy(instance_ip, username, instance_id, first_deploy=True, **runner_
else:
async_scripts.append(script)

format_script = lambda s: {"name": s.get_title_slug(), "text": s.get_text()}
format_script = lambda s: {"name": str(s.get_title_slug()), "text": str(s.get_text()).splitlines()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this coercion necessary for 2.5?
We should not be passing a list of lines, why the change?

# An error has occurred during deployment!
# Handle specific errors from ansible based on the 'register' results.
playbook_results = playbook_runner.results.get(hostname)
_check_results_for_script_failure(playbook_results)
# If the failure was not related to users boot-scripts,
# handle as a generic ansible failure.
return raise_playbook_errors(playbook_runner, instance_id, instance_ip, hostname)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to be consistent with playbook_results rather than playbook_runner which refers to an Ansible object

inventory_dir = "%s/ansible" % settings.ANSIBLE_ROOT

setattr(C, "DEFAULT_STDOUT_CALLBACK", "null")
setattr(C, "DEFAULT_LOG_PATH", settings.DEPLOY_LOG_DIR)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we don't want either of these setattr calls. The expectation with our use of ansible is that it would log in the celery log, and the plugin would log elsewhere, if there is a duplicate log in the celery log that just needs to be figured out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEFAULT_LOG_PATH should not be repurposed here. its a constant completely internal to ansible, that is likely used in the absence of log_path. If you need to get a directory into the plugin, the ansible plugin should be templated by clank just like the ansible.cfg.j2

@@ -529,45 +445,38 @@ def playbook_error_message(runner_details, error_name):


def execution_has_unreachable(pbs, hostname):
"""Return value 4 means unreachable in ansible-playbook"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want naming to fall behind, pbs no longer make sense. See if we actually need these methods, if we do, then please rename param.

@@ -48,14 +48,14 @@ def check_volume_task(driverCls, provider, identity,
playbooks = deploy_check_volume(
instance.ip, username, instance.id,
device_location, device_type=device_type)
celery_logger.info(playbooks.__dict__)
celery_logger.info(playbooks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is playbooks a list of return values? what is being logged?

@calvinmclean calvinmclean force-pushed the ATMO-2149 branch 7 times, most recently from bbef979 to 060150a Compare July 11, 2018 17:55
Copy link
Contributor

@cdosborn cdosborn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really good, there are a few more things, that i mentioned in person but not in my review.

@@ -48,14 +48,12 @@ def check_volume_task(driverCls, provider, identity,
playbooks = deploy_check_volume(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be playbook_results or something else

hostname = build_host_name(instance.id, instance.ip)
result = False if execution_has_failures(playbooks, hostname)\
or execution_has_unreachable(playbooks, hostname) else True
result = False if execution_has_failures(playbooks) or execution_has_unreachable(playbooks) else True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

playbooks is a misnomer

if not result:
raise Exception(
"Error encountered while checking volume for filesystem: %s"
% playbooks.stats.summarize(host=hostname))
% playbooks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't want to log this, should instead log instance_id and volume_id

@calvinmclean
Copy link
Contributor Author

Whoops I missed a few of those. I went through and found the rest and removed some function calls that were unnecessary (like building a hostname that is never used)

@cdosborn cdosborn changed the base branch from master to v33 July 12, 2018 18:31
@coveralls
Copy link

coveralls commented Jul 12, 2018

Coverage Status

Coverage increased (+1.04%) to 37.495% when pulling a4cfd8f on calvinmclean:ATMO-2149 into 70d7059 on cyverse:v33.

@cdosborn
Copy link
Contributor

I tested this and launched two instances and confirmed that deployment/volume attach/volume detach work.

Again great work.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants