Example #1
0
    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
Example #2
0
    def process_cluster_attributes(cls, cluster, attributes):
        """Generate Cluster-Plugins relation based on attributes

        Iterates through plugins attributes, creates
        or deletes Cluster <-> Plugins relation if plugin
        is enabled or disabled.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param attributes: Cluster attributes
        :type attributes: dict
        """
        def _convert_attrs(plugin_id, attrs):
            prefix = "#{0}_".format(plugin_id)
            result = dict((title[len(prefix):], attrs[title])
                          for title in attrs
                          if title.startswith(prefix))
            for attr in six.itervalues(result):
                if 'restrictions' not in attr:
                    continue
                if len(attr['restrictions']) == 1:
                    attr.pop('restrictions')
                else:
                    attr['restrictions'].pop()
            return result

        for attrs in six.itervalues(attributes):
            if not isinstance(attrs, dict):
                continue

            plugin_versions = attrs.pop('plugin_versions', None)
            if plugin_versions is None:
                continue

            metadata = attrs.pop('metadata', {})
            plugin_enabled = metadata.get('enabled', False)
            default = metadata.get('default', False)

            for version in plugin_versions['values']:
                pid = version.get('data')
                plugin = Plugin.get_by_uid(pid)
                if not plugin:
                    logger.warning(
                        'Plugin with id "%s" is not found, skip it', pid)
                    continue

                enabled = plugin_enabled and\
                    pid == plugin_versions['value']

                ClusterPlugins.set_attributes(
                    cluster.id, plugin.id, enabled=enabled,
                    attrs=_convert_attrs(plugin.id, attrs)
                    if enabled or default else None
                )
Example #3
0
    def process_cluster_attributes(cls, cluster, attributes):
        """Generate Cluster-Plugins relation based on attributes

        Iterates through plugins attributes, creates
        or deletes Cluster <-> Plugins relation if plugin
        is enabled or disabled.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param attributes: Cluster attributes
        :type attributes: dict
        """
        def _convert_attrs(plugin_id, attrs):
            prefix = "#{0}_".format(plugin_id)
            result = dict((title[len(prefix):], attrs[title])
                          for title in attrs if title.startswith(prefix))
            for attr in six.itervalues(result):
                if 'restrictions' not in attr:
                    continue
                if len(attr['restrictions']) == 1:
                    attr.pop('restrictions')
                else:
                    attr['restrictions'].pop()
            return result

        for attrs in six.itervalues(attributes):
            if not isinstance(attrs, dict):
                continue

            plugin_versions = attrs.pop('plugin_versions', None)
            if plugin_versions is None:
                continue

            metadata = attrs.pop('metadata', {})
            plugin_enabled = metadata.get('enabled', False)
            default = metadata.get('default', False)

            for version in plugin_versions['values']:
                pid = version.get('data')
                plugin = Plugin.get_by_uid(pid)
                if not plugin:
                    logger.warning('Plugin with id "%s" is not found, skip it',
                                   pid)
                    continue

                enabled = plugin_enabled and\
                    pid == plugin_versions['value']

                ClusterPlugins.set_attributes(
                    cluster.id,
                    plugin.id,
                    enabled=enabled,
                    attrs=_convert_attrs(plugin.id, attrs)
                    if enabled or default else None)
Example #4
0
    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", [])

        data["fuel_version"] = settings.VERSION["release"]
        new_cluster = super(Cluster, cls).create(data)
        cls.create_default_group(new_cluster)

        cls.create_attributes(new_cluster)
        cls.create_vmware_attributes(new_cluster)
        cls.create_default_extensions(new_cluster)

        try:
            cls.get_network_manager(new_cluster).\
                create_network_groups_and_config(new_cluster, data)
            cls.add_pending_changes(new_cluster, "attributes")
            cls.add_pending_changes(new_cluster, "networks")
            cls.add_pending_changes(new_cluster, "vmware_attributes")

            if assign_nodes:
                cls.update_nodes(new_cluster, assign_nodes)
        except (
            errors.OutOfVLANs,
            errors.OutOfIPs,
            errors.NoSuitableCIDR
        ) as exc:
            db().delete(new_cluster)
            raise errors.CannotCreate(exc.message)

        db().flush()

        ClusterPlugins.add_compatible_plugins(new_cluster)

        return new_cluster
Example #5
0
 def get_cluster_plugins_with_tasks(cls, cluster):
     cluster_plugins = []
     for plugin_db in ClusterPlugins.get_enabled(cluster.id):
         plugin_adapter = wrap_plugin(plugin_db)
         plugin_adapter.set_cluster_tasks()
         cluster_plugins.append(plugin_adapter)
     return cluster_plugins
Example #6
0
    def _success_action(cls, task, status, progress):
        # check if all nodes are ready
        if any(map(lambda n: n.status == 'error', task.cluster.nodes)):
            cls._error_action(task, 'error', 100)
            return

        task_name = task.name.title()
        try:
            message = (u"{0} of environment '{1}' is done. ").format(
                task_name,
                task.cluster.name,
            )
        except Exception as exc:
            logger.error(": ".join([str(exc), traceback.format_exc()]))
            message = u"{0} of environment '{1}' is done".format(
                task_name, task.cluster.name)

        zabbix_url = objects.Cluster.get_network_manager(
            task.cluster).get_zabbix_url(task.cluster)

        if zabbix_url:
            message = "{0} Access Zabbix dashboard at {1}".format(
                message, zabbix_url)

        plugins_msg = cls._make_plugins_success_message(
            ClusterPlugins.get_enabled(task.cluster.id))
        if plugins_msg:
            message = '{0}\n\n{1}'.format(message, plugins_msg)

        cls._notify(task, consts.NOTIFICATION_TOPICS.done, message)
        data = {'status': status, 'progress': progress, 'message': message}
        objects.Task.update(task, data)
Example #7
0
    def get_network_roles(cls, cluster, merge_policy):
        """Returns the network roles from plugins.

        The roles cluster and plugins will be mixed
        according to merge policy.
        """

        instance_roles = cluster.release.network_roles_metadata
        all_roles = dict((role['id'], role) for role in instance_roles)
        conflict_roles = dict()

        for plugin in ClusterPlugins.get_enabled(cluster.id):
            for role in plugin.network_roles_metadata:
                role_id = role['id']
                if role_id in all_roles:
                    try:
                        merge_policy.apply_patch(
                            all_roles[role_id],
                            role
                        )
                    except errors.UnresolvableConflict as e:
                        logger.error("cannot merge plugin {0}: {1}"
                                     .format(plugin.name, e))
                        conflict_roles[role_id] = plugin.name
                else:
                    all_roles[role_id] = role

        if conflict_roles:
            raise errors.NetworkRoleConflict(
                "Cannot override existing network roles: '{0}' in "
                "plugins: '{1}'".format(
                    ', '.join(conflict_roles),
                    ', '.join(set(conflict_roles.values()))))

        return list(all_roles.values())
Example #8
0
 def get_cluster_plugins_with_tasks(cls, cluster):
     cluster_plugins = []
     for plugin_db in ClusterPlugins.get_enabled(cluster.id):
         plugin_adapter = wrap_plugin(plugin_db)
         plugin_adapter.set_cluster_tasks()
         cluster_plugins.append(plugin_adapter)
     return cluster_plugins
Example #9
0
    def get_plugins_node_roles(cls, cluster):
        result = {}
        core_roles = set(cluster.release.roles_metadata)

        for plugin_db in ClusterPlugins.get_enabled(cluster.id):
            plugin_roles = wrap_plugin(plugin_db).normalized_roles_metadata

            # we should check all possible cases of roles intersection
            # with core ones and those from other plugins
            # and afterwards show them in error message;
            # thus role names for which following checks
            # fails are accumulated in err_info variable
            err_roles = set(r for r in plugin_roles
                            if r in core_roles or r in result)
            if err_roles:
                raise errors.AlreadyExists(
                    "Plugin (ID={0}) is unable to register the following "
                    "node roles: {1}".format(plugin_db.id,
                                             ", ".join(sorted(err_roles))))

            # update info on processed roles in case of
            # success of all intersection checks
            result.update(plugin_roles)

        return result
Example #10
0
    def get_plugins_node_roles(cls, cluster):
        result = {}
        core_roles = set(cluster.release.roles_metadata)

        for plugin_db in ClusterPlugins.get_enabled(cluster.id):
            plugin_roles = wrap_plugin(plugin_db).normalized_roles_metadata

            # we should check all possible cases of roles intersection
            # with core ones and those from other plugins
            # and afterwards show them in error message;
            # thus role names for which following checks
            # fails are accumulated in err_info variable
            err_roles = set(
                r for r in plugin_roles if r in core_roles or r in result
            )
            if err_roles:
                raise errors.AlreadyExists(
                    "Plugin (ID={0}) is unable to register the following "
                    "node roles: {1}".format(plugin_db.id,
                                             ", ".join(sorted(err_roles)))
                )

            # update info on processed roles in case of
            # success of all intersection checks
            result.update(plugin_roles)

        return result
Example #11
0
    def _success_action(cls, task, status, progress):
        # check if all nodes are ready
        if any(map(lambda n: n.status == "error", task.cluster.nodes)):
            cls._error_action(task, "error", 100)
            return

        task_name = task.name.title()
        try:
            message = (u"{0} of environment '{1}' is done. ").format(task_name, task.cluster.name)
        except Exception as exc:
            logger.error(": ".join([str(exc), traceback.format_exc()]))
            message = u"{0} of environment '{1}' is done".format(task_name, task.cluster.name)

        zabbix_url = objects.Cluster.get_network_manager(task.cluster).get_zabbix_url(task.cluster)

        if zabbix_url:
            message = "{0} Access Zabbix dashboard at {1}".format(message, zabbix_url)

        plugins_msg = cls._make_plugins_success_message(ClusterPlugins.get_enabled(task.cluster.id))
        if plugins_msg:
            message = "{0}\n\n{1}".format(message, plugins_msg)

        cls._notify(task, consts.NOTIFICATION_TOPICS.done, message)
        data = {"status": status, "progress": progress, "message": message}
        objects.Task.update(task, data)
Example #12
0
    def get_network_roles(cls, cluster, merge_policy):
        """Returns the network roles from plugins.

        The roles cluster and plugins will be mixed
        according to merge policy.
        """

        instance_roles = cluster.release.network_roles_metadata
        all_roles = dict((role['id'], role) for role in instance_roles)
        conflict_roles = dict()

        for plugin in ClusterPlugins.get_enabled(cluster.id):
            for role in plugin.network_roles_metadata:
                role_id = role['id']
                if role_id in all_roles:
                    try:
                        merge_policy.apply_patch(all_roles[role_id], role)
                    except errors.UnresolvableConflict as e:
                        logger.error("cannot merge plugin {0}: {1}".format(
                            plugin.name, e))
                        conflict_roles[role_id] = plugin.name
                else:
                    all_roles[role_id] = role

        if conflict_roles:
            raise errors.NetworkRoleConflict(
                "Cannot override existing network roles: '{0}' in "
                "plugins: '{1}'".format(
                    ', '.join(conflict_roles),
                    ', '.join(set(conflict_roles.values()))))

        return list(all_roles.values())
Example #13
0
    def get_cluster_plugins_info(self, cluster):
        plugins_info = []
        for plugin_inst in ClusterPlugins.get_enabled(cluster.id):
            plugin_info = self.get_attributes(plugin_inst.__dict__,
                                              self.plugin_info_white_list)
            plugins_info.append(plugin_info)

        return plugins_info
Example #14
0
    def get_cluster_plugins_info(self, cluster):
        plugins_info = []
        for plugin_inst in ClusterPlugins.get_enabled(cluster.id):
            plugin_info = self.get_attributes(plugin_inst.__dict__,
                                              self.plugin_info_white_list)
            plugins_info.append(plugin_info)

        return plugins_info
Example #15
0
    def enable_plugins_by_components(cls, cluster):
        """Enable plugin by components.

        :param cluster: A cluster instance
        :type cluster: Cluster model
        """
        cluster_components = set(cluster.components)
        plugin_ids = [p.id for p in PluginCollection.all_newest()]

        for plugin in ClusterPlugins.get_connected_plugins(
                cluster, plugin_ids):
            plugin_adapter = wrap_plugin(plugin)
            plugin_components = set(
                component['name']
                for component in plugin_adapter.components_metadata)

            if cluster_components & plugin_components:
                ClusterPlugins.set_attributes(
                    cluster.id, plugin.id, enabled=True)
Example #16
0
    def enable_plugins_by_components(cls, cluster):
        """Enable plugin by components.

        :param cluster: A cluster instance
        :type cluster: Cluster model
        """
        cluster_components = set(cluster.components)
        plugin_ids = [p.id for p in PluginCollection.all_newest()]

        for plugin in ClusterPlugins.get_connected_plugins(
                cluster, plugin_ids):
            plugin_adapter = wrap_plugin(plugin)
            plugin_components = set(
                component['name']
                for component in plugin_adapter.components_metadata)

            if cluster_components & plugin_components:
                ClusterPlugins.set_attributes(cluster.id,
                                              plugin.id,
                                              enabled=True)
Example #17
0
    def get_release_info(self, release):
        """Get plugin release information which corresponds to given release"""
        rel_os = release.operating_system.lower()
        version = release.version

        release_info = filter(
            lambda r: (
                r['os'] == rel_os and
                ClusterPlugins.is_release_version_compatible(version,
                                                             r['version'])),
            self.plugin.releases)

        return release_info[0]
Example #18
0
    def get_plugins_attributes(cls,
                               cluster,
                               all_versions=False,
                               default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        plugins_attributes = {}
        for plugin in ClusterPlugins.get_connected_plugins_data(cluster.id):
            db_plugin = Plugin.get_by_uid(plugin.id)
            plugin_adapter = wrap_plugin(db_plugin)
            default_attrs = plugin_adapter.attributes_metadata

            if all_versions:
                container = plugins_attributes.setdefault(plugin.name, {})
                enabled = plugin.enabled and not (all_versions and default)
                cls.create_common_metadata(plugin, container, enabled)
                container['metadata']['default'] = default

                versions = container['metadata'].setdefault('versions', [])
                if default:
                    actual_attrs = copy.deepcopy(default_attrs)
                    actual_attrs.setdefault('metadata', {})
                else:
                    actual_attrs = copy.deepcopy(plugin.attributes)
                    actual_attrs['metadata'] = default_attrs.get(
                        'metadata', {})
                cls.fill_plugin_metadata(plugin, actual_attrs['metadata'])
                versions.append(actual_attrs)

                container['metadata'].setdefault('chosen_id', plugin.id)
                if enabled:
                    container['metadata']['chosen_id'] = plugin.id

            elif plugin.enabled:
                container = plugins_attributes.setdefault(plugin.name, {})
                cls.create_common_metadata(plugin, container)
                container['metadata'].update(default_attrs.get('metadata', {}))
                cls.fill_plugin_metadata(plugin, container['metadata'])
                container.update(plugin.attributes)

        return plugins_attributes
Example #19
0
    def get_cluster_plugins_info(self, cluster):
        plugins_info = []
        for plugin_inst in ClusterPlugins.get_enabled(cluster.id):
            plugin_info = {
                "id": plugin_inst.id,
                "name": plugin_inst.name,
                "version": plugin_inst.version,
                "releases": plugin_inst.releases,
                "fuel_version": plugin_inst.fuel_version,
                "package_version": plugin_inst.package_version,
            }
            plugins_info.append(plugin_info)

        return plugins_info
Example #20
0
    def get_cluster_plugins_info(self, cluster):
        plugins_info = []
        for plugin_inst in ClusterPlugins.get_enabled(cluster.id):
            plugin_info = {
                "id": plugin_inst.id,
                "name": plugin_inst.name,
                "version": plugin_inst.version,
                "releases": plugin_inst.releases,
                "fuel_version": plugin_inst.fuel_version,
                "package_version": plugin_inst.package_version,
            }
            plugins_info.append(plugin_info)

        return plugins_info
Example #21
0
    def process_cluster_attributes(cls, cluster, attributes):
        """Generate Cluster-Plugins relation based on attributes.

        Iterates through plugins attributes, creates
        or deletes Cluster <-> Plugins relation if plugin
        is enabled or disabled.

        :param cluster: A cluster instance
        :type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster
        :param attributes: Cluster attributes
        :type attributes: dict
        """
        plugins = {}

        # Detach plugins data
        for k in list(attributes):
            if cls.is_plugin_data(attributes[k]):
                plugins[k] = attributes.pop(k)['metadata']
                cluster.attributes.editable.pop(k, None)

        for container in six.itervalues(plugins):
            default = container.get('default', False)
            for attrs in container.get('versions', []):
                version_metadata = attrs.pop('metadata')
                plugin_id = version_metadata['plugin_id']
                plugin = Plugin.get_by_uid(plugin_id)
                if not plugin:
                    logger.warning('Plugin with id "%s" is not found, skip it',
                                   plugin_id)
                    continue
                enabled = container['enabled']\
                    and plugin_id == container['chosen_id']
                ClusterPlugins.set_attributes(
                    cluster.id,
                    plugin.id,
                    enabled=enabled,
                    attrs=attrs if enabled or default else None)
Example #22
0
    def process_cluster_attributes(cls, cluster, attributes):
        """Generate Cluster-Plugins relation based on attributes.

        Iterates through plugins attributes, creates
        or deletes Cluster <-> Plugins relation if plugin
        is enabled or disabled.

        :param cluster: A cluster instance
        :type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster
        :param attributes: Cluster attributes
        :type attributes: dict
        """
        plugins = {}

        # Detach plugins data
        for k in list(attributes):
            if cls.is_plugin_data(attributes[k]):
                plugins[k] = attributes.pop(k)['metadata']
                cluster.attributes.editable.pop(k, None)

        for container in six.itervalues(plugins):
            default = container.get('default', False)
            for attrs in container.get('versions', []):
                version_metadata = attrs.pop('metadata')
                plugin_id = version_metadata['plugin_id']
                plugin = Plugin.get_by_uid(plugin_id)
                if not plugin:
                    logger.warning(
                        'Plugin with id "%s" is not found, skip it', plugin_id)
                    continue
                enabled = container['enabled']\
                    and plugin_id == container['chosen_id']
                ClusterPlugins.set_attributes(
                    cluster.id, plugin.id, enabled=enabled,
                    attrs=attrs if enabled or default else None
                )
Example #23
0
    def get_plugins_attributes(
            cls, cluster, all_versions=False, default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        plugins_attributes = {}
        for plugin in ClusterPlugins.get_connected_plugins_data(cluster.id):
            db_plugin = Plugin.get_by_uid(plugin.id)
            plugin_adapter = wrap_plugin(db_plugin)
            default_attrs = plugin_adapter.attributes_metadata

            if all_versions:
                container = plugins_attributes.setdefault(plugin.name, {})
                enabled = plugin.enabled and not (all_versions and default)
                cls.create_common_metadata(plugin, container, enabled)
                container['metadata']['default'] = default

                versions = container['metadata'].setdefault('versions', [])
                if default:
                    actual_attrs = copy.deepcopy(default_attrs)
                    actual_attrs.setdefault('metadata', {})
                else:
                    actual_attrs = copy.deepcopy(plugin.attributes)
                    actual_attrs['metadata'] = default_attrs.get('metadata',
                                                                 {})
                cls.fill_plugin_metadata(plugin, actual_attrs['metadata'])
                versions.append(actual_attrs)

                container['metadata'].setdefault('chosen_id', plugin.id)
                if enabled:
                    container['metadata']['chosen_id'] = plugin.id

            elif plugin.enabled:
                container = plugins_attributes.setdefault(plugin.name, {})
                cls.create_common_metadata(plugin, container)
                container['metadata'].update(default_attrs.get('metadata', {}))
                cls.fill_plugin_metadata(plugin, container['metadata'])
                container.update(plugin.attributes)

        return plugins_attributes
Example #24
0
    def get_volumes_metadata(cls, cluster):
        """Get volumes metadata for cluster from all plugins which enabled it.

        :param cluster: A cluster instance
        :type cluster: Cluster model
        :return: dict -- Object with merged volumes data from plugins
        """
        volumes_metadata = {
            'volumes': [],
            'volumes_roles_mapping': {},
            'rule_to_pick_boot_disk': [],
        }
        release_volumes = cluster.release.volumes_metadata.get('volumes', [])
        release_volumes_ids = [v['id'] for v in release_volumes]
        processed_volumes = {}

        enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
        for plugin_adapter in map(wrap_plugin, enabled_plugins):
            metadata = plugin_adapter.volumes_metadata

            for volume in metadata.get('volumes', []):
                volume_id = volume['id']
                if volume_id in release_volumes_ids:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with release '
                        'by introducing the same volume with id "{1}"'.format(
                            plugin_adapter.full_name, volume_id))
                elif volume_id in processed_volumes:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with plugin {1} '
                        'by introducing the same volume with id "{2}"'.format(
                            plugin_adapter.full_name,
                            processed_volumes[volume_id], volume_id))

                processed_volumes[volume_id] = plugin_adapter.full_name

            volumes_metadata.get('volumes_roles_mapping', {}).update(
                metadata.get('volumes_roles_mapping', {}))
            volumes_metadata.get('volumes',
                                 []).extend(metadata.get('volumes', []))
            volumes_metadata.get('rule_to_pick_boot_disk', []).extend(
                metadata.get('rule_to_pick_boot_disk', []))

        return volumes_metadata
Example #25
0
    def get_volumes_metadata(cls, cluster):
        """Get volumes metadata for cluster from all plugins which enabled it.

        :param cluster: A cluster instance
        :type cluster: Cluster model
        :return: dict -- Object with merged volumes data from plugins
        """
        volumes_metadata = {
            'volumes': [],
            'volumes_roles_mapping': {}
        }
        release_volumes = cluster.release.volumes_metadata.get('volumes', [])
        release_volumes_ids = [v['id'] for v in release_volumes]
        processed_volumes = {}

        enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
        for plugin_adapter in map(wrap_plugin, enabled_plugins):
            metadata = plugin_adapter.volumes_metadata

            for volume in metadata.get('volumes', []):
                volume_id = volume['id']
                if volume_id in release_volumes_ids:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with release '
                        'by introducing the same volume with id "{1}"'
                        .format(plugin_adapter.full_name, volume_id))
                elif volume_id in processed_volumes:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with plugin {1} '
                        'by introducing the same volume with id "{2}"'
                        .format(plugin_adapter.full_name,
                                processed_volumes[volume_id],
                                volume_id))

                processed_volumes[volume_id] = plugin_adapter.full_name

            volumes_metadata.get('volumes_roles_mapping', {}).update(
                metadata.get('volumes_roles_mapping', {}))
            volumes_metadata.get('volumes', []).extend(
                metadata.get('volumes', []))

        return volumes_metadata
Example #26
0
    def get_plugins_deployment_tasks(cls, cluster):
        deployment_tasks = []
        processed_tasks = {}

        enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
        for plugin_adapter in map(wrap_plugin, enabled_plugins):
            depl_tasks = plugin_adapter.deployment_tasks

            for t in depl_tasks:
                t_id = t['id']
                if t_id in processed_tasks:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with plugin {1} '
                        'by introducing the same deployment task with '
                        'id {2}'.format(plugin_adapter.full_name,
                                        processed_tasks[t_id], t_id))
                processed_tasks[t_id] = plugin_adapter.full_name

            deployment_tasks.extend(depl_tasks)

        return deployment_tasks
Example #27
0
    def _success_action(cls, task, status, progress, nodes):
        # check if all nodes are ready
        if any(n.status == consts.NODE_STATUSES.error for n in nodes):
            cls._error_action(task, 'error', 100)
            return

        task_name = task.name.title()
        if nodes:
            # check that all nodes in same state
            remaining = objects.Cluster.get_nodes_count_unmet_status(
                nodes[0].cluster, nodes[0].status
            )
            if remaining > 0:
                message = u"{0} of {1} environment node(s) is done.".format(
                    task_name, len(nodes)
                )
            else:
                message = u"{0} of environment '{1}' is done.".format(
                    task_name, task.cluster.name
                )
        else:
            message = u"{0} is done. No changes.".format(task_name)

        zabbix_url = objects.Cluster.get_network_manager(
            task.cluster
        ).get_zabbix_url(task.cluster)

        if zabbix_url:
            message = "{0} Access Zabbix dashboard at {1}".format(
                message, zabbix_url)

        if task.name != consts.TASK_NAMES.provision:
            plugins_msg = cls._make_plugins_success_message(
                ClusterPlugins.get_enabled(task.cluster.id))
            if plugins_msg:
                message = '{0}\n\n{1}'.format(message, plugins_msg)

        cls._notify(task, consts.NOTIFICATION_TOPICS.done, message)
        data = {'status': status, 'progress': progress, 'message': message}
        objects.Task.update(task, data)
Example #28
0
    def _success_action(cls, task, status, progress, nodes):
        # check if all nodes are ready
        if any(n.status == consts.NODE_STATUSES.error for n in nodes):
            cls._error_action(task, 'error', 100)
            return

        task_name = task.name.title()
        if nodes:
            # check that all nodes in same state
            remaining = objects.Cluster.get_nodes_count_unmet_status(
                nodes[0].cluster, nodes[0].status)
            if remaining > 0:
                message = u"{0} of {1} environment node(s) is done.".format(
                    task_name, len(nodes))
            else:
                message = u"{0} of environment '{1}' is done.".format(
                    task_name, task.cluster.name)
        else:
            message = u"{0} is done. No changes.".format(task_name)

        zabbix_url = objects.Cluster.get_network_manager(
            task.cluster).get_zabbix_url(task.cluster)

        if zabbix_url:
            message = "{0} Access Zabbix dashboard at {1}".format(
                message, zabbix_url)

        if task.name != consts.TASK_NAMES.provision:
            plugins_msg = cls._make_plugins_success_message(
                ClusterPlugins.get_enabled(task.cluster.id))
            if plugins_msg:
                message = '{0}\n\n{1}'.format(message, plugins_msg)

        cls._notify(task, consts.NOTIFICATION_TOPICS.done, message)
        data = {'status': status, 'progress': progress, 'message': message}
        objects.Task.update(task, data)
Example #29
0
    def get_plugins_deployment_tasks(cls, cluster, graph_type=None):
        deployment_tasks = []
        processed_tasks = {}

        enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
        for plugin_adapter in map(wrap_plugin, enabled_plugins):
            depl_tasks = plugin_adapter.get_deployment_tasks(graph_type)

            for t in depl_tasks:
                t_id = t['id']
                if t_id in processed_tasks:
                    raise errors.AlreadyExists(
                        'Plugin {0} is overlapping with plugin {1} '
                        'by introducing the same deployment task with '
                        'id {2}'
                        .format(plugin_adapter.full_name,
                                processed_tasks[t_id],
                                t_id)
                    )
                processed_tasks[t_id] = plugin_adapter.full_name

            deployment_tasks.extend(depl_tasks)

        return deployment_tasks
Example #30
0
    def get_plugins_attributes(cls,
                               cluster,
                               all_versions=False,
                               default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        versions = {
            u'type': u'radio',
            u'values': [],
            u'weight': 10,
            u'value': None,
            u'label': 'Choose a plugin version'
        }

        def _convert_attr(pid, name, title, attr):
            restrictions = attr.setdefault('restrictions', [])
            restrictions.append({
                'action':
                'hide',
                'condition':
                "settings:{0}.plugin_versions.value != '{1}'".format(
                    name, pid)
            })
            return "#{0}_{1}".format(pid, title), attr

        plugins_attributes = {}
        for pid, name, title, version, enabled, default_attrs, cluster_attrs\
                in ClusterPlugins.get_connected_plugins(cluster.id):
            if all_versions:
                enabled = enabled and not default
            data = plugins_attributes.get(name, {})
            metadata = data.setdefault('metadata', {
                u'toggleable': True,
                u'weight': 70
            })
            metadata['enabled'] = enabled or metadata.get('enabled', False)
            metadata['label'] = title

            if all_versions:
                metadata['default'] = default

                attrs = default_attrs if default else cluster_attrs
                data.update(
                    _convert_attr(pid, name, key, attrs[key]) for key in attrs)

                if 'plugin_versions' in data:
                    plugin_versions = data['plugin_versions']
                else:
                    plugin_versions = copy.deepcopy(versions)
                plugin_versions['values'].append({
                    u'data': str(pid),
                    u'description': '',
                    u'label': version
                })
                if not plugin_versions['value'] or enabled:
                    plugin_versions['value'] = str(pid)

                data['plugin_versions'] = plugin_versions
            else:
                data.update(cluster_attrs if enabled else {})
            plugins_attributes[name] = data

        return plugins_attributes
Example #31
0
 def get_enabled_plugins(cls, cluster):
     return [
         wrap_plugin(plugin)
         for plugin in ClusterPlugins.get_enabled(cluster.id)
     ]
Example #32
0
    def get_plugins_attributes(
            cls, cluster, all_versions=False, default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        versions = {
            'type': 'radio',
            'values': [],
            'weight': 10,
            'value': None,
            'label': 'Choose a plugin version'
        }

        plugins_attributes = {}
        for plugin in ClusterPlugins.get_connected_plugins_data(cluster.id):
            plugin_id = str(plugin.id)
            enabled = plugin.enabled and not (all_versions and default)
            plugin_attributes = plugins_attributes.setdefault(plugin.name, {})
            metadata = plugin_attributes.setdefault('metadata', {
                'toggleable': True,
                'weight': 70
            })
            metadata['enabled'] = enabled or metadata.get('enabled', False)
            metadata['label'] = plugin.title
            if plugin.is_hotpluggable:
                metadata["always_editable"] = True

            if all_versions:
                metadata['default'] = default

                plugin_attributes.update(
                    cls.convert_plugin_attributes(
                        plugin,
                        plugin.attributes_metadata
                        if default else plugin.attributes
                    )
                )

                plugin_version = {
                    'data': plugin_id,
                    'description': '',
                    'label': plugin.version,
                }
                if not plugin.is_hotpluggable:
                    plugin_version['restrictions'] = [{
                        'action': 'disable',
                        'condition': 'cluster:is_locked'
                    }]

                plugin_versions = plugin_attributes.get('plugin_versions')
                if plugin_versions is not None:
                    if enabled:
                        plugin_versions['value'] = plugin_id
                else:
                    plugin_versions = copy.deepcopy(versions)
                    plugin_versions['value'] = plugin_id
                    plugin_attributes['plugin_versions'] = plugin_versions

                plugin_versions['values'].append(plugin_version)
            elif enabled:
                plugin_attributes.update(plugin.attributes)

        return plugins_attributes
Example #33
0
    def get_plugins_attributes(
            cls, cluster, all_versions=False, default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        versions = {
            u'type': u'radio',
            u'values': [],
            u'weight': 10,
            u'value': None,
            u'label': 'Choose a plugin version'
        }

        def _convert_attr(pid, name, title, attr):
            restrictions = attr.setdefault('restrictions', [])
            restrictions.append({
                'action': 'hide',
                'condition': "settings:{0}.plugin_versions.value != '{1}'"
                             .format(name, pid)
            })
            return "#{0}_{1}".format(pid, title), attr

        plugins_attributes = {}
        for pid, name, title, version, enabled, default_attrs, cluster_attrs\
                in ClusterPlugins.get_connected_plugins(cluster.id):
            if all_versions:
                enabled = enabled and not default
            data = plugins_attributes.get(name, {})
            metadata = data.setdefault('metadata', {
                u'toggleable': True,
                u'weight': 70
            })
            metadata['enabled'] = enabled or metadata.get('enabled', False)
            metadata['label'] = title

            if all_versions:
                metadata['default'] = default

                attrs = default_attrs if default else cluster_attrs
                data.update(_convert_attr(pid, name, key, attrs[key])
                            for key in attrs)

                if 'plugin_versions' in data:
                    plugin_versions = data['plugin_versions']
                else:
                    plugin_versions = copy.deepcopy(versions)
                plugin_versions['values'].append({
                    u'data': str(pid),
                    u'description': '',
                    u'label': version
                })
                if not plugin_versions['value'] or enabled:
                    plugin_versions['value'] = str(pid)

                data['plugin_versions'] = plugin_versions
            else:
                data.update(cluster_attrs if enabled else {})
            plugins_attributes[name] = data

        return plugins_attributes
Example #34
0
    def get_plugins_attributes(cls,
                               cluster,
                               all_versions=False,
                               default=False):
        """Gets attributes of all plugins connected with given cluster.

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param all_versions: True to get attributes of all versions of plugins
        :type all_versions: bool
        :param default: True to return a default plugins attributes (for UI)
        :type default: bool
        :return: Plugins attributes
        :rtype: dict
        """
        versions = {
            'type': 'radio',
            'values': [],
            'weight': 10,
            'value': None,
            'label': 'Choose a plugin version'
        }

        plugins_attributes = {}
        for plugin in ClusterPlugins.get_connected_plugins_data(cluster.id):
            plugin_id = str(plugin.id)
            enabled = plugin.enabled and not (all_versions and default)
            plugin_attributes = plugins_attributes.setdefault(plugin.name, {})
            metadata = plugin_attributes.setdefault('metadata', {
                'toggleable': True,
                'weight': 70
            })
            metadata['enabled'] = enabled or metadata.get('enabled', False)
            metadata['label'] = plugin.title
            if plugin.is_hotpluggable:
                metadata["always_editable"] = True

            if all_versions:
                metadata['default'] = default

                plugin_attributes.update(
                    cls.convert_plugin_attributes(
                        plugin, plugin.attributes_metadata
                        if default else plugin.attributes))

                plugin_version = {
                    'data': plugin_id,
                    'description': '',
                    'label': plugin.version,
                }
                if not plugin.is_hotpluggable:
                    plugin_version['restrictions'] = [{
                        'action':
                        'disable',
                        'condition':
                        'cluster:is_locked'
                    }]

                plugin_versions = plugin_attributes.get('plugin_versions')
                if plugin_versions is not None:
                    if enabled:
                        plugin_versions['value'] = plugin_id
                else:
                    plugin_versions = copy.deepcopy(versions)
                    plugin_versions['value'] = plugin_id
                    plugin_attributes['plugin_versions'] = plugin_versions

                plugin_versions['values'].append(plugin_version)
            elif enabled:
                plugin_attributes.update(plugin.attributes)

        return plugins_attributes
Example #35
0
 def get_enabled_plugins(cls, cluster):
     return [wrap_plugin(plugin)
             for plugin in ClusterPlugins.get_enabled(cluster.id)]