From 3c782b55822d0ebe52faaae80638715662bed8a0 Mon Sep 17 00:00:00 2001 From: "Yuanbin.Chen" Date: Mon, 22 Jan 2018 09:37:35 +0800 Subject: [PATCH] Add clustering guides cluster file, examples cluster code Change-Id: I7a86398b86a4317100b454f1bd45a8eafc6ae4d4 Signed-off-by: Yuanbin.Chen --- doc/source/user/guides/clustering/cluster.rst | 177 +++++++++++++++++- examples/clustering/cluster.py | 172 +++++++++++++++++ 2 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 examples/clustering/cluster.py diff --git a/doc/source/user/guides/clustering/cluster.rst b/doc/source/user/guides/clustering/cluster.rst index b4772ef33..7ee5134e0 100644 --- a/doc/source/user/guides/clustering/cluster.rst +++ b/doc/source/user/guides/clustering/cluster.rst @@ -15,4 +15,179 @@ Managing Clusters ================= -.. TODO(Qiming): Implement this guide +Clusters are first-class citizens in Senlin service design. A cluster is +defined as a collection of homogeneous objects. The "homogeneous" here means +that the objects managed (aka. Nodes) have to be instantiated from the same +"profile type". + + +List Clusters +~~~~~~~~~~~~~ + +To examine the list of receivers: + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: list_cluster + +When listing clusters, you can specify the sorting option using the ``sort`` +parameter and you can do pagination using the ``limit`` and ``marker`` +parameters. + +Full example: `manage cluster`_ + + +Create Cluster +~~~~~~~~~~~~~~ + +When creating a cluster, you will provide a dictionary with keys and values +according to the cluster type referenced. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: create_cluster + +Optionally, you can specify a ``metadata`` keyword argument that contains some +key-value pairs to be associated with the cluster. + +Full example: `manage cluster`_ + + +Get Cluster +~~~~~~~~~~~ + +To get a cluster based on its name or ID: + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: get_cluster + +Full example: `manage cluster`_ + + +Find Cluster +~~~~~~~~~~~~ + +To find a cluster based on its name or ID: + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: find_cluster + +Full example: `manage cluster`_ + + +Update Cluster +~~~~~~~~~~~~~~ + +After a cluster is created, most of its properties are immutable. Still, you +can update a cluster's ``name`` and/or ``params``. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: update_cluster + +Full example: `manage cluster`_ + + +Delete Cluster +~~~~~~~~~~~~~~ + +A cluster can be deleted after creation, When there are nodes in the cluster, +the Senlin engine will launch a process to delete all nodes from the cluster +and destroy them before deleting the cluster object itself. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: delete_cluster + + +Cluster Add Nodes +~~~~~~~~~~~~~~~~~ + +Add some existing nodes into the specified cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_add_nodes + + +Cluster Del Nodes +~~~~~~~~~~~~~~~~~ + +Remove nodes from specified cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_del_nodes + + +Cluster Replace Nodes +~~~~~~~~~~~~~~~~~~~~~ + +Replace some existing nodes in the specified cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_replace_nodes + + +Cluster Scale Out +~~~~~~~~~~~~~~~~~ + +Inflate the size of a cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_scale_out + + +Cluster Scale In +~~~~~~~~~~~~~~~~ + +Shrink the size of a cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_scale_in + + +Cluster Resize +~~~~~~~~~~~~~~ + +Resize of cluster. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_resize + + +Cluster Policy Attach +~~~~~~~~~~~~~~~~~~~~~ + +Once a policy is attached (bound) to a cluster, it will be +enforced when related actions are performed on that cluster, +unless the policy is (temporarily) disabled on the cluster + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_attach_policy + + +Cluster Policy Detach +~~~~~~~~~~~~~~~~~~~~~ + +Once a policy is attached to a cluster, it can be detached +from the cluster at user's request. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: cluster_detach_policy + + +Cluster Check +~~~~~~~~~~~~~ + +Check cluster health status, Cluster members can be check. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: check_cluster + + +Cluster Recover +~~~~~~~~~~~~~~~ + +To restore a specified cluster, members in the cluster will be checked. + +.. literalinclude:: ../../examples/clustering/cluster.py + :pyobject: recover_cluster + + +.. _manage cluster: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/clustering/cluster.py + diff --git a/examples/clustering/cluster.py b/examples/clustering/cluster.py new file mode 100644 index 000000000..a4d46ce08 --- /dev/null +++ b/examples/clustering/cluster.py @@ -0,0 +1,172 @@ +# 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. + +""" +Managing policies in the Cluster service. + +For a full guide see +https://developer.openstack.org/sdks/python/openstacksdk/user/guides/cluster.html +""" + +CLUSTER_NAME = "Test_Cluster" +CLUSTER_ID = "47d808e5-ce75-4a1e-bfd2-4ed4639e8640" +PROFILE_ID = "b0e3a680-e270-4eb8-9361-e5c9503fba0a" +NODE_ID = "dd803d4a-015d-4223-b15f-db29bad3146c" +POLICY_ID = "c0e3a680-e270-4eb8-9361-e5c9503fba00" + + +def list_cluster(conn): + print("List clusters:") + + for cluster in conn.clustering.clusters(): + print(cluster.to_dict()) + + for cluster in conn.clustering.clusters(sort='name:asc'): + print(cluster.to_dict()) + + +def create_cluster(conn): + print("Create cluster:") + + spec = { + "name": CLUSTER_NAME, + "profile_id": PROFILE_ID, + "min_size": 0, + "max_size": -1, + "desired_capacity": 1, + } + + cluster = conn.clustering.create_cluster(**spec) + print(cluster.to_dict()) + + +def get_cluster(conn): + print("Get cluster:") + + cluster = conn.clustering.get_cluster(CLUSTER_ID) + print(cluster.to_dict()) + + +def find_cluster(conn): + print("Find cluster:") + + cluster = conn.clustering.find_cluster(CLUSTER_ID) + print(cluster.to_dict()) + + +def update_cluster(conn): + print("Update cluster:") + + spec = { + "name": "Test_Cluster001", + "profile_id": "c0e3a680-e270-4eb8-9361-e5c9503fba0a", + "profile_only": True, + } + cluster = conn.clustering.update_cluster(CLUSTER_ID, **spec) + print(cluster.to_dict()) + + +def delete_cluster(conn): + print("Delete cluster:") + + conn.clustering.delete_cluster(CLUSTER_ID) + print("Cluster deleted.") + + # cluster support force delete + conn.clustering.delete_cluster(CLUSTER_ID, False, True) + print("Cluster deleted") + + +def cluster_add_nodes(conn): + print("Add nodes to cluster:") + + node_ids = [NODE_ID] + res = conn.clustering.cluster_add_nodes(CLUSTER_ID, node_ids) + print(res.to_dict()) + + +def cluster_del_nodes(conn): + print("Remove nodes from a cluster:") + + node_ids = [NODE_ID] + res = conn.clustering.cluster_del_nodes(CLUSTER_ID, node_ids) + print(res.to_dict()) + + +def cluster_replace_nodes(conn): + print("Replace the nodes in a cluster with specified nodes:") + + old_node = NODE_ID + new_node = "cd803d4a-015d-4223-b15f-db29bad3146c" + spec = { + old_node: new_node + } + res = conn.clustering.cluster_replace_nodes(CLUSTER_ID, **spec) + print(res.to_dict()) + + +def cluster_scale_out(conn): + print("Inflate the size of a cluster:") + + res = conn.clustering.cluster_scale_out(CLUSTER_ID, 1) + print(res.to_dict()) + + +def cluster_scale_in(conn): + print("Shrink the size of a cluster:") + + res = conn.clustering.cluster_scale_in(CLUSTER_ID, 1) + print(res.to_dict()) + + +def cluster_resize(conn): + print("Resize of cluster:") + + spec = { + 'min_size': 1, + 'max_size': 6, + 'adjustment_type': 'EXACT_CAPACITY', + 'number': 2 + } + res = conn.clustering.cluster_resize(CLUSTER_ID, **spec) + print(res.to_dict()) + + +def cluster_attach_policy(conn): + print("Attach policy to a cluster:") + + spec = {'enabled': True} + res = conn.clustering.cluster_attach_policy(CLUSTER_ID, POLICY_ID, + **spec) + print(res.to_dict()) + + +def cluster_detach_policy(conn): + print("Detach a policy from a cluster:") + + res = conn.clustering.cluster_detach_policy(CLUSTER_ID, POLICY_ID) + print(res.to_dict()) + + +def check_cluster(conn): + print("Check cluster:") + + res = conn.clustering.check_cluster(CLUSTER_ID) + print(res.to_dict()) + + +def recover_cluster(conn): + print("Recover cluster:") + + spec = {'check': True} + res = conn.clustering.recover_cluster(CLUSTER_ID, **spec) + print(res.to_dict())