From d946438a343bac1f0c31a6a14ed6333d4db166f7 Mon Sep 17 00:00:00 2001 From: tengqm Date: Mon, 17 Jul 2017 21:31:10 -0400 Subject: [PATCH] Support to node-adopt and node-adopt-preview This adds support to adopt and adopt-preview API added to Senlin API (microversion 1.7) Change-Id: Ic3a11a094ba36d6875953cf10da11aae563e10a4 --- doc/source/users/proxies/cluster.rst | 1 + openstack/cluster/v1/_proxy.py | 32 +++++++++++++++++++ openstack/cluster/v1/node.py | 18 +++++++++++ openstack/tests/unit/cluster/v1/test_node.py | 28 ++++++++++++++++ openstack/tests/unit/cluster/v1/test_proxy.py | 22 +++++++++++++ 5 files changed, 101 insertions(+) diff --git a/doc/source/users/proxies/cluster.rst b/doc/source/users/proxies/cluster.rst index 9951478f..db7eec00 100644 --- a/doc/source/users/proxies/cluster.rst +++ b/doc/source/users/proxies/cluster.rst @@ -125,6 +125,7 @@ Node Operations .. automethod:: openstack.cluster.v1._proxy.Proxy.recover_node .. automethod:: openstack.cluster.v1._proxy.Proxy.perform_operation_on_node + .. automethod:: openstack.cluster.v1._proxy.Proxy.adopt_node .. automethod:: openstack.cluster.v1._proxy.Proxy.node_operation diff --git a/openstack/cluster/v1/_proxy.py b/openstack/cluster/v1/_proxy.py index 44778a62..29ef4b6a 100644 --- a/openstack/cluster/v1/_proxy.py +++ b/openstack/cluster/v1/_proxy.py @@ -722,6 +722,38 @@ class Proxy(proxy2.BaseProxy): obj = self._get_resource(_node.Node, node) return obj.recover(self._session, **params) + def adopt_node(self, preview=False, **attrs): + """Adopting an existing resource as a node. + + :param preview: A boolean indicating whether this is a "preview" + operation which means only the profile to be used is returned + rather than creating a node object using that profile. + :param dict attrs: Keyword parameters for node adoption. Valid + parameters include: + + * type: (Required) A string containing the profile type and + version to be used for node adoption. For example, + ``os.nova.sever-1.0``. + * identity: (Required) A string including the name or ID of an + OpenStack resource to be adopted as a Senlin node. + * name: (Optional) The name of of node to be created. Omitting + this parameter will have the node named automatically. + * snapshot: (Optional) A boolean indicating whether a snapshot + of the target resource should be created if possible. Default + is False. + * metadata: (Optional) A dictionary of arbitrary key-value pairs + to be associated with the adopted node. + * overrides: (Optional) A dictionary of key-value pairs to be used + to override attributes derived from the target resource. + + :returns: The result of node adoption. If `preview` is set to False + (default), returns a :class:`~openstack.cluster.v1.node.Node` + object, otherwise a Dict is returned containing the profile to + be used for the new node. + """ + node = self._get_resource(_node.Node, None) + return node.adopt(self._session, preview=preview, **attrs) + @utils.deprecated(deprecated_in="0.9.14", removed_in="1.0", details="Use perform_operation_on_node instead") def node_operation(self, node, operation, **params): diff --git a/openstack/cluster/v1/node.py b/openstack/cluster/v1/node.py index 3b8bfa26..fe442d0a 100644 --- a/openstack/cluster/v1/node.py +++ b/openstack/cluster/v1/node.py @@ -125,6 +125,24 @@ class Node(resource.Resource): json={operation: params}) return resp.json() + def adopt(self, session, preview=False, **params): + """Adopt a node for management. + + :param session: A session object used for sending request. + :param preview: A boolean indicating whether the adoption is a + preview. A "preview" does not create the node object. + :param dict params: A dict providing the details of a node to be + adopted. + """ + path = "adopt-preview" if preview else "adopt" + url = utils.urljoin(self.base_path, path) + resp = session.post(url, endpoint_filter=self.service, json=params) + if preview: + return resp.json() + + self._translate_response(resp) + return self + class NodeDetail(Node): base_path = '/nodes/%(node_id)s?show_details=True' diff --git a/openstack/tests/unit/cluster/v1/test_node.py b/openstack/tests/unit/cluster/v1/test_node.py index aefffd03..a6225823 100644 --- a/openstack/tests/unit/cluster/v1/test_node.py +++ b/openstack/tests/unit/cluster/v1/test_node.py @@ -104,6 +104,34 @@ class TestNode(testtools.TestCase): sess.post.assert_called_once_with(url, endpoint_filter=sot.service, json={'dance': {'style': 'tango'}}) + def test_adopt_preview(self): + sot = node.Node.new() + resp = mock.Mock() + resp.headers = {} + resp.json = mock.Mock(return_value={"foo": "bar"}) + sess = mock.Mock() + sess.post = mock.Mock(return_value=resp) + + res = sot.adopt(sess, True, param="value") + self.assertEqual({"foo": "bar"}, res) + sess.post.assert_called_once_with("nodes/adopt-preview", + endpoint_filter=sot.service, + json={"param": "value"}) + + def test_adopt(self): + sot = node.Node.new() + resp = mock.Mock() + resp.headers = {} + resp.json = mock.Mock(return_value={"foo": "bar"}) + sess = mock.Mock() + sess.post = mock.Mock(return_value=resp) + + res = sot.adopt(sess, False, param="value") + self.assertEqual(sot, res) + sess.post.assert_called_once_with("nodes/adopt", + endpoint_filter=sot.service, + json={"param": "value"}) + class TestNodeDetail(testtools.TestCase): diff --git a/openstack/tests/unit/cluster/v1/test_proxy.py b/openstack/tests/unit/cluster/v1/test_proxy.py index 3609b59f..ec6b55c3 100644 --- a/openstack/tests/unit/cluster/v1/test_proxy.py +++ b/openstack/tests/unit/cluster/v1/test_proxy.py @@ -391,6 +391,28 @@ class TestClusterProxy(test_proxy_base2.TestProxyBase): method_args=["FAKE_NODE"]) mock_get.assert_called_once_with(node.Node, "FAKE_NODE") + @mock.patch.object(proxy_base.BaseProxy, '_get_resource') + def test_node_adopt(self, mock_get): + mock_node = node.Node.new() + mock_get.return_value = mock_node + self._verify("openstack.cluster.v1.node.Node.adopt", + self.proxy.adopt_node, + method_kwargs={"preview": False, "foo": "bar"}, + expected_kwargs={"preview": False, "foo": "bar"}) + + mock_get.assert_called_once_with(node.Node, None) + + @mock.patch.object(proxy_base.BaseProxy, '_get_resource') + def test_node_adopt_preview(self, mock_get): + mock_node = node.Node.new() + mock_get.return_value = mock_node + self._verify("openstack.cluster.v1.node.Node.adopt", + self.proxy.adopt_node, + method_kwargs={"preview": True, "foo": "bar"}, + expected_kwargs={"preview": True, "foo": "bar"}) + + mock_get.assert_called_once_with(node.Node, None) + @deprecation.fail_if_not_removed @mock.patch.object(proxy_base.BaseProxy, '_get_resource') def test_node_operation(self, mock_get):