Pluggable protection provider doc

Change-Id: I64dce168322cf607951bada5ac0eb19f80c4b09e
This commit is contained in:
Saggi Mizrahi 2015-12-29 18:27:32 +02:00
parent 70a97bea74
commit ef71a5b311
6 changed files with 274 additions and 1 deletions

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="370px" style="width:612px;height:370px;" version="1.1" viewBox="0 0 612 370" width="612px">
<defs>
<filter height="300%" id="f1" width="300%" x="-1" y="-1">
<feGaussianBlur result="blurOut" stdDeviation="2.0" />
<feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0" />
<feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3" />
<feBlend in="SourceGraphic" in2="blurOut3" mode="normal" />
</filter>
</defs>
<g>
<text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacingAndGlyphs" textLength="175" x="223" y="16.708">Smaug Protectables</text>
<polygon fill="#DDDDDD" points="43.5,28.9531,43.5,104.1406,576.5,104.1406,576.5,28.9531,43.5,28.9531" style="stroke: #000000; stroke-width: 1.0;" />
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="474" x="49.5" y="46.9482">This file contains the dependecy between protectables in the default</text>
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="514" x="49.5" y="63.2451">distribution of Smaug. The arrows, similar to inheritance point to the parent</text>
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="521" x="49.5" y="79.542">since Protectables define what types they depend on so this reflects who is</text>
<text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="216" x="49.5" y="95.8389">responsible for the connection.</text>
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="120" x="6" y="321.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="114" x="9" y="337.2793">OS::Glance::Image</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="7" x2="125" y1="345.1094" y2="345.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="7" x2="125" y1="353.1094" y2="353.1094" />
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="110" x="90" y="221.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="104" x="93" y="237.2793">OS::Nova::Server</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="91" x2="199" y1="245.1094" y2="245.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="91" x2="199" y1="253.1094" y2="253.1094" />
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="140" x="183" y="121.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="134" x="186" y="137.2793">OS::Keystone::Project</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="184" x2="322" y1="145.1094" y2="145.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="184" x2="322" y1="153.1094" y2="153.1094" />
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="125" x="175.5" y="321.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="119" x="178.5" y="337.2793">OS::Cinder::Volume</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="176.5" x2="299.5" y1="345.1094" y2="345.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="176.5" x2="299.5" y1="353.1094" y2="353.1094" />
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="146" x="306" y="221.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="140" x="309" y="237.2793">OS::Neutron::Topology</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="307" x2="451" y1="245.1094" y2="245.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="307" x2="451" y1="253.1094" y2="253.1094" />
<rect fill="#FEFECE" filter="url(#f1)" height="39.9688" style="stroke: #A80036; stroke-width: 1.5;" width="116" x="487" y="221.1406" />
<text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="110" x="490" y="237.2793">OS::Manila::Share</text>
<line style="stroke: #A80036; stroke-width: 1.5;" x1="488" x2="602" y1="245.1094" y2="245.1094" />
<line style="stroke: #A80036; stroke-width: 1.5;" x1="488" x2="602" y1="253.1094" y2="253.1094" />
<path d="M116.496,277.4996 C104.7183,292.1104 91.5229,308.4793 81.5754,320.8192 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="111.39,272.6798,129.392,261.5022,122.29,281.4662,111.39,272.6798" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M163.291,160.0376 C129.059,171.5966 93.2034,190.4656 72,221.1406 C51.416,250.9196 56.1704,295.5937 61.2398,320.883 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="161.414,153.2916,182.585,154.1916,165.474,166.6906,161.414,153.2916" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M177.204,276.0761 C191.403,291.0385 207.572,308.0769 219.664,320.8192 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="172.063,280.8282,163.374,261.5022,182.219,271.1911,172.063,280.8282" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M250.003,181.6976 C246.806,223.8996 241.875,288.9852 239.449,321.008 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="243.044,180.9006,251.534,161.4866,257.004,181.9576,243.044,180.9006" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M217.053,174.7586 C200.12,190.1246 180.51,207.9186 166.027,221.0606 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="212.405,169.5246,231.92,161.2686,221.813,179.8926,212.405,169.5246" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M293.425,173.5816 C313.517,189.2086 337.139,207.5816 354.469,221.0606 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="289.083,179.0726,277.593,161.2686,297.678,168.0216,289.083,179.0726" style="stroke: #A80036; stroke-width: 1.0;" />
<path d="M328.634,167.5246 C378.412,184.2306 442.531,205.7506 488.013,221.0146 " fill="none" style="stroke: #A80036; stroke-width: 1.0;" />
<polygon fill="none" points="326.38,174.1516,309.647,161.1526,330.835,160.8796,326.38,174.1516" style="stroke: #A80036; stroke-width: 1.0;" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,26 @@
@startuml
title Smaug Protectables
hide circle
legend top
This file contains the dependecy between protectables in the default
distribution of Smaug. The arrows, similar to inheritance point to the parent
since Protectables define what types they depend on so this reflects who is
responsible for the connection.
endlegend
class OS::Glance::Image extends OS::Nova::Server, OS::Keystone::Project
class OS::Cinder::Volume extends OS::Nova::Server, OS::Keystone::Project
class OS::Nova::Server extends OS::Keystone::Project
class OS::Keystone::Project
class OS::Neutron::Topology extends OS::Keystone::Project
class OS::Manila::Share extends OS::Keystone::Project
@enduml

View File

@ -31,9 +31,10 @@ Spec Template
.. toctree::
:maxdepth: 3
bank-plugin-lease
pluggable_protection_provider
skeleton
template
bank-plugin-lease
Indices and tables

View File

@ -0,0 +1,126 @@
@startuml
title Pluggable Protection Provider
class ResourceType extends String {
}
class Resource {
+type: ResourceType
+id: UUID
}
class ResourceGraphNode {
resource: Resource
dependent_resources: []ResourceGraphNode
}
ResourceGraphNode "1" o- "0..*" ResourceGraphNode
class ResourceGraphWalker {
+constructor(sources: []ResourceGraphNode)
+add_listener(listener: ResourceGraphWalkerListener)
+walk()
}
ResourceGraphWalker -- ResourceGraphWalkerListener
interface ResourceGraphWalkerListener {
on_node_enter(node: ResourceGraphNode, is_first_visit: boolean)
on_node_exit(node: ResourceGraphNode, is_first_visit: boolean)
}
ResourceGraphNode *- Resource
class ProtectableRegistry {
+ {static} fetch_dependant_resources(resource: Resource): []Resource
+ {static} register(resource_type: ResourceType, protectable: Protectable)
+ {static} list_resources(resource_type: ResourceType): [] Resource
}
ProtectableRegistry --> Resource: <<creates>>
ProtectableRegistry "1" *- "*" Protectable
interface Protectable {
+ possible_parent_types(resource_type: ResourceType): []ResourceType
+ fetch_child_resources(resource: Resource): []Resource
+ list_resources(resource_type: ResourceType): []Resource
}
Resource *- ResourceType
enum Operation {
protect
start
suspend
restore
delete
}
class Context {
+plan: ProtectionPlan
+operation: Operation
+parameters: dict
+resource: ResourceGraphNode
+bank_section: BankSection
+is_first_visit: boolean
+task_builder: TaskBuilder
}
interface BankPlugin {
}
interface BankSection extends BankPluginInterface {
is_writeable(): bool
}
Context *-- TaskBuilder
Context *-- BankSection
interface Task {
}
note left of Task
Opaque object
end note
interface TaskBuilder {
add_task(target: function, args=collection): Task
link_tasks(a: Task, b: Task)
}
TaskBuilder --> Task: Creates
Context -- Operation
interface ProtectionPlugin {
..metadata functions..
get_supported_resources_types(): []ResourceType
..graph walk functions..
+on_resource_start(context: Context)
+on_resource_end(context: Context)
..schema functions..
+get_options_schema(resource_type: ResourceType)
+get_saved_info_schema(resource_type: ResourceType)
+get_restore_schema(resource_type: ResourceType)
+get_saved_info(metadata_store: MetadataStore, resource: Resource)
}
ProtectionPlugin -- Context
interface ProtectionProvider {
}
class PluggableProtectionProvider extends ProtectionProvider {
-plugins: [ResourceType]ProtectionPlugin
}
PluggableProtectionProvider *-- "1..*" ProtectionPlugin: Uses for functionality
PluggableProtectionProvider -> ResourceGraphWalker: uses it to iterate over graph
ResourceGraphWalker - ResourceGraphNode
@enduml

View File

@ -0,0 +1,62 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==========================================
Pluggable Protection Provider
==========================================
https://blueprints.launchpad.net/smaug/+spec/operation-engine-design
Problem Description
===================
Even though we allow each provider to be implemented in any way it pleases we
foresee that most providers will want to be able share code between them.
We would also like for a user to be able to easily extend the ProtectionProvider
that will be provided by default.
Proposed Change
===============
As as solution we propose the *Pluggable Protection Provider*.
The *Pluggable Protection Provider* will be the reference implementation
protection provider. It's purpose is to be fully pluggable and extandable so
that only extream use cases will need to implement their own Protection Provider
from scratch.
The protection provider will contain internally a map between any registered
*Protectable* and a corrosponding *Protection Plugin*. When the pluggable
protection provider is asked to perform an action, it will walk over the
graph and pass a context object to the appropriate plugin whenever a node is
encountered.
The resource graph is traversed in with DFS. When a node is first encountered
the protection manager gets the plugin for the appropriate resource type, builds
a context and passes it to the plugins `get_pre_task()` method. The plugin can
return any tasks that it wants added to the task list. When all of a node
childrens have been visited the `get_pre_task()` is called. The task returned
from this method will also be added to the task list but is also guranteed to
execute after all the child node's tasks have finished. Any of the methods can
return `None` if they don't want any action performed.
After the entire grap has been traversed the Protection Provider will return
the task lists which will be queued and than executed according to the
executor's policy. When all the tasks are done the operation is considered
complete.
This scheme decouples the tree structure form the task execution. A plugin that
handles multiple resources or that aggregates mutiple resources to one task can
use this mechanism to only return tasks when appropriate for it's scheme.
.. image:: https://raw.githubusercontent.com/openstack/smaug/master/doc/images/pluggable_protection_provider.svg
:alt: Smaug
:align: center
References
==========
1. `Class Diagram Source <http://raw.githubusercontent.com/openstack/smaug/master/doc/images/specs/pluggable_protection_provider.pu>`_
2. `Dependency graph building algorithm <https://docs.google.com/document/d/1Mkd9RgUVdiRL6iei8Nqzzx4xteKIcd-yjMLEkV4Jc9s/edit#>`_