Basic VIP management commands added to Nailgun CLI v2
Now Naigun CLI v2 supports VIP configuration management commands that allow to download and upload VIP configuration: fuel2 vip download --env 1 --ip-address-id 1 --file firstvip.yaml fuel2 vip upload --env 1 --file ip_address.yaml Partial-Bug: #1482399 Implements Blueprint: allow-any-vip Change-Id: Ib9b15bfdb7d4514919efbac2dab4416d088aa1e9
This commit is contained in:
@@ -55,6 +55,7 @@ def get_client(resource, version='v1'):
|
||||
'openstack-config': v1.openstack_config,
|
||||
'plugins': v1.plugins,
|
||||
'task': v1.task,
|
||||
'vip': v1.vip
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ class VIPAction(Action):
|
||||
fuel --env 1 vip --download --file vip.yaml
|
||||
where --file param is optional
|
||||
"""
|
||||
|
||||
env = Environment(params.env)
|
||||
vips_data = env.get_vips_data(
|
||||
ip_address_id=getattr(params, 'ip-address-id'),
|
||||
|
||||
126
fuelclient/commands/vip.py
Normal file
126
fuelclient/commands/vip.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuelclient.commands import base
|
||||
|
||||
|
||||
class VipMixIn(object):
|
||||
entity_name = 'vip'
|
||||
|
||||
@staticmethod
|
||||
def add_env_id_arg(parser):
|
||||
parser.add_argument(
|
||||
'-e',
|
||||
'--env',
|
||||
type=int,
|
||||
required=True,
|
||||
help='Environment identifier'
|
||||
)
|
||||
|
||||
|
||||
class VipDownload(VipMixIn, base.BaseCommand):
|
||||
"""Download VIPs configuration."""
|
||||
|
||||
@staticmethod
|
||||
def add_ip_address_id_arg(parser):
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--ip-address-id",
|
||||
type=int,
|
||||
default=None,
|
||||
required=False,
|
||||
help="IP address entity identifier"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def add_network_id_arg(parser):
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--network",
|
||||
type=int,
|
||||
default=None,
|
||||
required=False,
|
||||
help="Network identifier"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def add_network_role_arg(parser):
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--network-role",
|
||||
type=str,
|
||||
default=None,
|
||||
required=False,
|
||||
help="Network role string"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def add_file_arg(parser):
|
||||
parser.add_argument(
|
||||
'-f',
|
||||
'--file',
|
||||
type=str,
|
||||
required=False,
|
||||
default=None,
|
||||
help='YAML file that contains openstack configuration.'
|
||||
)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(VipDownload, self).get_parser(prog_name)
|
||||
self.add_env_id_arg(parser)
|
||||
self.add_ip_address_id_arg(parser)
|
||||
self.add_file_arg(parser)
|
||||
self.add_network_id_arg(parser)
|
||||
self.add_network_role_arg(parser)
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
vips_data_file_path = self.client.download(
|
||||
env_id=args.env,
|
||||
ip_addr_id=args.ip_address_id,
|
||||
network_id=args.network,
|
||||
network_role=args.network_role,
|
||||
file_path=args.file
|
||||
)
|
||||
|
||||
self.app.stdout.write(
|
||||
"VIP configuration for environment with id={0}"
|
||||
" downloaded to {1}".format(args.env, vips_data_file_path)
|
||||
)
|
||||
|
||||
|
||||
class VipUpload(VipMixIn, base.BaseCommand):
|
||||
"""Upload new VIPs configuration from file."""
|
||||
|
||||
@staticmethod
|
||||
def add_file_arg(parser):
|
||||
parser.add_argument(
|
||||
'-f',
|
||||
'--file',
|
||||
required=True,
|
||||
type=str,
|
||||
help='YAML file that contains openstack configuration.'
|
||||
)
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(VipUpload, self).get_parser(prog_name)
|
||||
self.add_env_id_arg(parser)
|
||||
self.add_file_arg(parser)
|
||||
return parser
|
||||
|
||||
def take_action(self, args):
|
||||
self.client.upload(env_id=args.env, file_path=args.file)
|
||||
self.app.stdout.write("VIP configuration uploaded.")
|
||||
68
fuelclient/tests/unit/v2/cli/test_vip.py
Normal file
68
fuelclient/tests/unit/v2/cli/test_vip.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from fuelclient.tests.unit.v2.cli import test_engine
|
||||
|
||||
|
||||
class TestVIPActions(test_engine.BaseCLITest):
|
||||
|
||||
def _test_cmd(self, method, cmd_line, expected_kwargs):
|
||||
self.m_get_client.reset_mock()
|
||||
self.m_client.get_filtered.reset_mock()
|
||||
self.m_client.__getattr__(method).return_value = 'vips_1.yaml'
|
||||
self.exec_command('vip {0} {1}'.format(method, cmd_line))
|
||||
self.m_get_client.assert_called_once_with('vip', mock.ANY)
|
||||
self.m_client.__getattr__(method).assert_called_once_with(
|
||||
**expected_kwargs)
|
||||
|
||||
def test_vip_download(self):
|
||||
self._test_cmd('download', '--env 1', dict(
|
||||
env_id=1,
|
||||
file_path=None,
|
||||
ip_addr_id=None,
|
||||
network_id=None,
|
||||
network_role=None))
|
||||
|
||||
def test_vip_download_with_network_id(self):
|
||||
self._test_cmd('download', '--env 1 --network 3', dict(
|
||||
env_id=1,
|
||||
file_path=None,
|
||||
ip_addr_id=None,
|
||||
network_id=3,
|
||||
network_role=None))
|
||||
|
||||
def test_vip_download_with_network_role(self):
|
||||
self._test_cmd('download', '--env 1 --network-role some/role', dict(
|
||||
env_id=1,
|
||||
file_path=None,
|
||||
ip_addr_id=None,
|
||||
network_id=None,
|
||||
network_role='some/role'))
|
||||
|
||||
def test_single_vip_download(self):
|
||||
self._test_cmd('download', '--env 1 --ip-address-id 5', dict(
|
||||
env_id=1,
|
||||
file_path=None,
|
||||
ip_addr_id=5,
|
||||
network_id=None,
|
||||
network_role=None))
|
||||
|
||||
def test_vip_upload(self):
|
||||
self._test_cmd('upload', '--env 1 --file vips_1.yaml', dict(
|
||||
env_id=1,
|
||||
file_path='vips_1.yaml'))
|
||||
66
fuelclient/tests/unit/v2/lib/test_vip.py
Normal file
66
fuelclient/tests/unit/v2/lib/test_vip.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import yaml
|
||||
|
||||
import fuelclient
|
||||
from fuelclient.tests.unit.v1.test_vip_action import MANY_VIPS_YAML
|
||||
from fuelclient.tests.unit.v2.lib import test_api
|
||||
|
||||
|
||||
class TestVipFacade(test_api.BaseLibTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVipFacade, self).setUp()
|
||||
|
||||
self.version = 'v1'
|
||||
self.env_id = 42
|
||||
self.res_uri = (
|
||||
'/api/{version}/clusters/{env_id}'
|
||||
'/network_configuration/ips/vips/'.format(
|
||||
version=self.version, env_id=self.env_id))
|
||||
|
||||
self.client = fuelclient.get_client('vip', self.version)
|
||||
|
||||
def test_vip_upload(self):
|
||||
expected_body = yaml.load(MANY_VIPS_YAML)
|
||||
matcher = self.m_request.put(self.res_uri, json=expected_body)
|
||||
|
||||
m_open = mock.mock_open(read_data=MANY_VIPS_YAML)
|
||||
with mock.patch('fuelclient.cli.serializers.open',
|
||||
m_open, create=True):
|
||||
with mock.patch('fuelclient.objects.environment.os') as env_os:
|
||||
env_os.path.exists.return_value = True
|
||||
self.client.upload(self.env_id, 'vips_1.yaml')
|
||||
|
||||
self.assertTrue(matcher.called)
|
||||
self.assertEqual(expected_body, matcher.last_request.json())
|
||||
|
||||
def test_vip_download(self):
|
||||
expected_body = yaml.load(MANY_VIPS_YAML)
|
||||
matcher = self.m_request.get(self.res_uri, json=expected_body)
|
||||
|
||||
m_open = mock.mock_open()
|
||||
with mock.patch('fuelclient.cli.serializers.open',
|
||||
m_open, create=True):
|
||||
self.client.download(self.env_id)
|
||||
|
||||
self.assertTrue(matcher.called)
|
||||
|
||||
written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0])
|
||||
expected_yaml = yaml.safe_load(MANY_VIPS_YAML)
|
||||
self.assertEqual(written_yaml, expected_yaml)
|
||||
@@ -17,8 +17,9 @@ from fuelclient.v1 import fuelversion
|
||||
from fuelclient.v1 import network_group
|
||||
from fuelclient.v1 import node
|
||||
from fuelclient.v1 import openstack_config
|
||||
from fuelclient.v1 import task
|
||||
from fuelclient.v1 import plugins
|
||||
from fuelclient.v1 import task
|
||||
from fuelclient.v1 import vip
|
||||
|
||||
# Please keeps the list in alphabetical order
|
||||
__all__ = ('environment',
|
||||
@@ -27,4 +28,5 @@ __all__ = ('environment',
|
||||
'node',
|
||||
'openstack_config',
|
||||
'plugins',
|
||||
'task',)
|
||||
'task',
|
||||
'vip')
|
||||
|
||||
54
fuelclient/v1/vip.py
Normal file
54
fuelclient/v1/vip.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuelclient.cli.serializers import Serializer
|
||||
from fuelclient import objects
|
||||
from fuelclient.v1 import base_v1
|
||||
|
||||
|
||||
class VipClient(base_v1.BaseV1Client):
|
||||
|
||||
_entity_wrapper = objects.Environment
|
||||
|
||||
@staticmethod
|
||||
def download(env_id, ip_addr_id=None, network_id=None,
|
||||
network_role=None, file_path=None):
|
||||
|
||||
env = objects.Environment(env_id)
|
||||
vips_data = env.get_vips_data(
|
||||
ip_address_id=ip_addr_id,
|
||||
network=network_id,
|
||||
network_role=network_role
|
||||
)
|
||||
vips_data_file_path = env.write_vips_data_to_file(
|
||||
vips_data,
|
||||
file_path=file_path,
|
||||
serializer=Serializer()
|
||||
)
|
||||
return vips_data_file_path
|
||||
|
||||
@staticmethod
|
||||
def upload(env_id, file_path):
|
||||
env = objects.Environment(env_id)
|
||||
vips_data = env.read_vips_data_from_file(
|
||||
file_path=file_path,
|
||||
serializer=Serializer()
|
||||
)
|
||||
env.set_vips_data(vips_data)
|
||||
|
||||
|
||||
def get_client():
|
||||
return VipClient()
|
||||
@@ -62,6 +62,8 @@ fuelclient =
|
||||
openstack-config_upload=fuelclient.commands.openstack_config:OpenstackConfigUpload
|
||||
openstack-config_download=fuelclient.commands.openstack_config:OpenstackConfigDownload
|
||||
openstack-config_execute=fuelclient.commands.openstack_config:OpenstackConfigExecute
|
||||
vip_upload=fuelclient.commands.vip:VipUpload
|
||||
vip_download=fuelclient.commands.vip:VipDownload
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
|
||||
Reference in New Issue
Block a user