c53129c79f
This change: * catches exceptions in the node cleanup method so they don't stop the main run method * implements a timeout on node deletion so that if we can't delete an instance from the cloud, we still eventually delete the node * switches from monotonic to regular time on the state machine start time initializer (since unlike nodepool, this value will be used by multiple components). Change-Id: I17d99dea5f0d165579fc7d804615a0ad09023d44
148 lines
4.3 KiB
Python
148 lines
4.3 KiB
Python
# Copyright 2021-2024 Acme Gating, LLC
|
|
#
|
|
# 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.
|
|
|
|
import time
|
|
|
|
|
|
class StateMachine:
|
|
START = 'start'
|
|
|
|
def __init__(self, initial_state):
|
|
self.state = initial_state.get("state", self.START)
|
|
self.complete = False
|
|
self.start_time = initial_state.get("start_time", time.time())
|
|
|
|
def advance(self):
|
|
pass
|
|
|
|
def toDict(self):
|
|
return dict(
|
|
state=self.state,
|
|
start_time=self.start_time,
|
|
)
|
|
|
|
|
|
class Instance:
|
|
"""Represents a cloud instance
|
|
|
|
This class is used by the State Machine Driver classes to
|
|
represent a standardized version of a remote cloud instance.
|
|
Implement this class in your driver, override the :py:meth:`load`
|
|
method, and supply as many of the fields as possible.
|
|
|
|
The following attributes are required:
|
|
|
|
* ready: bool (whether the instance is ready)
|
|
* deleted: bool (whether the instance is in a deleted state)
|
|
* interface_ip: str
|
|
* metadata: dict
|
|
|
|
The following are optional:
|
|
|
|
* public_ipv4: str
|
|
* public_ipv6: str
|
|
* private_ipv4: str
|
|
* cloud: str
|
|
* az: str
|
|
* region: str
|
|
* host_id: str
|
|
* driver_data: any
|
|
* slot: int
|
|
|
|
And the following are even more optional (as they are usually
|
|
already set from the image configuration):
|
|
|
|
* username: str
|
|
* python_path: str
|
|
* shell_type: str
|
|
* connection_port: str
|
|
* connection_type: str
|
|
* host_keys: [str]
|
|
|
|
This is extremely optional, in fact, it's difficult to imagine
|
|
that it's useful for anything other than the metastatic driver:
|
|
|
|
* node_attributes: dict
|
|
|
|
"""
|
|
def __init__(self):
|
|
self.ready = False
|
|
self.deleted = False
|
|
self.public_ipv4 = None
|
|
self.public_ipv6 = None
|
|
self.private_ipv4 = None
|
|
self.interface_ip = None
|
|
self.cloud = None
|
|
self.az = None
|
|
self.region = None
|
|
self.host_id = None
|
|
self.metadata = {}
|
|
self.driver_data = None
|
|
self.slot = None
|
|
|
|
@property
|
|
def external_id(self):
|
|
"""Return a string representation of external ID(s) for this instance,
|
|
for use in logging"""
|
|
raise NotImplementedError()
|
|
|
|
def __repr__(self):
|
|
state = []
|
|
if self.ready:
|
|
state.append('ready')
|
|
if self.deleted:
|
|
state.append('deleted')
|
|
state = ' '.join(state)
|
|
return '<{klass} {external_id} {state}>'.format(
|
|
klass=self.__class__.__name__,
|
|
external_id=self.external_id,
|
|
state=state)
|
|
|
|
def getQuotaInformation(self):
|
|
"""Return quota information about this instance.
|
|
|
|
:returns: A :py:class:`QuotaInformation` object.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
|
|
class Resource:
|
|
"""Represents a cloud resource
|
|
|
|
This could be an instance, a disk, a floating IP, or anything
|
|
else. It is used by the driver to detect leaked resources so the
|
|
adapter can clean them up.
|
|
|
|
The `type` attribute should be an alphanumeric string suitable for
|
|
inclusion in a statsd metric name.
|
|
|
|
The `metadata` attribute is a dictionary of key/value pairs
|
|
initially supplied by the driver to the adapter when an instance
|
|
or image was created. This is used by the driver to detect leaked
|
|
resources. The adapter may add any other information to this
|
|
instance for its own bookeeping (resource type, id, etc).
|
|
|
|
The 'plural_metric_name' attribute is set in the constructor
|
|
automatically; override this value if necessary.
|
|
|
|
:param str type: The type of resource.
|
|
:param dict metadata: A dictionary of metadata for the resource.
|
|
|
|
"""
|
|
|
|
def __init__(self, metadata, type):
|
|
self.type = type
|
|
self.plural_metric_name = type + 's'
|
|
self.metadata = metadata
|