mirror of
https://github.com/gryf/mistral-evacuate.git
synced 2026-04-02 09:13:32 +02:00
Separate geting flavors and filtering into separe tasks
Also minimalize numbers of calls to nova API Signed-off-by: Dawid Deja <dawid.deja@intel.com>
This commit is contained in:
@@ -18,7 +18,7 @@ Installation
|
|||||||
mistral.actions =
|
mistral.actions =
|
||||||
…
|
…
|
||||||
custom.filter_vm = filter_vm_action:FilterVmAction
|
custom.filter_vm = filter_vm_action:FilterVmAction
|
||||||
custom.evacuate = evacuate_vm_action:EvacuateVmAction
|
custom.find_flavors = find_flavors_by_extra_spec:FindFlavorsByExtraSpecs
|
||||||
|
|
||||||
to ``setup.cfg`` file under Mistral repository
|
to ``setup.cfg`` file under Mistral repository
|
||||||
#. Run db-sync tool via either
|
#. Run db-sync tool via either
|
||||||
@@ -47,7 +47,10 @@ Installation
|
|||||||
"search_opts": {
|
"search_opts": {
|
||||||
"host": "compute-hostanme"
|
"host": "compute-hostanme"
|
||||||
},
|
},
|
||||||
"on_shared_storage": false
|
"on_shared_storage": false,
|
||||||
|
"flavor_extra_specs": {
|
||||||
|
"evacuation:evacuate": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#. Trigger the action via:
|
#. Trigger the action via:
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
from mistral.actions.openstack.actions import NovaAction
|
|
||||||
from mistral.workflow.utils import Result
|
|
||||||
|
|
||||||
|
|
||||||
class EvacuateVmAction(NovaAction):
|
|
||||||
|
|
||||||
def __init__(self, uuid, on_shared_storage, evacuate):
|
|
||||||
self._uuid = uuid
|
|
||||||
self._on_shared_storage = on_shared_storage
|
|
||||||
self._evacuate = evacuate
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
client = self._get_client()
|
|
||||||
|
|
||||||
if self._evacuate:
|
|
||||||
client.servers.evacuate(self._uuid,
|
|
||||||
on_shared_storage=self._on_shared_storage)
|
|
||||||
@@ -4,52 +4,28 @@ FilterVmAction - custom action.
|
|||||||
Simple action for filtering VM on the presence of metadata/extra spec
|
Simple action for filtering VM on the presence of metadata/extra spec
|
||||||
"evacuate" flag
|
"evacuate" flag
|
||||||
"""
|
"""
|
||||||
from mistral.actions.openstack.actions import NovaAction
|
from mistral.actions import base
|
||||||
from mistral.workflow.utils import Result
|
|
||||||
|
|
||||||
|
|
||||||
class FilterVmException(Exception):
|
class FilterVmAction(base.Action):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FilterVmAction(NovaAction):
|
|
||||||
"""
|
"""
|
||||||
Filter and return VMs whith the flag 'evacuate' either on vm metadtata
|
Filter and return VMs whith the flag 'evacuate' either on vm metadtata
|
||||||
or flavor extra spec.
|
or flavor extra spec.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, metadata, flavor, uuid):
|
def __init__(self, flavors, vms):
|
||||||
"""init."""
|
"""init."""
|
||||||
self._metadata = metadata
|
self._flavors = flavors
|
||||||
self._flavor = flavor
|
self._vms = vms
|
||||||
self._uuid = uuid
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Entry point for the action execution."""
|
"""Entry point for the action execution."""
|
||||||
client = self._get_client()
|
result = []
|
||||||
metadata = self._metadata
|
|
||||||
|
|
||||||
if str(metadata.get('evacuate')).upper() == 'TRUE':
|
for vm in self._vms:
|
||||||
return Result(data={'evacuate': True, 'uuid': self._uuid})
|
if str(vm['metadata'].get('evacuate')).upper() == 'TRUE'\
|
||||||
elif str(metadata.get('evacuate')).upper() == 'FALSE':
|
or (str(vm['metadata'].get('evacuate')).upper() != 'FALSE'
|
||||||
return Result(data={'evacuate': False, 'uuid': self._uuid})
|
and vm['flavor']['id'] in self._flavors):
|
||||||
|
result.append(vm['id'])
|
||||||
|
|
||||||
# Ether is no metadata for vm - check flavor.
|
return result
|
||||||
try:
|
|
||||||
# Maybe this should be done in different action
|
|
||||||
# only once per whole workflow.
|
|
||||||
# In case there is ~100 VMs to evacuate, there will be
|
|
||||||
# the same amount of calls to nova API.
|
|
||||||
flavor = filter(
|
|
||||||
lambda f: f.id == self._flavor,
|
|
||||||
client.flavors.list()
|
|
||||||
)[0]
|
|
||||||
except IndexError:
|
|
||||||
raise FilterVmException('Flavor not found')
|
|
||||||
|
|
||||||
evacuate = flavor.get_keys().get('evacuation:evacuate')
|
|
||||||
|
|
||||||
if str(evacuate).upper() == 'TRUE':
|
|
||||||
return Result(data={'evacuate': True, 'uuid': self._uuid})
|
|
||||||
|
|
||||||
return Result(data={'evacuate': False, 'uuid': self._uuid})
|
|
||||||
32
find_flavors_by_extra_spec.py
Normal file
32
find_flavors_by_extra_spec.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
FindFlavorsByExtraSpecs - custom action.
|
||||||
|
|
||||||
|
It works pretty similar to nova.flavors_findall, but it looks for items in
|
||||||
|
flavors extra spec
|
||||||
|
"""
|
||||||
|
|
||||||
|
from mistral.actions.openstack.actions import NovaAction
|
||||||
|
|
||||||
|
|
||||||
|
class FindFlavorsByExtraSpecs(NovaAction):
|
||||||
|
|
||||||
|
def __init__(self, extra_specs):
|
||||||
|
if type(extra_specs) is dict:
|
||||||
|
self._extra_specs = extra_specs
|
||||||
|
else:
|
||||||
|
raise TypeError("Extra spec must be a dictionary")
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
client = self._get_client()
|
||||||
|
flavors = client.flavors.list()
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for flavor in flavors:
|
||||||
|
flavor_extra_specs = flavor.get_keys().items()
|
||||||
|
if all(
|
||||||
|
item in flavor_extra_specs
|
||||||
|
for item in self._extra_specs.items()
|
||||||
|
):
|
||||||
|
result.append(flavor.id)
|
||||||
|
|
||||||
|
return result
|
||||||
@@ -2,27 +2,33 @@
|
|||||||
version: '2.0'
|
version: '2.0'
|
||||||
|
|
||||||
host-evacuate:
|
host-evacuate:
|
||||||
description: Evacuate VMs from given host
|
description: Evacuate VMs from given host
|
||||||
type: direct
|
type: direct
|
||||||
|
input:
|
||||||
|
- search_opts
|
||||||
|
- on_shared_storage
|
||||||
|
- flavor_extra_specs
|
||||||
|
|
||||||
input:
|
tasks:
|
||||||
- search_opts
|
list_vms:
|
||||||
- on_shared_storage
|
action: nova.servers_list search_opts=<% $.search_opts %>
|
||||||
|
publish:
|
||||||
|
vms: <% $.list_vms %>
|
||||||
|
on-success: filter_vms
|
||||||
|
|
||||||
tasks:
|
list_flavors:
|
||||||
list_vms:
|
action: custom.find_flavors extra_specs=<% $.flavor_extra_specs %>
|
||||||
action: nova.servers_list search_opts=<% $.search_opts %>
|
publish:
|
||||||
publish:
|
flavors: <% $.list_flavors %>
|
||||||
vms: <% $.list_vms %>
|
on-success: filter_vms
|
||||||
on-success: filter_vms
|
|
||||||
|
|
||||||
filter_vms:
|
filter_vms:
|
||||||
with-items: vm in <% $.vms %>
|
join: all
|
||||||
action: custom.filter flavor=<% $.vm.flavor.id %> metadata=<% $.vm.metadata %> uuid=<% $.vm.id %>
|
action: custom.filter flavors=<% $.flavors %> vms=<% $.vms %>
|
||||||
publish:
|
publish:
|
||||||
filtered_vms: <% $.filter_vms %>
|
filtered_vms: <% $.filter_vms %>
|
||||||
on-success: evacuate_vms
|
on-success: evacuate_vms
|
||||||
|
|
||||||
evacuate_vms:
|
evacuate_vms:
|
||||||
with-items: vm in <% $.filtered_vms %>
|
with-items: vm in <% $.filtered_vms %>
|
||||||
action: custom.evacuate uuid=<% $.vm.uuid %> evacuate=<% $.vm.evacuate %> on_shared_storage=<% $.on_shared_storage %>
|
action: nova.servers_evacuate server=<% $.vm %> on_shared_storage=<% $.on_shared_storage %>
|
||||||
|
|||||||
@@ -2,5 +2,8 @@
|
|||||||
"search_opts": {
|
"search_opts": {
|
||||||
"host": "compute1"
|
"host": "compute1"
|
||||||
},
|
},
|
||||||
"on_shared_storage": false
|
"on_shared_storage": false,
|
||||||
|
"flavor_extra_specs": {
|
||||||
|
"evacuation:evacuate": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user