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 ;)')
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 ;)')