shipyard/src/bin/shipyard_airflow/shipyard_airflow/plugins/drydock_relabel_nodes.py

111 lines
4.1 KiB
Python

# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Update node labels using Drydock
"""
import logging
from airflow.exceptions import AirflowException
from airflow.plugins_manager import AirflowPlugin
try:
from drydock_base_operator import DrydockBaseOperator
from drydock_base_operator import gen_node_name_filter
from drydock_errors import (
DrydockTaskFailedException,
DrydockTaskTimeoutException
)
except ImportError:
from shipyard_airflow.plugins.drydock_base_operator import \
DrydockBaseOperator
from shipyard_airflow.plugins.drydock_base_operator import \
gen_node_name_filter
from shipyard_airflow.plugins.drydock_errors import (
DrydockTaskFailedException,
DrydockTaskTimeoutException
)
LOG = logging.getLogger(__name__)
class DrydockRelabelNodesOperator(DrydockBaseOperator):
"""Drydock Relabel Nodes Operator
Update Kubernetes node labels on a targeted set of nodes
using Drydock.
"""
def do_execute(self):
self.successes = []
LOG.info("Relabeling nodes [%s]", ", ".join(self.target_nodes))
self.setup_configured_values()
self.node_filter = gen_node_name_filter(self.target_nodes)
self.execute_relabel()
self.successes = self.get_successes_for_task(self.drydock_task_id)
self.report_summary()
if not self.is_task_successful():
raise AirflowException(
"One or more nodes requested for relabeling failed to relabel"
)
def setup_configured_values(self):
"""Retrieve and localize the interval and timeout values for destroy
"""
self.q_interval = \
self.dc['physical_provisioner.relabel_nodes_interval']
self.task_timeout = \
self.dc['physical_provisioner.relabel_nodes_timeout']
def execute_relabel(self):
# Trigger DryDock to execute task
task_name = 'relabel_nodes'
self.create_task(task_name)
# Query Task
try:
self.query_task(self.q_interval, self.task_timeout)
except DrydockTaskFailedException:
LOG.exception("Task %s has failed. Some nodes may have been "
"relabeled. The report at the end of processing "
"this step contains the results", task_name)
except DrydockTaskTimeoutException:
LOG.warn("Task %s has timed out after %s seconds. Some nodes may "
"have been relabeled. The report at the end of "
"processing this step contains the results", task_name,
self.task_timeout)
def report_summary(self):
"""Reports the successfully relabeled nodes"""
failed = list(set(self.target_nodes) - set(self.successes))
LOG.info("===== Relabel Nodes Summary =====")
LOG.info(" Nodes requested: %s", ", ".join(sorted(self.target_nodes)))
LOG.info(" Nodes relabeled: %s ", ", ".join(sorted(self.successes)))
LOG.info(" Nodes not relabeled: %s", ", ".join(sorted(failed)))
LOG.info("===== End Relabel Nodes Summary =====")
# TODO: redundant with drydock_destroy_nodes...worth refactoring?
def is_task_successful(self):
"""Boolean if the task was completely succesful."""
failed = set(self.target_nodes) - set(self.successes)
return not failed
class DrydockRelabelNodesOperatorPlugin(AirflowPlugin):
"""Creates DrydockRelabelNodesOperator in Airflow."""
name = 'drydock_relabel_nodes_operator'
operators = [DrydockRelabelNodesOperator]