Example #1
0
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

        self.db = self.pyramid.db
        self.referenced_data_type = {}
        self.referenced_data_type['storage_can_view'] = 'storage'
        self.referenced_data_type['repository_can_view'] = 'repository'
        self.referenced_data_type['printer_can_view'] = 'printer'

        # Get gecos_ws_mgmt cookbook default data structure
        default_data_dotted_keys = {}
        default_data = self.get_default_data(default_data_dotted_keys)
        if default_data is None:
            logger.error("Can't find default data!")
            return

        # Get all the policies structures
        logger.info('Getting all the policies structures from database...')
        dbpolicies = self.db.policies.find()
        self.policiesdata = {}
        self.slug_check = {}
        for policy in dbpolicies:
            logger.debug('Adding to dictionary: %s => %s' %
                         (policy['_id'], json.dumps(policy['schema'])))
            self.policiesdata[str(policy['_id'])] = policy

            # Check policy slug field (must be unique)
            if policy['slug'] in self.slug_check:
                logger.error("There are more than one policy with '%s' slug!" %
                             (policy['slug']))
            else:
                slug = policy['slug']
                # The slug of the emitter policies is different from the others
                if slug == 'printer_can_view':
                    slug = 'printers_res'
                elif slug == 'storage_can_view':
                    slug = 'user_shared_folders_res'
                elif slug == 'repository_can_view':
                    slug = 'software_sources_res'

                self.slug_check[slug] = policy

            # Check policy serialization
            try:
                logger.debug('Serialized policy: %s' %
                             (json.dumps(Policy().serialize(policy))))
            except Exception as err:
                logger.error(
                    'Policy %s with slug %s can\'t be serialized: %s' %
                    (policy['_id'], policy['slug'], str(err)))
                logger.warn(
                    'Possible cause: New fields in models (Colander) but the import_policies command has not yet been executed to update schema.'
                )

        if self.options.clean_inheritance:
            logger.info('Cleaning inheritance field...')
            self.db.nodes.update({"inheritance": {
                '$exists': True
            }}, {'$unset': {
                "inheritance": {
                    '$exist': True
                }
            }},
                                 multi=True)

        if self.options.clean_variables:
            logger.info('Cleaning variables data from Chef nodes')
            for node_id in ChefNode.list():
                node = ChefNode(node_id, self.api)
                if node.normal.has_dotted('gecos_info'):
                    del node.normal['gecos_info']
                    node.save()

        logger.info('Checking tree...')
        # Look for the root of the nodes tree
        root_nodes = self.db.nodes.find({"path": "root"})
        for root in root_nodes:
            self.check_node_and_subnodes(root)

        logger.info(
            'Checking nodes that are outside the tree (missing OUs in the PATH)...'
        )
        # Check node path
        nodes = self.db.nodes.find({})
        for node in nodes:
            if not 'path' in node:
                logger.error('Node with ID: %s has no "path" attribute!' %
                             (str(node['_id'])))
                continue

            if not 'name' in node:
                logger.error('Node with ID: %s has no "name" attribute!' %
                             (str(node['_id'])))
                continue

            if not 'type' in node:
                logger.error('Node with ID: %s has no "type" attribute!' %
                             (str(node['_id'])))
                continue

            for ou_id in node['path'].split(','):
                if ou_id == 'root':
                    continue

                ou = self.db.nodes.find_one({"_id": ObjectId(ou_id)})
                if not ou:
                    logger.error(
                        'Can\'t find OU %s that belongs to node path (node ID: %s NAME: %s)'
                        % (str(ou_id), str(node['_id']), node['name']))
                    continue

        logger.info('Checking chef node references...')
        # Check the references to Chef nodes
        computers = self.db.nodes.find({"type": "computer"})
        for computer in computers:
            if "node_chef_id" in computer:
                # Check Chef node
                computer_node = ChefNode(computer['node_chef_id'], self.api)
                logger.info("Computer: %s Chef ID: %s" %
                            (computer['name'], computer['node_chef_id']))
                if not computer_node.exists:
                    logger.error("No Chef node with ID %s!" %
                                 (computer['node_chef_id']))

            else:
                logger.error("No Chef ID in '%s' computer!" %
                             (computer['name']))

        logger.info(
            'Checking MongoDB computer references and deprecated policies...')
        # Check the references to computer nodes
        for node_id in ChefNode.list():
            found = False
            computers = self.db.nodes.find({"node_chef_id": node_id})
            node_path = None
            for computer in computers:
                found = True
                node_path = computer['path']

            computer_node = ChefNode(node_id, self.api)
            if not found:
                pclabel = "(No OHAI-GECOS data in the node)"
                try:
                    pclabel = "(pclabel = %s)" % (
                        computer_node.attributes.get_dotted(
                            'ohai_gecos.pclabel'))
                except KeyError:
                    pass

                logger.error("No computer node for Chef ID: '%s' %s!" %
                             (node_id, pclabel))
                logger.warn(
                    "Possible cause: The node has been deleted in Gecos Control Center but not in Chef server, either because it was in use at that time or for another unknown reason."
                )

            # Check default data for chef node
            if not computer_node.default.to_dict(
            ) or not computer_node.attributes.has_dotted('gecos_ws_mgmt'):
                logger.info(
                    "FIXED: For an unknown reason Chef node: %s has no default attributes."
                    % (node_id))
                computer_node.default = default_data
                computer_node.save()

            # Check "updated_by" field
            attributes = computer_node.normal.to_dict()
            updated, updated_attributes = self.check_updated_by_field(
                node_id, None, attributes)
            if updated:
                computer_node.normal = updated_attributes
                computer_node.save()

            updated, updated_attributes = self.check_chef_node_policies(
                node_id, None, attributes)
            if updated:
                computer_node.normal = updated_attributes
                computer_node.save()

            if node_path is not None:
                # Check "gecos_path_ids" field
                if not computer_node.attributes.has_dotted(
                        'gecos_path_ids'
                ) or computer_node.attributes.get_dotted(
                        'gecos_path_ids') != node_path:
                    logger.info(
                        "FIXED: gecos_path_ids attribute in node: %s." %
                        (node_id))
                    computer_node.attributes.set_dotted(
                        'gecos_path_ids', node_path)
                    computer_node.save()

                # Check "gecos_path_names" field
                node_path_names = 'root'
                for elm in node_path.split(','):
                    if elm == 'root':
                        continue
                    ou = self.db.nodes.find_one({'_id': ObjectId(elm)})
                    node_path_names += ',' + ou['name']

                if not computer_node.attributes.has_dotted(
                        'gecos_path_names'
                ) or computer_node.attributes.get_dotted(
                        'gecos_path_names') != node_path_names:
                    logger.info(
                        "FIXED: gecos_path_names attribute in node: %s." %
                        (node_id))
                    computer_node.attributes.set_dotted(
                        'gecos_path_names', node_path_names)
                    computer_node.save()

        logger.info('END ;)')
Example #2
0
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                            toChefUsername(self.options.chef_username),
                            self.options.chef_pem, False, self.settings.get('chef.version'))

        self.db = self.pyramid.db
        self.referenced_data_type = {}
        self.referenced_data_type['storage_can_view'] = 'storage'
        self.referenced_data_type['repository_can_view'] = 'repository'
        self.referenced_data_type['printer_can_view'] = 'printer'
        
        # Get gecos_ws_mgmt cookbook default data structure
        default_data_dotted_keys = {}
        default_data = self.get_default_data(default_data_dotted_keys)
        if default_data is None:
            logger.error("Can't find default data!")
            return
        
        # Get all the policies structures
        logger.info('Getting all the policies structures from database...')
        dbpolicies = self.db.policies.find()
        self.policiesdata = {}
        self.slug_check = {}
        for policy in dbpolicies:
            logger.debug('Addig to dictionary: %s => %s'%(policy['_id'], json.dumps(policy['schema'])))
            self.policiesdata[str(policy['_id'])] = policy
            
            # Check policy slug field (must be unique)
            if policy['slug'] in self.slug_check:
                logger.error("There are more than one policy with '%s' slug!"%(policy['slug']))
            else:
                self.slug_check[policy['slug']] = policy
                
            # Check policy serialization
            try:
                logger.debug('Serialized policy: %s'%(json.dumps(Policy().serialize(policy))))
            except Exception as err:
                logger.error('Policy %s with slug %s can\'t be serialized: %s'%(policy['_id'], policy['slug'], str(err)))
                logger.warn('Possible cause: New fields in models (Colander) but the import_policies command has not yet been executed to update schema.')
                
        if self.options.clean_inheritance:
            logger.info('Cleaning inheritance field...')
            self.db.nodes.update({"inheritance": { '$exists': True }}, { '$unset': { "inheritance": {'$exist': True } }}, multi=True)
        
        logger.info('Checking tree...')
        # Look for the root of the nodes tree
        root_nodes = self.db.nodes.find({"path" : "root"})    
        for root in root_nodes:        
            self.check_node_and_subnodes(root)
        
        logger.info('Checking nodes that are outside the tree (missing OUs in the PATH)...')
        # Check node path
        nodes = self.db.nodes.find({})    
        for node in nodes:
            if not 'path' in node:
                logger.error('Node with ID: %s has no "path" attribute!'%(str(node['_id'])))                
                continue

            if not 'name' in node:
                logger.error('Node with ID: %s has no "name" attribute!'%(str(node['_id'])))                
                continue

            if not 'type' in node:
                logger.error('Node with ID: %s has no "type" attribute!'%(str(node['_id'])))                
                continue

                
            for ou_id in node['path'].split(','):
                if ou_id == 'root':
                    continue
                    
                ou = self.db.nodes.find_one({ "_id" : ObjectId(ou_id) })    
                if not ou:
                    logger.error('Can\'t find OU %s that belongs to node path (node ID: %s NAME: %s)'%(str(ou_id), str(node['_id']), node['name']))                
                    continue        
        
        logger.info('Checking chef node references...')
        # Check the references to Chef nodes
        computers = self.db.nodes.find({"type" : "computer"})    
        for computer in computers:  
            if "node_chef_id" in computer:
                # Check Chef node
                computer_node = ChefNode(computer['node_chef_id'], self.api)
                logger.info("Computer: %s Chef ID: %s"%(computer['name'], computer['node_chef_id']))
                if not computer_node.exists:
                    logger.error("No Chef node with ID %s!"%(computer['node_chef_id']))
                
            else:
                logger.error("No Chef ID in '%s' computer!"%(computer['name']))

                
        logger.info('Checking MongoDB computer references...')
        # Check the references to computer nodes
        for node_id in ChefNode.list():
            found = False
            computers = self.db.nodes.find({"node_chef_id" : node_id})    
            for computer in computers:   
                found = True
                
            computer_node = ChefNode(node_id, self.api)
            if not found:
                pclabel = "(No OHAI-GECOS data in the node)"
                try:
                    pclabel = "(pclabel = %s)"%( computer_node.attributes.get_dotted('ohai_gecos.pclabel') )
                except KeyError:
                    pass
                        
                logger.error("No computer node for Chef ID: '%s' %s!"%(node_id, pclabel))
                logger.warn("Possible cause: The node has been deleted in Gecos Control Center but not in Chef server, either because it was in use at that time or for another unknown reason.")
        
            # Check default data for chef node
            if not computer_node.default.to_dict() or not computer_node.attributes.has_dotted('gecos_ws_mgmt'):
                logger.info("FIXED: For an unknown reason Chef node: %s has no default attributes."%(node_id))
                computer_node.default = default_data
                computer_node.save()
                
            # Check "updated_by" field
            atrributes = computer_node.normal.to_dict()
            updated, updated_attributes = self.check_updated_by_field(node_id, None, atrributes)
            if updated:
                computer_node.normal = atrributes
                computer_node.save()
            
        
        logger.info('END ;)')