Add node attributes commannds to CLI v1
Add commands that allow to download and upload node attributes
for specified nodes:
fuel node --node-id 1 --attributes --upload [--dir DIR]
fuel node --node-id 1 --attributes --download [--dir DIR]
Change-Id: Ic368f393ed59e88631080ec8c3b3a7c0e29f6913
Implements: blueprint support-numa-cpu-pinning
This commit is contained in:
@@ -42,6 +42,7 @@ class NodeAction(Action):
|
||||
Args.get_list_arg("List all nodes."),
|
||||
Args.get_set_arg("Set role for specific node."),
|
||||
Args.get_delete_arg("Delete specific node from environment."),
|
||||
Args.get_attributes_arg("Node attributes."),
|
||||
Args.get_network_arg("Node network configuration."),
|
||||
Args.get_disk_arg("Node disk configuration."),
|
||||
Args.get_deploy_arg("Deploy specific nodes."),
|
||||
@@ -88,6 +89,7 @@ class NodeAction(Action):
|
||||
("skip", self.execute_tasks),
|
||||
("end", self.execute_tasks),
|
||||
("start", self.execute_tasks),
|
||||
("attributes", self.node_attributes),
|
||||
(None, self.list)
|
||||
)
|
||||
|
||||
@@ -375,3 +377,36 @@ class NodeAction(Action):
|
||||
"Hostname for node with id {0} has been changed to {1}."
|
||||
.format(node.id, params.hostname)
|
||||
)
|
||||
|
||||
@check_all("node")
|
||||
@check_any("upload", "download")
|
||||
def node_attributes(self, params):
|
||||
"""Download node attributes for specified node:
|
||||
fuel node --node-id 1 --attributes --download [--dir download-dir]
|
||||
|
||||
Upload node attributes for specified node
|
||||
fuel node --node-id 1 --attributes --upload [--dir upload-dir]
|
||||
|
||||
"""
|
||||
node = self._get_one_node(params)
|
||||
if params.upload:
|
||||
data = node.read_attribute(
|
||||
'attributes', params.dir, serializer=self.serializer)
|
||||
node.update_node_attributes(data)
|
||||
self.serializer.print_to_output(
|
||||
{},
|
||||
"Attributes for node {0} were uploaded."
|
||||
.format(node.id))
|
||||
elif params.download:
|
||||
attributes = node.get_node_attributes()
|
||||
file_path = node.write_attribute(
|
||||
'attributes', attributes,
|
||||
params.dir, serializer=self.serializer)
|
||||
self.serializer.print_to_output(
|
||||
{},
|
||||
"Attributes for node {0} were written to {1}"
|
||||
.format(node.id, file_path))
|
||||
|
||||
else:
|
||||
raise error.ArgumentException(
|
||||
"--upload or --download action should be specified.")
|
||||
|
||||
@@ -24,6 +24,7 @@ class Node(BaseObject):
|
||||
|
||||
class_api_path = "nodes/"
|
||||
instance_api_path = "nodes/{0}/"
|
||||
attributes_api_path = "nodes/{0}/attributes/"
|
||||
|
||||
attributes_urls = {
|
||||
"interfaces": ("interfaces", "default_assignment"),
|
||||
@@ -74,6 +75,17 @@ class Node(BaseObject):
|
||||
self.get_attribute_default_url(attributes_type)
|
||||
)
|
||||
|
||||
def get_node_attributes(self):
|
||||
return self.connection.get_request(
|
||||
self.attributes_api_path.format(self.id)
|
||||
)
|
||||
|
||||
def update_node_attributes(self, data):
|
||||
return self.connection.put_request(
|
||||
self.attributes_api_path.format(self.id),
|
||||
data
|
||||
)
|
||||
|
||||
def get_attribute(self, attributes_type):
|
||||
return self.connection.get_request(
|
||||
self.get_attribute_url(attributes_type)
|
||||
|
||||
@@ -55,8 +55,9 @@ class TestHandlers(base.BaseTestCase):
|
||||
|
||||
def test_node_action(self):
|
||||
help_msg = ["fuel node [-h] [--env ENV]",
|
||||
"[--list | --set | --delete | --network | --disk |"
|
||||
" --deploy | --hostname HOSTNAME | --name NAME |"
|
||||
"[--list | --set | --delete | --attributes |"
|
||||
" --network | --disk | --deploy |"
|
||||
" --hostname HOSTNAME | --name NAME |"
|
||||
" --delete-from-db | --provision]", "-h", "--help", " -s",
|
||||
"--default", " -d", "--download", " -u",
|
||||
"--upload", "--dir", "--node", "--node-id", " -r",
|
||||
|
||||
@@ -15,11 +15,17 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli.actions import node
|
||||
from fuelclient.cli import error
|
||||
from fuelclient.cli import serializers
|
||||
from fuelclient.tests.unit.v1 import base
|
||||
|
||||
NODE_ATTRIBUTES_DATA = {
|
||||
'test_attribute': 'value'
|
||||
}
|
||||
|
||||
|
||||
class TestNodeSetAction(base.UnitTestCase):
|
||||
|
||||
@@ -83,3 +89,51 @@ class TestNodeSetAction(base.UnitTestCase):
|
||||
"Hostname for node with id {0} has been changed to {1}.".format(
|
||||
self.node_id, new_hostname)
|
||||
)
|
||||
|
||||
|
||||
class TestNodeActions(base.UnitTestCase):
|
||||
def setUp(self):
|
||||
super(TestNodeActions, self).setUp()
|
||||
self.node_id = 1
|
||||
|
||||
@mock.patch('fuelclient.objects.node.os.mkdir', mock.Mock())
|
||||
def test_attributes_download(self):
|
||||
mget = self.m_request.get(
|
||||
'/api/v1/nodes/{0}/attributes/'.format(self.node_id),
|
||||
json=NODE_ATTRIBUTES_DATA)
|
||||
|
||||
cmd = ['fuel', 'node', '--node', '1', '--attributes',
|
||||
'--dir', '/fake/dir/', '--download']
|
||||
m_open = mock.mock_open()
|
||||
with mock.patch('fuelclient.cli.serializers.open', m_open,
|
||||
create=True):
|
||||
self.execute(cmd)
|
||||
|
||||
self.assertTrue(mget.called)
|
||||
m_open.assert_called_once_with(
|
||||
'/fake/dir/node_{0}/attributes.yaml'.format(self.node_id),
|
||||
mock.ANY)
|
||||
serializer = serializers.Serializer()
|
||||
m_open().write.assert_called_once_with(
|
||||
serializer.serialize(NODE_ATTRIBUTES_DATA))
|
||||
|
||||
@mock.patch('fuelclient.objects.node.os.path.exists',
|
||||
mock.Mock(return_value=True))
|
||||
def test_attributes_upload(self):
|
||||
mput = self.m_request.put(
|
||||
'/api/v1/nodes/{0}/attributes/'.format(self.node_id),
|
||||
json=NODE_ATTRIBUTES_DATA)
|
||||
|
||||
cmd = ['fuel', 'node', '--node', '1', '--attributes',
|
||||
'--dir', '/fake/dir', '--upload']
|
||||
m_open = mock.mock_open(read_data=yaml.safe_dump(NODE_ATTRIBUTES_DATA))
|
||||
with mock.patch('fuelclient.cli.serializers.open', m_open,
|
||||
create=True):
|
||||
self.execute(cmd)
|
||||
|
||||
self.assertTrue(mput.called)
|
||||
m_open.assert_called_once_with(
|
||||
'/fake/dir/node_{0}/attributes.yaml'.format(self.node_id),
|
||||
mock.ANY)
|
||||
self.assertEqual(mput.last_request.json(), NODE_ATTRIBUTES_DATA)
|
||||
m_open().read.assert_called_once_with()
|
||||
|
||||
Reference in New Issue
Block a user