Added commands to operate on vms

* added command to spawn vms on env
* added command to list and add vms for node

Change-Id: I41c71b842332e783d2656d03785c0be6632b1523
DocImpact
Implements: blueprint reduced-footprint
This commit is contained in:
Kamil Sambor
2015-07-09 13:19:24 +02:00
parent f35a361775
commit 6e24282c7a
12 changed files with 164 additions and 0 deletions

View File

@@ -254,3 +254,19 @@ class EnvDeploy(EnvMixIn, base.BaseCommand):
'has been started.\n'.format(t=task_id, e=parsed_args.id)
self.app.stdout.write(msg)
class EnvSpawnVms(EnvMixIn, base.BaseCommand):
"""Provision specified environment."""
def get_parser(self, prog_name):
parser = super(EnvSpawnVms, self).get_parser(prog_name)
parser.add_argument('id',
type=int,
help='Id of the environment to be provision.')
return parser
def take_action(self, parsed_args):
return self.client.spawn_vms(parsed_args.id)

View File

@@ -14,6 +14,7 @@
from fuelclient.commands import base
from fuelclient.common import data_utils
from fuelclient import utils
class NodeMixIn(object):
@@ -77,3 +78,39 @@ class NodeShow(NodeMixIn, base.BaseShowCommand):
# TODO(romcheg): network_data mostly never fits the screen
# 'network_data',
'manufacturer')
class NodeVmsList(NodeMixIn, base.BaseShowCommand):
"""Show list vms for node."""
columns = ('vms_conf',)
def take_action(self, parsed_args):
data = self.client.get_node_vms_conf(parsed_args.id)
data = data_utils.get_display_data_single(self.columns, data)
return (self.columns, data)
class NodeCreateVMsConf(NodeMixIn, base.BaseCommand):
"""Create vms config in metadata for selected node."""
def get_parser(self, prog_name):
parser = super(NodeCreateVMsConf, self).get_parser(prog_name)
parser.add_argument('id', type=int,
help='Id of the {0}.'.format(self.entity_name))
parser.add_argument(
'--conf',
type=str,
required=True,
nargs='+',
help='JSONs with VMs configuration',
)
return parser
def take_action(self, parsed_args):
confs = utils.parse_to_list_of_dicts(parsed_args.conf)
data = self.client.node_vms_create(parsed_args.id, confs)
msg = "{0}".format(data)
self.app.stdout.write(msg)

View File

@@ -451,3 +451,7 @@ class Environment(BaseObject):
resp = self.connection.get_request_raw(url, params=params)
resp.raise_for_status()
return resp.text
def spawn_vms(self):
url = 'clusters/{0}/spawn_vms/'.format(self.id)
return self.connection.put_request(url, {})

View File

@@ -121,6 +121,14 @@ class Node(BaseObject):
def delete(self):
self.connection.delete_request(self.instance_api_path.format(self.id))
def node_vms_create(self, config):
url = "nodes/{0}/vms_conf/".format(self.id)
return self.connection.put_request(url, config)
def get_node_vms_conf(self):
url = "nodes/{0}/vms_conf/".format(self.id)
return self.connection.get_request(url)
class NodeCollection(object):

View File

@@ -122,3 +122,11 @@ class TestEnvCommand(test_engine.BaseCLITest):
self.m_get_client.assert_called_once_with('environment', mock.ANY)
self.m_client.upgrade.assert_called_once_with(10, 15)
def test_env_spawn_vms(self):
env_id = 10
args = 'env spawn-vms {0}'.format(env_id)
self.exec_command(args)
self.m_get_client.assert_called_once_with('environment', mock.ANY)
self.m_client.spawn_vms.assert_called_once_with(env_id)

View File

@@ -54,3 +54,27 @@ class TestNodeCommand(test_engine.BaseCLITest):
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.get_by_id.assert_called_once_with(node_id)
def test_node_vms_conf_list(self):
node_id = 42
args = 'node list-vms-conf {node_id}'.format(node_id=node_id)
self.exec_command(args)
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.get_node_vms_conf.assert_called_once_with(node_id)
def test_node_vms_conf_create(self):
vms_conf = """{"id":2} {"id":3}"""
config = [{'id': 2},
{'id': 3}]
node_id = 42
args = "node create-vms-conf {0} --conf {1}".format(
node_id,
vms_conf)
self.exec_command(args)
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.node_vms_create.assert_called_once_with(node_id, config)

View File

@@ -158,3 +158,11 @@ class TestEnvFacade(test_api.BaseLibTest):
for assignment in self.session_adapter.last_request.json():
# Check whether all assignments are expected
self.assertIn(assignment, expected_body)
def test_env_spawn_vms(self):
env_id = 10
expected_uri = '/api/v1/clusters/{0}/spawn_vms/'.format(env_id)
self.client.spawn_vms(env_id)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)

View File

@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import requests_mock as rm
import fuelclient
@@ -44,3 +45,26 @@ class TestNodeFacade(test_api.BaseLibTest):
self.assertEqual(rm.GET, self.session_adapter.last_request.method)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
def test_node_vms_list(self):
node_id = 42
expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id)
self.client.get_node_vms_conf(node_id)
self.assertEqual(rm.GET, self.session_adapter.last_request.method)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
def test_node_vms_create(self):
config = [{'id': 1, 'opt2': 'val2'},
{'id': 2, 'opt4': 'val4'}]
node_id = 42
expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id)
expected_body = json.dumps(config)
self.client.node_vms_create(node_id, config)
self.assertEqual(rm.PUT, self.session_adapter.last_request.method)
self.assertEqual(expected_uri, self.session_adapter.last_request.path)
self.assertEqual(expected_body, self.session_adapter.last_request.body)

View File

@@ -16,6 +16,7 @@
import glob
import io
import json
import os
import subprocess
import yaml
@@ -129,3 +130,22 @@ def file_exists(path):
:returns: True if file is exist, Flase if is not
"""
return os.path.lexists(path)
def parse_to_list_of_dicts(str_list):
"""Parse list of json strings to dictionaries
:param list: list of dicts and json string
:returns" list of dictionaries
"""
dict_list = []
for json_str in str_list:
if not isinstance(json_str, dict):
try:
json_str = json.loads(json_str)
except Exception:
raise error.BadDataException(
'Not valid JSON data: {0}'.format(json_str))
dict_list.append(json_str)
return dict_list

View File

@@ -88,6 +88,10 @@ class EnvironmentClient(base_v1.BaseV1Client):
return deploy_task.id
def spawn_vms(self, environment_id):
env = self._entity_wrapper(obj_id=environment_id)
return env.spawn_vms()
def get_client():
return EnvironmentClient()

View File

@@ -28,6 +28,14 @@ class NodeClient(base_v1.BaseV1Client):
return result
def get_node_vms_conf(self, node_id):
node = self._entity_wrapper(node_id)
return node.get_node_vms_conf()
def node_vms_create(self, node_id, config):
node = self._entity_wrapper(node_id)
return node.node_vms_create(config)
def get_client():
return NodeClient()

View File

@@ -36,8 +36,11 @@ fuelclient =
env_upgrade=fuelclient.commands.environment:EnvUpgrade
env_deploy=fuelclient.commands.environment:EnvDeploy
env_add_nodes=fuelclient.commands.environment:EnvAddNodes
env_spawn-vms=fuelclient.commands.environment:EnvSpawnVms
node_list=fuelclient.commands.node:NodeList
node_show=fuelclient.commands.node:NodeShow
node_list-vms-conf=fuelclient.commands.node:NodeVmsList
node_create-vms-conf=fuelclient.commands.node:NodeCreateVMsConf
task_list=fuelclient.commands.task:TaskList
task_show=fuelclient.commands.task:TaskShow