def test_raise_exception_when_plugin_overlap_another_plugin_volumes(self): plugin_name = 'test_plugin_4' volumes_metadata = { 'volumes_roles_mapping': { plugin_name: [ {'allocate_size': 'min', 'id': plugin_name} ] }, 'volumes': [ {'id': 'test_plugin_2', 'type': 'vg'}, {'id': plugin_name, 'type': 'vg'} ] } self.env.create_plugin( cluster=self.cluster, name=plugin_name, package_version='3.0.0', fuel_version=['7.0'], volumes_metadata=volumes_metadata ) expected_message = ( 'Plugin test_plugin_4-0.1.0 is overlapping with plugin ' 'test_plugin_2-0.1.0 by introducing the same volume ' 'with id "test_plugin_2"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_volumes_metadata(self.cluster)
def patch_attributes(cls, instance, data): PluginManager.process_cluster_attributes(instance, data['editable']) instance.attributes.editable = dict_merge( instance.attributes.editable, data['editable']) cls.add_pending_changes(instance, "attributes") cls.get_network_manager(instance).update_restricted_networks(instance) db().flush()
def test_raise_exception_when_plugin_overlap_release_volumes(self): cluster = self.env.create_cluster(api=False) plugin_name = 'test_plugin_3' volumes_metadata = { 'volumes_roles_mapping': { plugin_name: [ {'allocate_size': 'min', 'id': plugin_name} ] }, 'volumes': [ {'id': 'os', 'type': 'vg'}, {'id': plugin_name, 'type': 'vg'} ] } self.env.create_plugin( cluster=cluster, name=plugin_name, package_version='3.0.0', fuel_version=['7.0'], volumes_metadata=volumes_metadata ) expected_message = ( 'Plugin test_plugin_3-0.1.0 is overlapping with release ' 'by introducing the same volume with id "os"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_volumes_metadata(cluster)
def test_update_plugin_node_attributes(self): self.env.create_plugin( name='plugin_b', cluster=self.cluster, enabled=True, package_version='5.0.0', node_attributes_metadata={ 'section_plugin_b': { 'attr_b': {'value': 'test_b'} } }) new_attrs = PluginManager.get_plugin_node_attributes(self.node) new_attrs['plugin_a_section_1']['attr_1']['value'] = 'new_test_1' new_attrs['section_plugin_b']['attr_b']['value'] = 'new_test_b' PluginManager.update_plugin_node_attributes(new_attrs) attributes = PluginManager.get_plugin_node_attributes(self.node) for attribute in attributes: del attributes[attribute]['metadata']['node_plugin_id'] self.assertDictEqual( { 'plugin_a_section_1': { 'metadata': {'label': 'Section 1 of Plugin A', 'class': 'plugin'}, 'attr_1': {'value': 'new_test_1'}}, 'plugin_a_section_2': { 'metadata': {'class': 'plugin'}, 'attr_2': {'value': 'test_2'}}, 'section_plugin_b': { 'metadata': {'class': 'plugin'}, 'attr_b': {'value': 'new_test_b'}} }, attributes )
def test_raise_exception_when_plugin_overlap_release_component(self): release = self.env.create_release( version='2015.1-8.1', operating_system='Ubuntu', modes=[consts.CLUSTER_MODES.ha_compact], components_metadata=self.env.get_default_components()) self.env.create_plugin( name='plugin_with_components', package_version='4.0.0', fuel_version=['8.0'], releases=[{ 'repository_path': 'repositories/ubuntu', 'version': '2015.1-8.1', 'os': 'ubuntu', 'mode': ['ha'], 'deployment_scripts_path': 'deployment_scripts/'}], components_metadata=self.env.get_default_components()) expected_message = ( 'Plugin plugin_with_components is overlapping with release ' 'by introducing the same component with name ' '"hypervisor:test_hypervisor"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_components_metadata(release)
def test_raise_exception_when_plugin_overlap_another_plugin_volumes(self): plugin_name = 'test_plugin_4' volumes_metadata = { 'volumes_roles_mapping': { plugin_name: [{ 'allocate_size': 'min', 'id': plugin_name }] }, 'volumes': [{ 'id': 'test_plugin_2', 'type': 'vg' }, { 'id': plugin_name, 'type': 'vg' }] } self.env.create_plugin(api=True, cluster=self.cluster, name=plugin_name, package_version='3.0.0', fuel_version=['7.0'], volumes_metadata=volumes_metadata) expected_message = ( 'Plugin test_plugin_4-0.1.0 is overlapping with plugin ' 'test_plugin_2-0.1.0 by introducing the same volume ' 'with id "test_plugin_2"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_volumes_metadata(self.cluster)
def test_raise_exception_when_plugin_overlap_release_component(self): release = self.env.create_release( version='2015.1-8.1', operating_system='Ubuntu', modes=[consts.CLUSTER_MODES.ha_compact], components_metadata=self.env.get_default_components()) self.env.create_plugin( name='plugin_with_components', package_version='4.0.0', fuel_version=['8.0'], releases=[{ 'repository_path': 'repositories/ubuntu', 'version': '2015.1-8.1', 'os': 'ubuntu', 'mode': ['ha'], 'deployment_scripts_path': 'deployment_scripts/' }], components_metadata=self.env.get_default_components()) expected_message = ( 'Plugin plugin_with_components is overlapping with release ' 'by introducing the same component with name ' '"hypervisor:test_hypervisor"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_components_metadata(release)
def update_attributes(cls, instance, data): PluginManager.process_cluster_attributes(instance, data['editable']) for key, value in data.iteritems(): setattr(instance.attributes, key, value) cls.add_pending_changes(instance, "attributes") db().flush()
def test_raise_exception_when_plugin_overlap_release_volumes(self): cluster = self.env.create_cluster(api=False) plugin_name = 'test_plugin_3' volumes_metadata = { 'volumes_roles_mapping': { plugin_name: [ {'allocate_size': 'min', 'id': plugin_name} ] }, 'volumes': [ {'id': 'os', 'type': 'vg'}, {'id': plugin_name, 'type': 'vg'} ] } self.env.create_plugin( api=True, cluster=cluster, name=plugin_name, package_version='3.0.0', fuel_version=['7.0'], volumes_metadata=volumes_metadata ) expected_message = ( 'Plugin test_plugin_3-0.1.0 is overlapping with release ' 'by introducing the same volume with id "os"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_volumes_metadata(cluster)
def create(cls, data): """Create Cluster instance with specified parameters in DB. This includes: * creating Cluster attributes and generating default values \ (see :func:`create_attributes`) * creating NetworkGroups for Cluster * adding default pending changes (see :func:`add_pending_changes`) * if "nodes" are specified in data then they are added to Cluster \ (see :func:`update_nodes`) :param data: dictionary of key-value pairs as object fields :returns: Cluster instance """ # TODO(enchantner): fix this temporary hack in clients if "release_id" not in data: release_id = data.pop("release", None) data["release_id"] = release_id # remove read-only attribute data.pop("is_locked", None) assign_nodes = data.pop("nodes", []) enabled_editable_attributes = None if 'components' in data: enabled_core_attributes = cls.get_cluster_attributes_by_components( data['components'], data["release_id"]) data = dict_merge(data, enabled_core_attributes['cluster']) enabled_editable_attributes = enabled_core_attributes['editable'] data["fuel_version"] = settings.VERSION["release"] cluster = super(Cluster, cls).create(data) cls.create_default_group(cluster) cls.create_attributes(cluster, enabled_editable_attributes) cls.create_vmware_attributes(cluster) cls.create_default_extensions(cluster) try: cls.get_network_manager(cluster).\ create_network_groups_and_config(cluster, data) cls.add_pending_changes(cluster, consts.CLUSTER_CHANGES.attributes) cls.add_pending_changes(cluster, consts.CLUSTER_CHANGES.networks) cls.add_pending_changes(cluster, consts.CLUSTER_CHANGES.vmware_attributes) if assign_nodes: cls.update_nodes(cluster, assign_nodes) except (errors.OutOfVLANs, errors.OutOfIPs, errors.NoSuitableCIDR) as exc: raise errors.CannotCreate(exc.message) db().flush() ClusterPlugins.add_compatible_plugins(cluster) PluginManager.enable_plugins_by_components(cluster) return cluster
def create_attributes(cls, instance): """Create attributes for interface with default values. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :returns: None """ instance.attributes = cls._get_default_attributes(instance) PluginManager.add_plugin_attributes_for_interface(instance) db().flush()
def test_get_specific_version(self): versions = [ {'metadata': {'plugin_id': '1'}}, {'metadata': {'plugin_id': '2'}} ] plugin_version_attrs = PluginManager._get_specific_version( versions, '1') self.assertEqual(versions[0], plugin_version_attrs) not_existed_plugin_version_attrs = PluginManager._get_specific_version( versions, '3') self.assertEqual({}, not_existed_plugin_version_attrs)
def test_update_nic_attributes(self): new_attrs = PluginManager.get_nic_attributes(self.interface) new_attrs['plugin_a']['attr_a']['value'] = {} PluginManager.update_nic_attributes(new_attrs) attributes = PluginManager.get_nic_attributes(self.interface) del attributes['plugin_a']['metadata']['nic_plugin_id'] self.assertDictEqual( {'plugin_a': { 'attr_a': {'value': {}}, 'metadata': { 'class': 'plugin', 'label': 'Test plugin'}}}, attributes)
def POST(self): """:returns: JSONized REST object. :http: * 200 (plugins successfully synced) * 404 (plugin not found in db) * 400 (problem with parsing metadata file) """ data = self.checked_data() ids = data.get("ids", None) try: PluginManager.sync_plugins_metadata(plugin_ids=ids) except errors.ParseError as exc: raise self.http(400, msg=six.text_type(exc)) raise self.http(200)
def POST(self): """:returns: JSONized REST object. :http: * 200 (plugins successfully synced) * 404 (plugin not found in db) * 400 (problem with parsing metadata file) """ data = self.checked_data() ids = data.get('ids', None) try: PluginManager.sync_plugins_metadata(plugin_ids=ids) except errors.ParseError as exc: raise self.http(400, msg=six.text_type(exc)) raise self.http(200)
def get_default_attributes(cls, instance): """Get default attributes for interface. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :returns: dict -- Dict object of NIC attributes """ attributes = cls._get_default_attributes(instance) attributes = utils.dict_merge( attributes, PluginManager.get_nic_attributes(instance)) attributes = utils.dict_merge( attributes, PluginManager.get_nic_default_attributes(instance.node.cluster)) return attributes
def get_network_roles(cls, instance): """Method for receiving network roles for particular cluster :param instance: nailgun.db.sqlalchemy.models.Cluster instance :returns: List of network roles' descriptions """ return instance.release.network_roles_metadata + PluginManager.get_network_roles(instance)
def serialize(self): plugins = PluginManager.get_cluster_plugins_with_tasks(self.cluster) return itertools.chain( self.create_repositories(plugins), self.sync_scripts(plugins), self.deployment_tasks(plugins) )
def get_all_components(cls, instance): """Get all components related to release Due to components architecture compatible/incompatible are duplex relations. So if some component is compatible/incompatible with another the last one also should have such relation. :param instance: Release instance :type instance: Release DB instance :returns: list -- list of all components """ plugin_components = PluginManager.get_components_metadata(instance) components = copy.deepcopy(instance.components_metadata + plugin_components) # we should provide commutative property for compatible/incompatible # relations between components for comp_i, comp_j in itertools.permutations(components, 2): if cls._check_relation(comp_j, comp_i, 'incompatible'): comp_i.setdefault('incompatible', []).append({ 'name': comp_j['name'], 'message': "Not compatible with {0}".format( comp_j.get('label') or comp_j.get('name')) }) if cls._check_relation(comp_j, comp_i, 'compatible'): comp_i.setdefault('compatible', []).append({'name': comp_j['name']}) return components
def update(cls, instance, data): """Update data of native and plugin attributes for interface. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :param data: Data to update :type data: dict :returns: instance of an object (model) """ attributes = data.pop('attributes', None) if attributes: PluginManager.update_nic_attributes(attributes) instance.attributes = utils.dict_merge( instance.attributes, attributes) return super(NIC, cls).update(instance, data)
def update(cls, instance, data): """Update data of native and plugin attributes for interface. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :param data: Data to update :type data: dict :returns: instance of an object (model) """ attributes = data.pop('attributes', None) if attributes: PluginManager.update_nic_attributes(attributes) instance.attributes = utils.dict_merge(instance.attributes, attributes) return super(NIC, cls).update(instance, data)
def get_all_components(cls, instance): """Get all components related to release Due to components architecture compatible/incompatible are duplex relations. So if some component is compatible/incompatible with another the last one also should have such relation. :param instance: Release instance :type instance: Release DB instance :returns: list -- list of all components """ plugin_components = PluginManager.get_components_metadata(instance) components = copy.deepcopy( instance.components_metadata + plugin_components) # we should provide commutative property for compatible/incompatible # relations between components for comp_i, comp_j in itertools.permutations(components, 2): if cls._check_relation(comp_j, comp_i, 'incompatible'): comp_i.setdefault('incompatible', []).append({ 'name': comp_j['name'], 'message': "Not compatible with {0}".format( comp_j.get('label') or comp_j.get('name'))}) if cls._check_relation(comp_j, comp_i, 'compatible'): comp_i.setdefault('compatible', []).append({ 'name': comp_j['name']}) return components
def get_attributes(cls, instance, all_plugins_versions=False): """Get attributes for current Cluster instance. :param instance: Cluster instance :param all_plugins_versions: Get attributes of all versions of plugins :returns: dict """ try: attrs = db().query(models.Attributes).filter( models.Attributes.cluster_id == instance.id ).one() except MultipleResultsFound: raise errors.InvalidData( u"Multiple rows with attributes were found for cluster '{0}'" .format(instance.name) ) except NoResultFound: raise errors.InvalidData( u"No attributes were found for cluster '{0}'" .format(instance.name) ) attrs = dict(attrs) # Merge plugins attributes into editable ones plugin_attrs = PluginManager.get_plugins_attributes( instance, all_versions=all_plugins_versions) plugin_attrs = traverse(plugin_attrs, AttributesGenerator, { 'cluster': instance, 'settings': settings, }) attrs['editable'].update(plugin_attrs) return attrs
def validate_allowed_attributes(cls, cluster, data, force): """Validates if attributes are hot pluggable or not. :param cluster: A cluster instance :type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster :param data: Changed attributes of cluster :type data: dict :param force: Allow forcefully update cluster attributes :type force: bool :raises: errors.NotAllowed """ # TODO(need to enable restrictions check for cluster attributes[1]) # [1] https://bugs.launchpad.net/fuel/+bug/1519904 # Validates only that plugin can be installed on deployed env. # If cluster is locked we have to check which attributes # we want to change and block an entire operation if there # one with always_editable=False. if not cluster.is_locked or force: return editable_cluster = objects.Cluster.get_editable_attributes( cluster, all_plugins_versions=True) editable_request = data.get('editable', {}) for attr_name, attr_request in six.iteritems(editable_request): attr_cluster = editable_cluster.get(attr_name, {}) meta_cluster = attr_cluster.get('metadata', {}) meta_request = attr_request.get('metadata', {}) if PluginManager.is_plugin_data(attr_cluster): if meta_request['enabled']: changed_ids = [meta_request['chosen_id']] if meta_cluster['enabled']: changed_ids.append(meta_cluster['chosen_id']) changed_ids = set(changed_ids) elif meta_cluster['enabled']: changed_ids = [meta_cluster['chosen_id']] else: continue for plugin in meta_cluster['versions']: plugin_id = plugin['metadata']['plugin_id'] always_editable = plugin['metadata']\ .get('always_editable', False) if plugin_id in changed_ids and not always_editable: raise errors.NotAllowed( "Plugin '{0}' version '{1}' couldn't be changed " "after or during deployment." .format(attr_name, plugin['metadata']['plugin_version']), log_message=True ) elif not meta_cluster.get('always_editable', False): raise errors.NotAllowed( "Environment attribute '{0}' couldn't be changed " "after or during deployment.".format(attr_name), log_message=True )
def serialize(self): tasks = [] plugins = PluginManager.get_cluster_plugins_with_tasks(self.cluster) tasks.extend(self.create_repositories(plugins)) tasks.extend(self.sync_scripts(plugins)) tasks.extend(self.deployment_tasks(plugins)) return tasks
def test_get_plugin_volumes_metadata_for_cluster(self): volumes_metadata = PluginManager.get_volumes_metadata(self.cluster) expected_volumes_metadata = { 'volumes_roles_mapping': { 'test_plugin_1': [{ 'allocate_size': 'min', 'id': 'test_plugin_1' }], 'test_plugin_2': [{ 'allocate_size': 'min', 'id': 'test_plugin_2' }], }, 'volumes': [{ 'id': 'test_plugin_1', 'type': 'vg' }, { 'id': 'test_plugin_2', 'type': 'vg' }] } self.assertEqual(volumes_metadata['volumes_roles_mapping'], expected_volumes_metadata['volumes_roles_mapping']) self.assertItemsEqual(volumes_metadata['volumes'], expected_volumes_metadata['volumes'])
def test_merge_plugin_values(self): attributes = { 'test_plugin': { 'metadata': { 'class': 'plugin', 'chosen_id': 1, 'enabled': True, 'versions': [{ 'metadata': { 'plugin_id': 1 }, 'attribute_a': { 'value': 'test_a' }, 'attribute_b': { 'value': 'test_b' } }, { 'metadata': { 'plugin_id': 2 }, 'attribute_a': { 'value': 'test_a' }, 'attribute_c': { 'value': 'test_c' } }] }, 'attribute_a': { 'value': '' }, 'attribute_b': { 'value': '' } } } PluginManager.inject_plugin_attribute_values(attributes) self.assertEqual('test_a', attributes['test_plugin']['attribute_a']['value']) self.assertEqual('test_b', attributes['test_plugin']['attribute_b']['value'])
def update(cls, instance, data): """Update existing Bond with specified parameters. :param instance: object (model) instance :param data: dictionary of key-value pairs as object fields :returns: instance of an object (model) """ attributes = data.pop('attributes', None) if attributes: PluginManager.update_bond_attributes(attributes) instance.attributes = utils.dict_merge( instance.attributes, attributes) instance = super(Bond, cls).update(instance, data) instance.offloading_modes = data.get('offloading_modes', {}) return instance
def get_network_roles(cls, instance): """Method for receiving network roles for particular cluster :param instance: nailgun.db.sqlalchemy.models.Cluster instance :returns: List of network roles' descriptions """ return (instance.release.network_roles_metadata + PluginManager.get_network_roles(instance))
def get_default_attributes(cls, instance): """Get default attributes for interface. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :returns: dict -- Dict object of NIC attributes """ attributes = cls._get_default_attributes(instance) attributes = utils.dict_merge( attributes, PluginManager.get_nic_attributes(instance)) attributes = utils.dict_merge( attributes, PluginManager.get_nic_default_attributes( instance.node.cluster)) return attributes
def update(cls, instance, data): """Update existing Bond with specified parameters. :param instance: object (model) instance :param data: dictionary of key-value pairs as object fields :returns: instance of an object (model) """ attributes = data.pop('attributes', None) if attributes: PluginManager.update_bond_attributes(attributes) instance.attributes = utils.dict_merge(instance.attributes, attributes) instance = super(Bond, cls).update(instance, data) instance.offloading_modes = data.get('offloading_modes', {}) return instance
def test_get_plugins_attributes_when_cluster_is_not_locked(self): self.env.create(api=False) cluster = self.env.clusters[-1] plugin_a1 = self.env.create_plugin(name='plugin_a', version='1.0.1', cluster=cluster, enabled=False) plugin_a2 = self.env.create_plugin(name='plugin_a', version='1.0.2', is_hotpluggable=True, cluster=cluster, enabled=True) plugin_b = self.env.create_plugin(name='plugin_b', title='plugin_a_title', cluster=cluster) self.assertFalse(plugin_a1.is_hotpluggable) self.assertTrue(plugin_a2.is_hotpluggable) self.assertFalse(plugin_b.is_hotpluggable) self.assertFalse(cluster.is_locked) attributes = PluginManager.get_plugins_attributes(cluster, True, True) self.assertItemsEqual(['plugin_a', 'plugin_b'], attributes) self.assertTrue(attributes['plugin_a']['metadata']['always_editable']) self.assertItemsEqual([{ 'data': str(plugin_a1.id), 'description': '', 'label': plugin_a1.version, 'restrictions': [{ 'action': 'disable', 'condition': 'cluster:is_locked' }], }, { 'data': str(plugin_a2.id), 'description': '', 'label': plugin_a2.version }], attributes['plugin_a']['plugin_versions']['values']) self.assertEqual(str(plugin_a1.id), attributes['plugin_a']['plugin_versions']['value']) self.assertNotIn('always_editable', attributes['plugin_b']['metadata']) self.assertItemsEqual([ { 'restrictions': [{ 'action': 'disable', 'condition': 'cluster:is_locked' }], 'data': str(plugin_b.id), 'description': '', 'label': plugin_b.version, }, ], attributes['plugin_b']['plugin_versions']['values']) self.assertEqual(str(plugin_b.id), attributes['plugin_b']['plugin_versions']['value'])
def get_roles(cls, instance): """Returns a dictionary of node roles available for deployment. :param instance: cluster instance :returns: a dictionary of roles metadata """ available_roles = copy.deepcopy(instance.release.roles_metadata) available_roles.update(PluginManager.get_plugins_node_roles(instance)) return available_roles
def get_all_components(cls, instance): """Get all components related to release :param instance: Release instance :type instance: Release DB instance :returns: list -- list of all components """ plugin_components = PluginManager.get_components_metadata(instance) return instance.components_metadata + plugin_components
def get_network_roles( cls, instance, merge_policy=NetworkRoleMergePolicy()): """Method for receiving network roles for particular cluster :param instance: nailgun.db.sqlalchemy.models.Cluster instance :param merge_policy: the policy to merge same roles :returns: List of network roles' descriptions """ return PluginManager.get_network_roles(instance, merge_policy)
def test_get_nic_plugin_atributes(self): attributes = PluginManager.get_nic_attributes(self.interface) del attributes['plugin_a']['metadata']['nic_plugin_id'] self.assertDictEqual( {'plugin_a': { 'attr_a': {'value': 'test_a'}, 'metadata': { 'class': 'plugin', 'label': 'Test plugin'}}}, attributes)
def test_add_plugin_attributes_for_node(self): new_cluster_node = self.env.create_node( cluster_id=self.cluster.id, roles=['controller'] ) PluginManager.add_plugin_attributes_for_node(new_cluster_node) node_cluster_plugins = new_cluster_node.node_cluster_plugins self.assertEqual(len(node_cluster_plugins), 1) attributes = node_cluster_plugins[0].attributes self.assertDictEqual( { 'plugin_a_section_1': { 'metadata': {'label': 'Section 1 of Plugin A'}, 'attr_1': {'value': 'test_1'}}, 'plugin_a_section_2': { 'attr_2': {'value': 'test_2'}} }, attributes )
def test_get_empty_plugin_volumes_metadata_for_cluster(self): cluster = self.env.create_cluster(api=False) self.env.create_plugin(cluster=cluster, package_version='3.0.0') volumes_metadata = PluginManager.get_volumes_metadata(cluster) expected_volumes_metadata = { 'volumes_roles_mapping': {}, 'volumes': [] } self.assertEqual(volumes_metadata, expected_volumes_metadata)
def test_merge_plugin_values(self): attributes = { 'test_plugin': { 'metadata': { 'class': 'plugin', 'chosen_id': 1, 'enabled': True, 'versions': [ { 'metadata': { 'plugin_id': 1 }, 'attribute_a': { 'value': 'test_a' }, 'attribute_b': { 'value': 'test_b' } }, { 'metadata': { 'plugin_id': 2 }, 'attribute_a': { 'value': 'test_a' }, 'attribute_c': { 'value': 'test_c' } } ] }, 'attribute_a': {'value': ''}, 'attribute_b': {'value': ''} } } PluginManager.inject_plugin_attribute_values(attributes) self.assertEqual( 'test_a', attributes['test_plugin']['attribute_a']['value']) self.assertEqual( 'test_b', attributes['test_plugin']['attribute_b']['value'])
def test_get_components(self): self.env.create_plugin( name='plugin_with_components', package_version='4.0.0', fuel_version=['8.0'], components_metadata=self.env.get_default_components()) components_metadata = PluginManager.get_components_metadata( self.release) self.assertEqual( components_metadata, self.env.get_default_components())
def test_raise_exception_when_plugin_overlap_another_component(self): self.env.create_plugin( name='plugin_with_components_1', package_version='4.0.0', fuel_version=['8.0'], components_metadata=self.env.get_default_components()) self.env.create_plugin( name='plugin_with_components_2', package_version='4.0.0', fuel_version=['8.0'], components_metadata=self.env.get_default_components()) expected_message = ( 'Plugin plugin_with_components_2 is overlapping with ' 'plugin_with_components_1 by introducing the same component ' 'with name "hypervisor:test_hypervisor"') with self.assertRaisesRegexp(errors.AlreadyExists, expected_message): PluginManager.get_components_metadata(self.release)
def test_get_components(self): self.env.create_plugin( name='plugin_with_components', package_version='4.0.0', fuel_version=['8.0'], components_metadata=self.env.get_default_components()) components_metadata = PluginManager.get_components_metadata( self.release) self.assertEqual(components_metadata, self.env.get_default_components())
def test_get_empty_plugin_volumes_metadata_for_cluster(self): cluster = self.env.create_cluster(api=False) self.env.create_plugin( cluster=cluster, package_version='3.0.0' ) volumes_metadata = PluginManager.get_volumes_metadata(cluster) expected_volumes_metadata = { 'volumes_roles_mapping': {}, 'volumes': []} self.assertEqual( volumes_metadata, expected_volumes_metadata)
def get_default_attributes(cls, cluster): """Get native and plugin default attributes for bond. :param cluster: A cluster instance :type cluster: Cluster model :returns: dict -- Object of bond default attributes """ default_attributes = cluster.release.bond_attributes default_attributes = utils.dict_merge( default_attributes, PluginManager.get_bond_default_attributes(cluster)) return default_attributes
def get_attributes(cls, instance): """Get native and plugin attributes for bond. :param instance: NodeBondInterface instance :type instance: NodeBondInterface model :returns: dict -- Object of bond attributes """ attributes = copy.deepcopy(instance.attributes) attributes = utils.dict_merge( attributes, PluginManager.get_bond_attributes(instance)) return attributes
def get_attributes(cls, instance): """Get all attributes for interface. :param instance: NodeNICInterface instance :type instance: NodeNICInterface model :returns: dict -- Object of interface attributes """ attributes = copy.deepcopy(instance.attributes) attributes = utils.dict_merge( attributes, PluginManager.get_nic_attributes(instance)) return attributes
def get_default_editable_attributes(cls, instance): """Get editable attributes from release metadata :param instance: Cluster instance :returns: Dict object """ editable = instance.release.attributes_metadata.get("editable") generate_editables(editable, AttributesGenerator) # when attributes created we need to understand whether should plugin # be applied for created cluster plugin_attrs = PluginManager.get_plugin_attributes(instance) editable = dict(plugin_attrs, **editable) return editable
def test_removes_tasks_from_db_if_removed_from_new_plugin(self): plugin = self.env.create_plugin( tasks=self.env.get_default_plugin_tasks()) mocked_metadata = { 'metadata.yaml': {}, 'environment_config.yaml': {}, } self.assertNotEqual(plugin.tasks, []) with mock.patch( 'nailgun.plugins.loaders.files_manager.FilesManager.load' ) as load: def se(key): # Simulate that tasks.yaml was removed if key.endswith('tasks.yaml'): raise errors.NoPluginFileFound() return copy.deepcopy( mocked_metadata.get(os.path.basename(key))) load.side_effect = se PluginManager.sync_plugins_metadata(plugin_ids=[plugin.id]) self.assertEqual(plugin.tasks, [])
def get_volumes_metadata(cls, instance): """Return proper volumes metadata for cluster and consists with general volumes metadata from release and volumes metadata from plugins which releated to this cluster :param instance: Cluster DB instance :returns: dict -- object with merged volumes metadata """ volumes_metadata = copy.deepcopy(instance.release.volumes_metadata) plugin_volumes = PluginManager.get_volumes_metadata(instance) volumes_metadata["volumes_roles_mapping"].update(plugin_volumes["volumes_roles_mapping"]) volumes_metadata["volumes"].extend(plugin_volumes["volumes"]) return volumes_metadata