diff --git a/distributedcloud/dcmanager/api/controllers/v1/peer_group_association.py b/distributedcloud/dcmanager/api/controllers/v1/peer_group_association.py index f4c849234..d13d8e09f 100644 --- a/distributedcloud/dcmanager/api/controllers/v1/peer_group_association.py +++ b/distributedcloud/dcmanager/api/controllers/v1/peer_group_association.py @@ -31,7 +31,6 @@ from dcmanager.rpc import client as rpc_client CONF = cfg.CONF LOG = logging.getLogger(__name__) -PEER_GROUP_PRIMARY_PRIORITY = 0 MIN_PEER_GROUP_ASSOCIATION_PRIORITY = 1 MAX_PEER_GROUP_ASSOCIATION_PRIORITY = 65536 ASSOCIATION_SYNC_STATUS_LIST = \ @@ -191,9 +190,9 @@ class PeerGroupAssociationsController(restcomm.GenericPathController): pecan.abort(httpclient.BAD_REQUEST, _('Invalid peer_group_priority')) - if (peer_group.group_priority == PEER_GROUP_PRIMARY_PRIORITY and + if (peer_group.group_priority == consts.PEER_GROUP_PRIMARY_PRIORITY and peer_group_priority is None) or ( - peer_group.group_priority > PEER_GROUP_PRIMARY_PRIORITY and + peer_group.group_priority > consts.PEER_GROUP_PRIMARY_PRIORITY and peer_group_priority is not None): pecan.abort(httpclient.BAD_REQUEST, _('Peer Group Association create is not allowed when ' @@ -201,7 +200,7 @@ class PeerGroupAssociationsController(restcomm.GenericPathController): 'and it is required when the subcloud peer group ' 'priority is 0.')) - is_primary = peer_group.group_priority == PEER_GROUP_PRIMARY_PRIORITY + is_primary = peer_group.group_priority == consts.PEER_GROUP_PRIMARY_PRIORITY # only one combination of peer_group_id + system_peer_id can exists association = None diff --git a/distributedcloud/dcmanager/api/controllers/v1/phased_subcloud_deploy.py b/distributedcloud/dcmanager/api/controllers/v1/phased_subcloud_deploy.py index 10727aa18..27b8744f0 100644 --- a/distributedcloud/dcmanager/api/controllers/v1/phased_subcloud_deploy.py +++ b/distributedcloud/dcmanager/api/controllers/v1/phased_subcloud_deploy.py @@ -309,6 +309,17 @@ class PhasedSubcloudDeployController(object): pecan.abort(400, _('Subcloud prestage is ongoing %s') % subcloud.prestage_status) + # If the subcloud belongs to a peer group, ensure that + # it's not being configured in a secondary site. + if subcloud.peer_group_id is not None: + peer_group = utils.subcloud_peer_group_get_by_ref( + context, str(subcloud.peer_group_id)) + if peer_group is not None: + if peer_group.group_priority != consts.PEER_GROUP_PRIMARY_PRIORITY: + pecan.abort(400, + _('Subcloud can only be configured in' + ' its primary site.')) + psd_common.populate_payload_with_pre_existing_data( payload, subcloud, SUBCLOUD_CONFIG_GET_FILE_CONTENTS) diff --git a/distributedcloud/dcmanager/common/consts.py b/distributedcloud/dcmanager/common/consts.py index 501d33c65..23d8afebc 100644 --- a/distributedcloud/dcmanager/common/consts.py +++ b/distributedcloud/dcmanager/common/consts.py @@ -461,6 +461,8 @@ PEER_GROUP_MIGRATING = 'migrating' PEER_GROUP_MIGRATION_COMPLETE = 'complete' PEER_GROUP_MIGRATION_NONE = 'none' +PEER_GROUP_PRIMARY_PRIORITY = 0 + # Peer group association type ASSOCIATION_TYPE_PRIMARY = 'primary' ASSOCIATION_TYPE_NON_PRIMARY = 'non-primary' diff --git a/distributedcloud/dcmanager/tests/unit/api/v1/controllers/test_phased_subcloud_deploy.py b/distributedcloud/dcmanager/tests/unit/api/v1/controllers/test_phased_subcloud_deploy.py index 9a3509cce..f223da350 100644 --- a/distributedcloud/dcmanager/tests/unit/api/v1/controllers/test_phased_subcloud_deploy.py +++ b/distributedcloud/dcmanager/tests/unit/api/v1/controllers/test_phased_subcloud_deploy.py @@ -28,6 +28,8 @@ from dcmanager.tests.unit.api.v1.controllers.test_subclouds import \ from dcmanager.tests.unit.api.v1.controllers.test_subclouds import \ TestSubcloudPost from dcmanager.tests.unit.common import fake_subcloud +from dcmanager.tests.unit.manager.test_system_peer_manager import \ + TestSystemPeerManager from dcmanager.tests import utils FAKE_URL = '/v1.0/phased-subcloud-deploy' @@ -345,6 +347,48 @@ class TestSubcloudDeployConfig(testroot.DCManagerApiTest): str(subcloud.id) + '/configure', headers=FAKE_HEADERS, params=data) + def test_configure_primary_subcloud_peer_group(self): + data_install = copy.copy(FAKE_SUBCLOUD_INSTALL_VALUES) + data_install.pop('software_version') + + fake_password = \ + (base64.b64encode('testpass'.encode("utf-8"))).decode('ascii') + data = {'sysadmin_password': fake_password} + + self.mock_rpc_client().subcloud_deploy_config.return_value = True + self.mock_get_request_data.return_value = data + + # Create a subcloud and add it to SPG with primary priority + peer_group = TestSystemPeerManager.create_subcloud_peer_group_static( + self.ctx, + group_priority=consts.PEER_GROUP_PRIMARY_PRIORITY, + peer_group_name='SubcloudPeerGroup1') + + subcloud = TestSystemPeerManager.create_subcloud_with_pg_static( + self.ctx, + peer_group_id=peer_group.id, + name='subcloud1', + data_install=json.dumps(data_install)) + + response = self.app.patch_json(FAKE_URL + '/' + str(subcloud.id) + + '/configure', + headers=FAKE_HEADERS, + params=data) + self.mock_rpc_client().subcloud_deploy_config.assert_called_once_with( + mock.ANY, subcloud.id, data, initial_deployment=True) + self.assertEqual(response.status_int, 200) + + # Change the SPG as if it was on peer site + db_api.subcloud_peer_group_update( + self.ctx, + peer_group.id, + group_priority=consts.PEER_GROUP_PRIMARY_PRIORITY + 1) + + six.assertRaisesRegex(self, webtest.app.AppError, "400 *", + self.app.patch_json, FAKE_URL + '/' + + str(subcloud.id) + '/configure', + headers=FAKE_HEADERS, params=data) + class TestSubcloudDeployInstall(testroot.DCManagerApiTest): def setUp(self):