Add node attributes commannds to CLI v2
Add commands that allow to download and upload node attributes
for specified nodes:
fuel node attributes-download [--dir DIR] NODE_ID
fuel node attributes-upload [--dir DIR] NODE_ID
Change-Id: I347f3bc201926784e453d25bffe898090ba82e49
Implements: blueprint support-numa-cpu-pinning
This commit is contained in:
@@ -263,3 +263,44 @@ class NodeLabelDelete(NodeMixIn, base.BaseCommand):
|
||||
msg = "Labels have been deleted on nodes: {0} \n".format(
|
||||
','.join(data))
|
||||
self.app.stdout.write(msg)
|
||||
|
||||
|
||||
class NodeAttributesDownload(NodeMixIn, base.BaseCommand):
|
||||
"""Download node attributes."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(NodeAttributesDownload, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'id', type=int, help='Node ID')
|
||||
parser.add_argument(
|
||||
'--dir', type=str, help='Directory to save attributes')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
file_path = self.client.download_attributes(
|
||||
parsed_args.id, parsed_args.dir)
|
||||
self.app.stdout.write(
|
||||
"Attributes for node {0} were written to {1}"
|
||||
.format(parsed_args.id, file_path))
|
||||
|
||||
|
||||
class NodeAttributesUpload(NodeMixIn, base.BaseCommand):
|
||||
"""Upload node attributes."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(NodeAttributesUpload, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'id', type=int, help='Node ID')
|
||||
parser.add_argument(
|
||||
'--dir', type=str, help='Directory to read attributes from')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.client.upload_attributes(parsed_args.id, parsed_args.dir)
|
||||
self.app.stdout.write(
|
||||
"Attributes for node {0} were uploaded."
|
||||
.format(parsed_args.id))
|
||||
|
||||
@@ -270,3 +270,19 @@ class TestNodeCommand(test_engine.BaseCLITest):
|
||||
self.m_get_client.assert_called_once_with('node', mock.ANY)
|
||||
self.m_client.delete_labels_for_nodes.assert_called_once_with(
|
||||
labels=labels_expected, node_ids=node_ids)
|
||||
|
||||
def test_node_attributes_download(self):
|
||||
args = 'node attributes-download 42'
|
||||
|
||||
self.exec_command(args)
|
||||
|
||||
self.m_get_client.assert_called_once_with('node', mock.ANY)
|
||||
self.m_client.download_attributes.assert_called_once_with(42, None)
|
||||
|
||||
def test_node_attributes_upload(self):
|
||||
args = 'node attributes-upload 42'
|
||||
|
||||
self.exec_command(args)
|
||||
|
||||
self.m_get_client.assert_called_once_with('node', mock.ANY)
|
||||
self.m_client.upload_attributes.assert_called_once_with(42, None)
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import yaml
|
||||
|
||||
import fuelclient
|
||||
from fuelclient.cli import error
|
||||
from fuelclient.cli import serializers
|
||||
from fuelclient.objects import base as base_object
|
||||
from fuelclient.tests.unit.v2.lib import test_api
|
||||
from fuelclient.tests import utils
|
||||
@@ -334,3 +336,49 @@ class TestNodeFacade(test_api.BaseLibTest):
|
||||
node_id = 42
|
||||
self.assertRaises(error.BadDataException,
|
||||
self.client.update, node_id, status=42)
|
||||
|
||||
@mock.patch('fuelclient.objects.node.os.mkdir', mock.Mock())
|
||||
def test_node_attributes_download(self):
|
||||
node_id = 42
|
||||
expected_uri = self.get_object_uri(
|
||||
self.res_uri, node_id, '/attributes/')
|
||||
fake_attributes = {
|
||||
'attribute_name': 'attribute_value'
|
||||
}
|
||||
|
||||
m_get = self.m_request.get(expected_uri, json=fake_attributes)
|
||||
|
||||
m_open = mock.mock_open()
|
||||
with mock.patch('fuelclient.cli.serializers.open',
|
||||
m_open, create=True):
|
||||
self.client.download_attributes(node_id, directory='/fake/dir')
|
||||
|
||||
self.assertTrue(m_get.called)
|
||||
m_open.assert_called_once_with(
|
||||
'/fake/dir/node_{0}/attributes.yaml'.format(node_id), mock.ANY)
|
||||
serializer = serializers.Serializer()
|
||||
m_open().write.assert_called_once_with(
|
||||
serializer.serialize(fake_attributes))
|
||||
|
||||
@mock.patch('fuelclient.objects.node.os.path.exists',
|
||||
mock.Mock(return_value=True))
|
||||
def test_node_attribute_upload(self):
|
||||
node_id = 42
|
||||
expected_uri = self.get_object_uri(
|
||||
self.res_uri, node_id, '/attributes/')
|
||||
fake_attributes = {
|
||||
'attribute_name': 'attribute_value'
|
||||
}
|
||||
|
||||
m_put = self.m_request.put(expected_uri, json=fake_attributes)
|
||||
|
||||
m_open = mock.mock_open(read_data=yaml.safe_dump(fake_attributes))
|
||||
with mock.patch('fuelclient.cli.serializers.open',
|
||||
m_open, create=True):
|
||||
self.client.upload_attributes(node_id, directory='/fake/dir')
|
||||
|
||||
self.assertTrue(m_put.called)
|
||||
m_open.assert_called_once_with(
|
||||
'/fake/dir/node_{0}/attributes.yaml'.format(node_id), mock.ANY)
|
||||
self.assertEqual(m_put.last_request.json(), fake_attributes)
|
||||
m_open().read.assert_called_once_with()
|
||||
|
||||
@@ -162,6 +162,17 @@ class NodeClient(base_v1.BaseV1Client):
|
||||
|
||||
return data_to_return
|
||||
|
||||
def download_attributes(self, node_id, directory=None):
|
||||
node = self._entity_wrapper(node_id)
|
||||
attributes = node.get_node_attributes()
|
||||
return node.write_attribute(
|
||||
'attributes', attributes, directory=directory)
|
||||
|
||||
def upload_attributes(self, node_id, directory=None):
|
||||
node = self._entity_wrapper(node_id)
|
||||
attributes = node.read_attribute('attributes', directory=directory)
|
||||
node.update_node_attributes(attributes)
|
||||
|
||||
def _check_label(self, labels, item):
|
||||
checking_list = []
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ fuelclient =
|
||||
network-template_delete=fuelclient.commands.network_template:NetworkTemplateDelete
|
||||
network-template_download=fuelclient.commands.network_template:NetworkTemplateDownload
|
||||
network-template_upload=fuelclient.commands.network_template:NetworkTemplateUpload
|
||||
node_attributes-download=fuelclient.commands.node:NodeAttributesDownload
|
||||
node_attributes-upload=fuelclient.commands.node:NodeAttributesUpload
|
||||
node_create-vms-conf=fuelclient.commands.node:NodeCreateVMsConf
|
||||
node_label_delete=fuelclient.commands.node:NodeLabelDelete
|
||||
node_label_list=fuelclient.commands.node:NodeLabelList
|
||||
|
||||
Reference in New Issue
Block a user