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 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 )
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)
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
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
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)
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())
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
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
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)
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())
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
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)
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)
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]
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
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
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)
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 )
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
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
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
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
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)
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)
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
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
def get_enabled_plugins(cls, cluster): return [ wrap_plugin(plugin) for plugin in ClusterPlugins.get_enabled(cluster.id) ]
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
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
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
def get_enabled_plugins(cls, cluster): return [wrap_plugin(plugin) for plugin in ClusterPlugins.get_enabled(cluster.id)]