Ejemplo n.º 1
0
    def validate_allowed_attributes(cls, cluster, data):
        """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
        :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:
            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
                )
Ejemplo n.º 2
0
    def validate(cls, data):
        # TODO(enchantner): rewrite validators to use Node object
        data = cls.validate_json(data)

        if data.get("status", "") != "discover":
            raise errors.NotAllowed(
                "Only bootstrap nodes are allowed to be registered.")

        if 'mac' not in data:
            raise errors.InvalidData("No mac address specified",
                                     log_message=True)

        if cls.does_node_exist_in_db(data):
            raise errors.AlreadyExists("Node with mac {0} already "
                                       "exists - doing nothing".format(
                                           data["mac"]),
                                       log_level="info")

        if cls.validate_existent_node_mac_create(data):
            raise errors.AlreadyExists("Node with mac {0} already "
                                       "exists - doing nothing".format(
                                           data["mac"]),
                                       log_level="info")

        if 'meta' in data:
            MetaValidator.validate_create(data['meta'])

        return data
Ejemplo n.º 3
0
    def validate(cls, data):
        data = cls.validate_json(data)
        cluster = objects.Cluster.get_by_uid(data['cluster_id'],
                                             fail_if_not_found=True)

        cls._validate_unique_name(data)

        if data.get('is_default'):
            raise errors.NotAllowed(
                "Default node group is created only by Nailgun.")

        if cluster.net_provider == consts.CLUSTER_NET_PROVIDERS.nova_network:
            raise errors.NotAllowed(
                "Node groups can only be created when using Neutron.")

        return data
Ejemplo n.º 4
0
    def _validate_common(cls, data, instance=None):
        d = cls.validate_json(data)
        release_id = d.get("release", d.get("release_id"))
        if release_id:
            release = objects.Release.get_by_uid(release_id)
            if not release:
                raise errors.InvalidData("Invalid release ID",
                                         log_message=True)
            if not objects.Release.is_deployable(release):
                raise errors.NotAllowed(
                    "Release with ID '{0}' is not deployable.".format(
                        release_id),
                    log_message=True)
            cls._validate_mode(d, release)

        pend_release_id = d.get("pending_release_id")
        if pend_release_id:
            pend_release = objects.Release.get_by_uid(pend_release_id,
                                                      fail_if_not_found=True)
            if not release_id:
                if not instance:
                    raise errors.InvalidData(
                        "Cannot set pending release when "
                        "there is no current release",
                        log_message=True)
                release_id = instance.release_id
            curr_release = objects.Release.get_by_uid(release_id)

            if not cls._can_update_release(curr_release, pend_release):
                raise errors.InvalidData(
                    "Cannot set pending release as "
                    "it cannot update current release",
                    log_message=True)

        return d
Ejemplo n.º 5
0
    def validate(cls, data):
        data = cls.validate_json(data)
        cluster = objects.Cluster.get_by_uid(data['cluster_id'])
        if cluster.net_provider == consts.CLUSTER_NET_PROVIDERS.nova_network:
            raise errors.NotAllowed(
                "Node groups can only be created when using Neutron.")

        return data
Ejemplo n.º 6
0
    def validate(cls, data):
        data = cls.validate_json(data)
        cluster = objects.Cluster.get_by_uid(data['cluster_id'])
        if (cluster.net_provider == consts.CLUSTER_NET_PROVIDERS.nova_network
                or cluster.network_config.segmentation_type !=
                consts.NEUTRON_SEGMENT_TYPES.gre):
            raise errors.NotAllowed(
                "Node groups can only be created when using Neutron GRE.")

        return data
Ejemplo n.º 7
0
 def _check_for_deployed_nodes(cls, cluster):
     """Check if nodes reconfiguration is allowed for cluster"""
     env_version = cluster.release.environment_version
     if not StrictVersion(env_version) >= StrictVersion('8.0'):
         if any(
                 objects.Cluster.get_nodes_by_status(
                     cluster, consts.NODE_STATUSES.ready)):
             raise errors.NotAllowed("Reconfiguration of nodes after the "
                                     "deployment is allowed only for "
                                     "environments 8.0 or greater.")
Ejemplo n.º 8
0
    def _validate_default_flag(self, data):
        """Vadidate default flag

        Since changing of 'is_default' flag for node group is forbidden
        this method validate such case

        :param data: input request data
        :type data: dict
        """
        nodegroup = objects.NodeGroupCollection.filter_by(
            None, name=data['name'], cluster_id=data['cluster_id']).first()
        if nodegroup and data['is_default'] != nodegroup.is_default:
            raise errors.NotAllowed(
                "'default' flag for node group cannot be changed")
Ejemplo n.º 9
0
    def validate_update(cls, data, instance):
        data = cls.validate_json(data)

        cls._validate_unique_name(data,
                                  objects.NodeGroup.model.id != instance.id)

        if 'is_default' in data:
            cls._validate_default_flag(data)

        if 'cluster_id' in data and data['cluster_id'] != instance.cluster_id:
            raise errors.NotAllowed(
                "Node group cannot be assigned to other cluster "
                "after creation.")

        return data
Ejemplo n.º 10
0
    def validate_plugin_attributes(cls, cluster, attributes):
        """Validates Cluster-Plugins relations attributes

        :param cluster: A cluster instance
        :type cluster: nailgun.objects.cluster.Cluster
        :param attributes: The editable attributes of the Cluster
        :type attributes: dict
        :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 not cluster.is_locked:
            return

        enabled_plugins = set(
            p.id for p in objects.ClusterPlugins.get_enabled(cluster.id)
        )

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

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

            if not attrs.get('metadata', {}).get('enabled'):
                continue

            for version in plugin_versions['values']:
                plugin_id = version.get('data')
                plugin = objects.Plugin.get_by_uid(plugin_id)
                if not plugin:
                    continue

                if plugin_id != plugin_versions['value']:
                    continue

                if plugin.is_hotpluggable or plugin.id in enabled_plugins:
                    break

                raise errors.NotAllowed(
                    "This plugin version can be enabled only "
                    "before environment is deployed.",
                    log_message=True
                )
Ejemplo n.º 11
0
    def _check_no_running_deploy_tasks(cluster):
        """Check that no deploy tasks are running at the moment

        If there are running deploy tasks in cluster, NotAllowed exception
        raises.
        """
        deploy_task_ids = [
            six.text_type(task.id)
            for task in objects.TaskCollection.get_by_name_and_cluster(
                cluster, (consts.TASK_NAMES.deployment, )).filter(
                    models.Task.status.in_((
                        consts.TASK_STATUSES.pending,
                        consts.TASK_STATUSES.running))).all()
        ]

        if deploy_task_ids:
            raise errors.NotAllowed(
                "Cannot perform the action because there are "
                "running deployment tasks '{0}'"
                "".format(', '.join(deploy_task_ids)))
Ejemplo n.º 12
0
    def validate_hostname(cls, hostname, instance):
        if hostname == instance.hostname:
            return

        if instance.status != consts.NODE_STATUSES.discover:
            raise errors.NotAllowed(
                "Node hostname may be changed only before provisioning.")

        if instance.cluster:
            cluster = instance.cluster
            public_ssl_endpoint = cluster.attributes.editable.get(
                'public_ssl', {}).get('hostname', {}).get('value', "")

            if public_ssl_endpoint in (
                    hostname,
                    objects.Node.generate_fqdn_by_hostname(hostname)):
                raise errors.InvalidData(
                    "New hostname '{0}' conflicts with public TLS endpoint".
                    format(hostname))
        if objects.Node.get_by_hostname(hostname, instance.cluster_id):
            raise errors.AlreadyExists(
                "Duplicate hostname '{0}'.".format(hostname))
Ejemplo n.º 13
0
    def _validate_unique_name(cls, data, *filters):
        """Validate node group name to be unique.

        Validate whether node group name is unique for specific
        environment. Prevent to have duplicated node group names for
        the same environment.

        :param data: data which contains node group name and cluster_id.
        :param filters: additional filters for the query which is
                        used in the method for validation.
        :type data: dict
        :type filters: list
        :returns: None
        """
        nodegroup_query = objects.NodeGroupCollection.filter_by(
            None, name=data['name'], cluster_id=data['cluster_id'])
        if filters:
            nodegroup_query = nodegroup_query.filter(*filters)
        nodegroup_exists = db.query(nodegroup_query.exists()).scalar()
        if nodegroup_exists:
            raise errors.NotAllowed("Node group '{0}' already exists "
                                    "in environment {1}.".format(
                                        data['name'], data['cluster_id']))