Implement updating services based on update notifications

This implements adding additional services via the metadata interface by
reacting on the compute.instance.update notifications. This effectively
covers updates from already enrolled nodes with some services towards
adding new services.

Note that this still requires folks to remove services manually if
they're no longer used.

Another important thing to note is that this doesn't yet cover updates
from non-enrolled deployments to enrolling them and adding services.

Related-Bug: #1715295
Change-Id: I48ab94a184657f6730281740935a05143abbc499
This commit is contained in:
Juan Antonio Osorio Robles 2018-02-05 17:06:36 +00:00
parent 168d812557
commit e2a15af973
2 changed files with 39 additions and 2 deletions

View File

@ -78,9 +78,9 @@ class Controller(object):
class JoinController(Controller):
def __init__(self):
def __init__(self, ipaclient=IPAClient()):
super(JoinController, self).__init__(None)
self.ipaclient = IPAClient()
self.ipaclient = ipaclient
def _get_allowed_hostclass(self, project_name):
"""Get the allowed list of hostclass from configuration."""

View File

@ -25,8 +25,10 @@ from neutronclient.v2_0 import client as neutron_client
from novaclient import client as nova_client
from novajoin import config
from novajoin.ipa import IPAClient
from novajoin import join
from novajoin.keystone_client import get_session
from novajoin.keystone_client import register_keystoneauth_opts
from novajoin.nova import get_instance
from novajoin.util import get_domain
from novajoin.util import get_fqdn
from oslo_log import log as logging
@ -57,6 +59,7 @@ class NotificationEndpoint(object):
publisher_id='^compute.*|^network.*',
event_type='^compute.instance.create.end|'
'^compute.instance.delete.end|'
'^compute.instance.update|'
'^network.floating_ip.(dis)?associate|'
'^floatingip.update.end')
@ -82,6 +85,40 @@ class NotificationEndpoint(object):
hostname = self._generate_hostname(payload.get('hostname'))
instance_id = payload.get('instance_id')
LOG.info("Add new host %s (%s)", instance_id, hostname)
elif event_type == 'compute.instance.update':
join_controller = join.JoinController(ipaclient)
hostname_short = payload.get('hostname')
instance_id = payload.get('instance_id')
payload_metadata = payload.get('metadata')
image_metadata = payload.get('image_meta')
hostname = self._generate_hostname(hostname_short)
enroll = payload_metadata.get('ipa_enroll', '')
image_enroll = image_metadata.get('ipa_enroll', '')
if enroll.lower() != 'true' and image_enroll.lower() != 'true':
LOG.info('IPA enrollment not requested, skipping update of %s',
hostname)
return
# Ensure this instance exists in nova
instance = get_instance(instance_id)
if instance is None:
msg = 'No such instance-id, %s' % instance_id
LOG.error(msg)
return
ipaclient.start_batch_operation()
# key-per-service
managed_services = [
payload_metadata[key] for key in payload_metadata.keys()
if key.startswith('managed_service_')]
if managed_services:
join_controller.handle_services(hostname, managed_services)
# compact json format
if 'compact_services' in payload_metadata:
join_controller.handle_compact_services(
hostname_short, payload_metadata.get('compact_services'))
ipaclient.flush_batch_operation()
elif event_type == 'compute.instance.delete.end':
hostname_short = payload.get('hostname')
instance_id = payload.get('instance_id')