diff --git a/senlinclient/plugin.py b/senlinclient/plugin.py index 544d0d6b..a56ee84d 100644 --- a/senlinclient/plugin.py +++ b/senlinclient/plugin.py @@ -24,7 +24,7 @@ LOG = logging.getLogger(__name__) DEFAULT_CLUSTERING_API_VERSION = '1' API_VERSION_OPTION = 'os_clustering_api_version' API_NAME = 'clustering' -CURRENT_API_VERSION = '1.12' +CURRENT_API_VERSION = '1.13' def _make_key(service_type, key): diff --git a/senlinclient/tests/functional/profiles/cirros_basic.yaml b/senlinclient/tests/functional/profiles/cirros_basic.yaml index e4825c96..29ddc2eb 100644 --- a/senlinclient/tests/functional/profiles/cirros_basic.yaml +++ b/senlinclient/tests/functional/profiles/cirros_basic.yaml @@ -2,7 +2,7 @@ type: os.nova.server version: 1.0 properties: flavor: 1 - image: "cirros-0.3.5-x86_64-disk.img" + image: "cirros-0.4.0-x86_64-disk" networks: - network: private metadata: diff --git a/senlinclient/tests/functional/test_nodes.py b/senlinclient/tests/functional/test_nodes.py index 5e407b37..4a8559c3 100644 --- a/senlinclient/tests/functional/test_nodes.py +++ b/senlinclient/tests/functional/test_nodes.py @@ -22,7 +22,7 @@ class NodeTest(base.OpenStackClientTestBase): self.assertTableStruct(node_list, ['id', 'name', 'index', 'status', 'cluster_id', 'physical_id', 'profile_name', 'created_at', - 'updated_at']) + 'updated_at', 'tainted']) def test_node_create(self): name = self.name_generate() @@ -39,8 +39,10 @@ class NodeTest(base.OpenStackClientTestBase): new_name = self.name_generate() pf_new = self.profile_create(new_name) role = 'master' - cmd = ('cluster node update --name %s --role %s --profile %s %s' - % (new_name, role, pf_new['id'], n1['id'])) + tainted = 'True' + cmd = ('cluster node update --name %s --role %s --profile %s ' + '--tainted %s %s' + % (new_name, role, pf_new['id'], tainted, n1['id'])) self.openstack(cmd) self.wait_for_status(n1['id'], 'ACTIVE', 'node', 120) raw_node = self.openstack('cluster node show %s' % n1['id']) @@ -48,6 +50,7 @@ class NodeTest(base.OpenStackClientTestBase): self.assertEqual(node_data['name'], new_name) self.assertNotEqual(node_data['name'], old_name) self.assertEqual(node_data['role'], role) + self.assertEqual(node_data['tainted'], tainted) self.assertEqual(node_data['profile_id'], pf_new['id']) self.node_delete(new_name) self.addCleanup(self.profile_delete, pf['id']) diff --git a/senlinclient/tests/unit/v1/test_node.py b/senlinclient/tests/unit/v1/test_node.py index bbe472c1..0a88b0f9 100644 --- a/senlinclient/tests/unit/v1/test_node.py +++ b/senlinclient/tests/unit/v1/test_node.py @@ -30,7 +30,8 @@ class TestNode(fakes.TestClusteringv1): class TestNodeList(TestNode): columns = ['id', 'name', 'index', 'status', 'cluster_id', - 'physical_id', 'profile_name', 'created_at', 'updated_at'] + 'physical_id', 'profile_name', 'created_at', 'updated_at', + 'tainted'] defaults = { 'cluster_id': None, @@ -60,6 +61,7 @@ class TestNodeList(TestNode): role=None, status="ACTIVE", status_reason="Creation succeeded", + tainted=True, updated_at=None, user_id="5e5bf8027826429c96af157f68dc9072" ) @@ -160,6 +162,7 @@ class TestNodeShow(TestNode): role=None, status="ACTIVE", status_reason="Creation succeeded", + tainted=True, updated_at="2015-03-04T04:58:27", user_id="5e5bf8027826429c96af157f68dc9072" ) @@ -275,7 +278,8 @@ class TestNodeUpdate(TestNode): "nk2": "nv2", }, "profile_id": "new_profile", - "role": "new_role" + "role": "new_role", + "tainted": True } def setUp(self): @@ -298,6 +302,7 @@ class TestNodeUpdate(TestNode): role="master", status="INIT", status_reason="Initializing", + tainted=False, updated_at=None, user_id="5e5bf8027826429c96af157f68dc9072" ) @@ -310,7 +315,7 @@ class TestNodeUpdate(TestNode): def test_node_update_defaults(self): arglist = ['--name', 'new_node', '--metadata', 'nk1=nv1;nk2=nv2', '--profile', 'new_profile', '--role', 'new_role', - '0df0931b'] + '--tainted', 'True', '0df0931b'] parsed_args = self.check_parser(self.cmd, arglist, []) self.cmd.take_action(parsed_args) self.mock_client.update_node.assert_called_with( diff --git a/senlinclient/v1/node.py b/senlinclient/v1/node.py index 8a2fafe3..cef86803 100644 --- a/senlinclient/v1/node.py +++ b/senlinclient/v1/node.py @@ -86,7 +86,8 @@ class ListNode(command.Lister): senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'index', 'status', 'cluster_id', - 'physical_id', 'profile_name', 'created_at', 'updated_at'] + 'physical_id', 'profile_name', 'created_at', 'updated_at', + 'tainted'] queries = { 'cluster_id': parsed_args.cluster, 'sort': parsed_args.sort, @@ -254,6 +255,14 @@ class UpdateNode(command.ShowOne): "can clean metadata "), action='append' ) + parser.add_argument( + '--tainted', + metavar='', + help=_("Whether the node should be marked as tainted. " + "If true, this node will be selected first for the next" + "cluster scale-in operation.") + + ) parser.add_argument( 'node', metavar='', @@ -278,6 +287,12 @@ class UpdateNode(command.ShowOne): 'metadata': senlin_utils.format_parameters(parsed_args.metadata), } + if parsed_args.tainted is not None: + attrs['tainted'] = strutils.bool_from_string( + parsed_args.tainted, + strict=True, + ) + senlin_client.update_node(node.id, **attrs) return _show_node(senlin_client, node.id)