def disable(cls, instance): """Disables configuration. It is required to track history of previous configurations. This why disable operation doesn't remove a record from the database, it sets `is_active` property to False. """ if not instance.is_active: raise errors.CannotUpdate( "Configuration '{0}' has been already disabled.".format( instance.id)) instance.is_active = False db().flush()
def update(cls, instance, data): """Update Node instance with specified parameters in DB. This includes: * adding node to Cluster (if cluster_id is not None in data) \ (see :func:`add_into_cluster`) * updating roles for Node if it belongs to Cluster \ (see :func:`update_roles` and :func:`update_pending_roles`) * removing node from Cluster (if cluster_id is None in data) \ (see :func:`remove_from_cluster`) * updating interfaces for Node in DB (see :func:`update_interfaces`) * creating default Node attributes (see :func:`create_attributes`) * updating volumes allocation for Node using Cluster's Release \ metadata (see :func:`update_volumes`) :param data: dictionary of key-value pairs as object fields :returns: Node instance """ data.pop("id", None) data.pop("network_data", None) roles = data.pop("roles", None) pending_roles = data.pop("pending_roles", None) new_meta = data.pop("meta", None) disks_changed = None if new_meta and "disks" in new_meta and "disks" in instance.meta: key = operator.itemgetter("name") new_disks = sorted(new_meta["disks"], key=key) old_disks = sorted(instance.meta["disks"], key=key) disks_changed = (new_disks != old_disks) # TODO(enchantner): fix this temporary hack in clients if "cluster_id" not in data and "cluster" in data: cluster_id = data.pop("cluster", None) data["cluster_id"] = cluster_id if new_meta: instance.update_meta(new_meta) # The call to update_interfaces will execute a select query for # the current instance. This appears to overwrite the object in the # current session and we lose the meta changes. db().flush() # smarter check needed cls.update_interfaces(instance) cluster_changed = False if "cluster_id" in data: new_cluster_id = data.pop("cluster_id") if instance.cluster_id: if new_cluster_id is None: # removing node from cluster cluster_changed = True cls.remove_from_cluster(instance) elif new_cluster_id != instance.cluster_id: # changing node cluster to another # (is currently not allowed) raise errors.CannotUpdate( u"Changing cluster on the fly is not allowed") else: if new_cluster_id is not None: # assigning node to cluster cluster_changed = True cls.add_into_cluster(instance, new_cluster_id) if "group_id" in data: new_group_id = data.pop("group_id") if instance.group_id != new_group_id: nm = Cluster.get_network_manager(instance.cluster) nm.clear_assigned_networks(instance) nm.clear_bond_configuration(instance) instance.group_id = new_group_id cls.add_into_cluster(instance, instance.cluster_id) data["node_type"] = instance.node_type if 'nochange_powerip' not in data: data["power_ip"] = instance.power_ip if "name" in data: instance.name = data.pop("name") #logger.info("这是data['name']的值是 %s",data["name"]) #data["name"]=instance.name # calculating flags roles_changed = (roles is not None and set(roles) != set(instance.roles)) pending_roles_changed = ( pending_roles is not None and set(pending_roles) != set(instance.pending_roles)) super(Node, cls).update(instance, data) if roles_changed: cls.update_roles(instance, roles) if pending_roles_changed: cls.update_pending_roles(instance, pending_roles) if any(( roles_changed, pending_roles_changed, cluster_changed, disks_changed, )) and instance.status not in (consts.NODE_STATUSES.provisioning, consts.NODE_STATUSES.deploying): cls.update_volumes(instance) return instance
def update(cls, instance, data): """Update Node instance with specified parameters in DB. This includes: * adding node to Cluster (if cluster_id is not None in data) \ (see :func:`add_into_cluster`) * updating roles for Node if it belongs to Cluster \ (see :func:`update_roles` and :func:`update_pending_roles`) * removing node from Cluster (if cluster_id is None in data) \ (see :func:`remove_from_cluster`) * updating interfaces for Node in DB (see :func:`update_interfaces`) * creating default Node attributes (see :func:`create_attributes`) * updating volumes allocation for Node using Cluster's Release \ metadata (see :func:`update_volumes`) :param data: dictionary of key-value pairs as object fields :returns: Node instance """ data.pop("id", None) data.pop("network_data", None) roles = data.pop("roles", None) pending_roles = data.pop("pending_roles", None) new_meta = data.pop("meta", None) disks_changed = None if new_meta and "disks" in new_meta and "disks" in instance.meta: key = operator.itemgetter("name") new_disks = sorted(new_meta["disks"], key=key) old_disks = sorted(instance.meta["disks"], key=key) disks_changed = (new_disks != old_disks) # TODO(enchantner): fix this temporary hack in clients if "cluster_id" not in data and "cluster" in data: cluster_id = data.pop("cluster", None) data["cluster_id"] = cluster_id if new_meta: instance.update_meta(new_meta) # smarter check needed cls.update_interfaces(instance) cluster_changed = False if "cluster_id" in data: new_cluster_id = data.pop("cluster_id") if instance.cluster_id: if new_cluster_id is None: # removing node from cluster cluster_changed = True cls.remove_from_cluster(instance) elif new_cluster_id != instance.cluster_id: # changing node cluster to another # (is currently not allowed) raise errors.CannotUpdate( u"Changing cluster on the fly is not allowed" ) else: if new_cluster_id is not None: # assigning node to cluster cluster_changed = True cls.add_into_cluster(instance, new_cluster_id) # calculating flags roles_changed = ( roles is not None and set(roles) != set(instance.roles) ) pending_roles_changed = ( pending_roles is not None and set(pending_roles) != set(instance.pending_roles) ) super(Node, cls).update(instance, data) if roles_changed: cls.update_roles(instance, roles) if pending_roles_changed: cls.update_pending_roles(instance, pending_roles) if any(( roles_changed, pending_roles_changed, cluster_changed, disks_changed, )) and instance.status not in ( consts.NODE_STATUSES.provisioning, consts.NODE_STATUSES.deploying ): cls.update_volumes(instance) return instance
def update(cls, instance, data): """Update Node instance with specified parameters in DB. This includes: * adding node to Cluster (if cluster_id is not None in data) \ (see :func:`add_into_cluster`) * updating roles for Node if it belongs to Cluster \ (see :func:`update_roles` and :func:`update_pending_roles`) * removing node from Cluster (if cluster_id is None in data) \ (see :func:`remove_from_cluster`) * updating interfaces for Node in DB (see :func:`update_interfaces`) * creating default Node attributes (see :func:`create_attributes`) :param data: dictionary of key-value pairs as object fields :returns: Node instance """ data.pop("id", None) data.pop("network_data", None) roles = data.pop("roles", None) pending_roles = data.pop("pending_roles", None) new_meta = data.pop("meta", None) update_by_agent = data.pop("is_agent", False) disks_changed = None if new_meta and "disks" in new_meta and "disks" in instance.meta: key = operator.itemgetter("name") new_disks = sorted(new_meta["disks"], key=key) old_disks = sorted(instance.meta["disks"], key=key) disks_changed = (new_disks != old_disks) # TODO(enchantner): fix this temporary hack in clients if "cluster_id" not in data and "cluster" in data: cluster_id = data.pop("cluster", None) data["cluster_id"] = cluster_id if new_meta: instance.update_meta(new_meta) # The call to update_interfaces will execute a select query for # the current instance. This appears to overwrite the object in the # current session and we lose the meta changes. db().flush() if cls.hardware_info_locked(instance): logger.info("Interfaces are locked for update on node %s", instance.human_readable_name) else: cls.update_interfaces(instance, update_by_agent) cluster_changed = False if "cluster_id" in data: new_cluster_id = data.pop("cluster_id") if instance.cluster_id: if new_cluster_id is None: # removing node from cluster cluster_changed = True cls.remove_from_cluster(instance) elif new_cluster_id != instance.cluster_id: # changing node cluster to another # (is currently not allowed) raise errors.CannotUpdate( u"Changing cluster on the fly is not allowed") else: if new_cluster_id is not None: # assigning node to cluster cluster_changed = True cls.add_into_cluster(instance, new_cluster_id) if "group_id" in data: new_group_id = data.pop("group_id") if instance.group_id != new_group_id: nm = Cluster.get_network_manager(instance.cluster) nm.clear_assigned_networks(instance) nm.clear_bond_configuration(instance) instance.group_id = new_group_id cls.add_into_cluster(instance, instance.cluster_id) # calculating flags roles_changed = (roles is not None and set(roles) != set(instance.roles)) pending_roles_changed = ( pending_roles is not None and set(pending_roles) != set(instance.pending_roles)) super(Node, cls).update(instance, data) if roles_changed: cls.update_roles(instance, roles) if pending_roles_changed: cls.update_pending_roles(instance, pending_roles) if any(( roles_changed, pending_roles_changed, cluster_changed, disks_changed, )) and instance.status not in (consts.NODE_STATUSES.provisioning, consts.NODE_STATUSES.deploying): # TODO(eli): we somehow should move this # condition into extension, in order to do # that probably we will have to create separate # table to keep disks which were used to create # volumes mapping. # Should be solved as a part of blueprint # https://blueprints.launchpad.net/fuel/+spec # /volume-manager-refactoring fire_callback_on_node_update(instance) return instance