Add 'fuel2 env remove nodes' command

Release new 'env remove nodes' command in fuel2
to support remove nodes procedure from specific
environment (cluster):

  fuel2 env remove nodes [-h] -e ENV
            (-n NODES [NODES ...] | --nodes-all)

DocImpact
Closes-Bug: 1603440

Change-Id: Ibc14966996ae046307299348f62f758980d31ace
(cherry picked from commit a245303ef5)
This commit is contained in:
tivaliy
2016-07-15 16:43:06 +03:00
committed by Vitalii Kulanov
parent 67d8c693a6
commit fd75673f67
6 changed files with 118 additions and 1 deletions

View File

@@ -193,6 +193,43 @@ class EnvAddNodes(EnvMixIn, base.BaseCommand):
r=parsed_args.roles))
class EnvRemoveNodes(EnvMixIn, base.BaseCommand):
"""Removes nodes from an environment."""
def get_parser(self, prog_name):
parser = super(EnvRemoveNodes, self).get_parser(prog_name)
parser.add_argument('-e',
'--env',
type=int,
required=True,
help='Id of the environment to remove nodes from')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-n',
'--nodes',
type=int,
nargs='+',
help='Ids of the nodes to remove.')
group.add_argument('--nodes-all',
action='store_true',
help='Remove all nodes from environment')
return parser
def take_action(self, parsed_args):
nodes = None if parsed_args.nodes_all else parsed_args.nodes
self.client.remove_nodes(environment_id=parsed_args.env,
nodes=nodes)
msg = 'Nodes were removed from the environment with id={e}\n'.format(
e=parsed_args.env)
self.app.stdout.write(msg)
class EnvDeploy(EnvMixIn, base.BaseCommand):
"""Deploys changes on the specified environment."""

View File

@@ -79,7 +79,7 @@ class Environment(BaseObject):
self.connection.get_request(
"nodes/?cluster_id={0}".format(self.id)
)
), key=attrgetter)
), key=attrgetter('id'))
def unassign_all(self):
nodes = self.get_all_nodes()

View File

@@ -158,6 +158,22 @@ class TestEnvCommand(test_engine.BaseCLITest):
roles=['compute',
'cinder'])
def test_env_remove_nodes_by_id(self):
args = 'env remove nodes -e 42 -n 24 25'
self.exec_command(args)
self.m_get_client.assert_called_once_with('environment', mock.ANY)
self.m_client.remove_nodes.assert_called_once_with(environment_id=42,
nodes=[24, 25])
def test_env_remove_nodes_all(self):
args = 'env remove nodes -e 42 --nodes-all'
self.exec_command(args)
self.m_get_client.assert_called_once_with('environment', mock.ANY)
self.m_client.remove_nodes.assert_called_once_with(environment_id=42,
nodes=None)
def test_env_update(self):
self.m_client._updatable_attributes = \
environment.EnvironmentClient._updatable_attributes

View File

@@ -212,3 +212,51 @@ class TestEnvFacade(test_api.BaseLibTest):
self.client.spawn_vms(env_id)
self.assertTrue(matcher.called)
def test_env_remove_nodes_by_id(self):
nodes = [25, 26]
env_id = 42
expected_body = []
for n in nodes:
expected_body.append({'id': n})
expected_uri = self.get_object_uri(self.res_uri,
env_id, '/unassignment/')
matcher = self.m_request.post(expected_uri, json={})
self.client.remove_nodes(env_id, nodes=nodes)
self.assertTrue(matcher.called)
for unassignment in matcher.last_request.json():
# Check whether all unassignments are expected
self.assertIn(unassignment, expected_body)
def test_env_remove_nodes_all(self):
nodes = [24, 25, 26]
env_id = 42
expected_body = []
for n in nodes:
expected_body.append({'id': n})
fake_nodes = [utils.get_fake_node(node_name='node_' + str(n),
node_id=n,
cluster=env_id) for n in nodes]
expected_uri = self.get_object_uri(self.res_uri,
env_id, '/unassignment/')
matcher_get = self.m_request.get(
'/api/v1/nodes/?cluster_id={}'.format(env_id),
json=fake_nodes
)
matcher_post = self.m_request.post(expected_uri, json={})
self.client.remove_nodes(env_id)
self.assertTrue(matcher_get.called)
self.assertTrue(matcher_post.called)
for unassignment in matcher_post.last_request.json():
# Check whether all unassignments are expected
self.assertIn(unassignment, expected_body)

View File

@@ -65,6 +65,21 @@ class EnvironmentClient(base_v1.BaseV1Client):
env.assign(nodes, roles)
def remove_nodes(self, environment_id, nodes=None):
"""Remove nodes from environment. If nodes are empty list then
all nodes will be removed
:param environment_id: Id of specific environment (cluster)
:type environment_id: int
:param nodes: List of node ids that should be removed
:type nodes: list
"""
env = self._entity_wrapper(obj_id=environment_id)
if nodes is not None:
env.unassign(nodes)
else:
env.unassign_all()
def deploy_changes(self, environment_id, dry_run=False):
env = self._entity_wrapper(obj_id=environment_id)

View File

@@ -35,6 +35,7 @@ fuelclient =
env_deploy=fuelclient.commands.environment:EnvDeploy
env_list=fuelclient.commands.environment:EnvList
env_redeploy=fuelclient.commands.environment:EnvRedeploy
env_remove_nodes=fuelclient.commands.environment:EnvRemoveNodes
env_show=fuelclient.commands.environment:EnvShow
env_spawn-vms=fuelclient.commands.environment:EnvSpawnVms
env_update=fuelclient.commands.environment:EnvUpdate