def _is_node_busy_and_reserve_it(node_id, api, controller_requestor='gcc'): settings = get_current_registry().settings seconds_block_is_busy = int(settings.get('chef.seconds_block_is_busy')) time_to_exp = datetime.timedelta(seconds=seconds_block_is_busy) node = ChefNode(node_id, api) current_use_node = node.attributes.get(USE_NODE, {}) current_use_node_control = current_use_node.get('control', None) current_use_node_exp_date = current_use_node.get('exp_date', None) if current_use_node_exp_date: current_use_node_exp_date = json.loads( current_use_node_exp_date, object_hook=json_util.object_hook) current_use_node_exp_date = current_use_node_exp_date.astimezone( pytz.utc).replace(tzinfo=None) now = datetime.datetime.now() if now - current_use_node_exp_date > time_to_exp: current_use_node_control = None if current_use_node_control == controller_requestor: return (node, False) elif current_use_node_control is None: exp_date = datetime.datetime.utcnow() + time_to_exp node.attributes.set_dotted( USE_NODE, { 'control': controller_requestor, 'exp_date': json.dumps(exp_date, default=json_util.default) }) node.save() node2 = ChefNode(node.name, api) # second check current_use_node2 = node2.attributes.get(USE_NODE, {}) current_use_control2 = current_use_node2.get('control', None) if current_use_control2 == controller_requestor: return (node2, False) return (node, True)
def register_node(api, node_id, ou, collection_nodes): from gecoscc.models import Computer node = ChefNode(node_id, api) if not node.attributes.to_dict(): return False try: computer_name = node.attributes.get_dotted('ohai_gecos.pclabel') except KeyError: computer_name = node_id comp_model = Computer() computer = comp_model.serialize({ 'path': '%s,%s' % (ou['path'], unicode(ou['_id'])), 'name': computer_name, 'type': 'computer', 'source': ou.get('source', SOURCE_DEFAULT), 'node_chef_id': node_id }) del computer['_id'] if check_unique_node_name_by_type_at_domain(collection_nodes, computer): if collection_nodes.find_one({'node_chef_id': node_id}): return 'duplicated-node-id' node_id = collection_nodes.insert(computer) return node_id return 'duplicated'
def update_node(api, node_id, ou, collection_nodes): from gecoscc.models import Computer node = ChefNode(node_id, api) if not node.attributes.to_dict(): return False try: computer_name = node.attributes.get_dotted('ohai_gecos.pclabel') except KeyError: computer_name = node_id comp_model = Computer() computer = comp_model.serialize({ 'path': '%s,%s' % (ou['path'], unicode(ou['_id'])), 'name': computer_name, 'type': 'computer', 'source': ou.get('source', SOURCE_DEFAULT), 'node_chef_id': node_id }) del computer['_id'] node_id = collection_nodes.update({'node_chef_id': node_id}, computer) return node_id
def openrc(self): """ Opens a new shell with variables loaded for novaclient """ user_name = self.environment.override_attributes['keystone'][ 'admin_user'] user = self.environment.override_attributes['keystone']['users'][ user_name] password = user['password'] tenant = user['roles'].keys()[0] controller = next(self.search_role('controller')) url = ChefNode(controller.name).normal['keystone']['publicURL'] strategy = 'keystone' openrc = { 'OS_USERNAME': user_name, 'OS_PASSWORD': password, 'OS_TENANT_NAME': tenant, 'OS_AUTH_URL': url, 'OS_AUTH_STRATEGY': strategy, 'OS_NO_CACHE': '1' } for key in openrc.keys(): os.putenv(key, openrc[key]) os.system(os.environ['SHELL'])
def post(self): node_id = self.request.POST.get('node_id') if node_id is None: return {'ok': False, 'message': 'Missing node ID'} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) # create chef client chef_client = ChefClient(node_id, api) if chef_client.exists: return {'ok': False, 'message': 'This client already exists'} chef_client = ChefClient.create(node_id, api) # Prepare the API for this client chef_url = settings.get('chef.url') chef_version = settings.get('chef.version') chef_ssl_verify = settings.get('chef.ssl.verify') if chef_ssl_verify == 'False' or chef_ssl_verify == 'True': chef_ssl_verify = bool(chef_ssl_verify) api = ChefAPI(chef_url, chef_client.private_key.encode(), node_id, chef_version, ssl_verify = False) # create chef node chef_node = ChefNode(node_id, api) if chef_node.exists: return {'ok': False, 'message': 'This node already exists'} chef_node.save() return {'ok': True, 'message': 'Node and client have been added', 'client_private_key': chef_client.private_key}
def from_chef_environment(cls, environment): """ Rebuilds a Deployment given a chef environment :param environment: name of environment :type environment: string :rtype: Chef """ local_api = autoconfigure() env = ChefEnvironment(environment, api=local_api) override = env.override_attributes default = env.default_attributes chef_auth = override.get('remote_chef', None) remote_api = None if chef_auth and chef_auth["key"]: remote_api = ChefServer._remote_chef_api(chef_auth) renv = ChefEnvironment(environment, api=remote_api) override = renv.override_attributes default = renv.default_attributes environment = MonsterChefEnvironment(env.name, local_api, description=env.name, default=default, override=override, remote_api=remote_api) name = env.name deployment_args = override.get('deployment', {}) features = deployment_args.get('features', {}) os_name = deployment_args.get('os_name', None) branch = deployment_args.get('branch', None) status = deployment_args.get('status', "provisioning") product = deployment_args.get('product', None) provisioner_name = deployment_args.get('provisioner', "razor") provisioner = get_provisioner(provisioner_name) deployment = cls.deployment_config(features, name, os_name, branch, environment, provisioner, status, product=product) nodes = deployment_args.get('nodes', []) for node in (ChefNode(n, local_api) for n in nodes): if not node.exists: util.logger.error("Non existant chef node:{0}".format( node.name)) continue cnode = MonsterChefNode.from_chef_node(node, deployment_args['os_name'], product, environment, deployment, provisioner, deployment_args['branch']) deployment.nodes.append(cnode) return deployment
def get(self): node_id = self.request.GET.get('node_id') if node_id is None: return {'ok': False, 'message': 'Missing node ID'} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) chef_node = ChefNode(node_id, api) if not chef_node.exists: return {'ok': False, 'message': 'This node does not exists'} else: return {'ok': True, 'message': 'This node does exists'}
def check_computers(self, ou, admin, policy): db = self.pyramid.db ou_path = '%s,%s' % (ou['path'], unicode(ou['_id'])) computers = db.nodes.find({'path': ou_path, 'type': 'computer'}) api = get_chef_api(self.settings, admin) computers_error = {} policy_attr_to_check = self.get_policy_attr_to_check(policy) for computer in computers: node_id = computer.get('node_chef_id', None) if not node_id: computers_error[computer['name']] = 'does not node_chef_id' node = ChefNode(node_id, api) if self.check_node(policy_attr_to_check, node): print '%s ok' % computer['name'] else: computers_error[computer['name']] = self.error return computers_error
def delete(self): node_id = self.request.GET.get('node_id') if node_id is None: return {'ok': False, 'message': 'Missing node ID'} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) chef_node = ChefNode(node_id, api) if not chef_node.exists: return {'ok': False, 'message': 'This node does not exists'} chef_node.delete() chef_client = ChefClient(node_id, api) if not chef_client.exists: return {'ok': False, 'message': 'This client does not exists'} chef_client.delete() return {'ok': True, 'message': 'Node and client have been deleted'}
def get(self): result = super(ComputerResource, self).get() if not result.get('node_chef_id', None): return result try: api = get_chef_api(self.request.registry.settings, self.request.user) computer_node = ChefNode(result['node_chef_id'], api) ohai = to_deep_dict(computer_node.attributes) cpu = ohai.get('cpu', {}).get('0', {}) dmi = ohai.get('dmi', {}) result.update({ 'ohai': ohai, 'users': ','.join([ i['username'] for i in ohai.get('ohai_gecos', {}).get('users', []) ]), 'uptime': ohai.get('uptime', ''), 'ipaddress': ohai.get('ipaddress', ''), 'cpu': '%s %s' % (cpu.get('vendor_id', ''), cpu.get('model_name', '')), 'product_name': dmi.get('system', {}).get('product_name', ''), 'manufacturer': dmi.get('system', {}).get('manufacturer', ''), 'ram': ohai.get('memory', {}).get('total', ''), 'lsb': ohai.get('lsb', {}), 'kernel': ohai.get('kernel', {}), 'filesystem': ohai.get('filesystem', {}), }) except (urllib2.URLError, ChefError, ChefServerError): pass return result
def check_users(self, ou, admin, policy): db = self.pyramid.db ou_path = '%s,%s' % (ou['path'], text_type(ou['_id'])) users = db.nodes.find({'path': ou_path, 'type': 'user'}) computers_error = {} api = get_chef_api(self.settings, admin) for user in users: computers_ids = user.get('computers', []) computers = db.nodes.find({'_id': {'$in': computers_ids}}) policy_attr_to_check = self.get_policy_attr_to_check(policy, user) for computer in computers: node_id = computer.get('node_chef_id', None) if not node_id: computers_error[computer['name']] = 'does not node_chef_id' node = ChefNode(node_id, api) if self.check_node(policy_attr_to_check, node): print('%s ok' % computer['name']) else: computers_error[ computer['name']] = self.error % (user['name']) return computers_error
def get(self): result = super(ComputerResource, self).get() node_collection = self.request.db.nodes if not result.get('node_chef_id', None): return result logger.info("/api/computers/: node_chef_id: %s" % (str(result.get('node_chef_id', None)))) try: api = get_chef_api(self.request.registry.settings, self.request.user) computer_node = ChefNode(result['node_chef_id'], api) ohai = to_deep_dict(computer_node.attributes) nodeid = result.get('_id', None) usernames = [ i['username'] for i in ohai.get('ohai_gecos', {}).get('users', []) ] users = list( node_collection.find( { "$and": [{ "$or": [{ "name": { "$in": usernames } }] }, { "type": "user" }, { "computers": { "$elemMatch": { "$eq": ObjectId(nodeid) } } }] }, { '_id': 1, 'name': 1, 'path': 1 })) # ObjectId to string for JSON serialize [d.update({'_id': str(d['_id'])}) for d in users] # Create a list of users that provides at least one user policy to this computer users_inheritance_pre = list( node_collection.find( { "$and": [{ "$or": [{ "name": { "$in": usernames } }] }, { "type": "user" }, { "computers": { "$elemMatch": { "$eq": ObjectId(nodeid) } } }] }, { '_id': 1, 'name': 1, 'path': 1, 'inheritance': 1 })) [d.update({'_id': str(d['_id'])}) for d in users_inheritance_pre] users_inheritance = [] for usr_inh in users_inheritance_pre: if 'inheritance' in usr_inh: policies_list = get_inheritance_tree_policies_list( usr_inh['inheritance'], []) if len(policies_list) > 0: users_inheritance.append(usr_inh) cpu = ohai.get('cpu', {}).get('0', {}) dmi = ohai.get('dmi', {}) # debug_mode flag for logs tab debug_mode = False try: debug_mode = computer_node.attributes.get_dotted( DEBUG_MODE_ENABLE_ATTR_PATH) except KeyError: pass # Get logs info logs_data = node_collection.find_one( { "type": "computer", "_id": ObjectId(nodeid) }, {"logs": True}) logs = {} if logs_data is not None and 'logs' in logs_data: logs_data = logs_data['logs'] date_format = locale.nl_langinfo(locale.D_T_FMT) date = datetime.datetime( *map(int, re.split('[^\d]', logs_data['date'])[:-1])) localename = locale.normalize( get_current_request().locale_name + '.UTF-8') logger.debug("/api/computers/: localename: %s" % (str(localename))) locale.setlocale(locale.LC_TIME, localename) logs['date'] = date.strftime(date_format) logger.debug("/api/computers/: date: %s" % (str(logs['date']))) logs['files'] = logs_data['files'] for filedata in logs_data['files']: # Do not send file contents del filedata['content'] # Get Help Channel info help_channel_enabled = True helpchannel_data = self.request.db.helpchannel.find({ "computer_node_id": result['node_chef_id'] }).sort([("last_modified", pymongo.DESCENDING)]).limit(6) helpchannel = {} helpchannel['current'] = None helpchannel['last'] = [] if helpchannel_data is not None: c = 0 for hcdata in helpchannel_data: # Format date date_format = locale.nl_langinfo(locale.D_T_FMT) logger.info("last_modified: {0}".format( hcdata['last_modified'])) last_mod = re.split('[^\d]', str(hcdata['last_modified'])) logger.info("last_mod: {0}".format(last_mod)) date = datetime.datetime(*map(int, last_mod[:-2])) localename = locale.normalize( get_current_request().locale_name + '.UTF-8') logger.debug("/api/computers/: localename: %s" % (str(localename))) locale.setlocale(locale.LC_TIME, localename) hcdata['last_modified'] = date.strftime(date_format) if hcdata['user_node_id']: # Format user user_data = node_collection.find_one({ "type": "user", "_id": ObjectId(hcdata['user_node_id']) }) if user_data: hcdata['user'] = user_data['name'] else: logger.error("User not found: {0}".format( hcdata['user_node_id'])) else: hcdata['user'] = '' if hcdata['adminuser_id']: # Format user user_data = self.request.db.adminusers.find_one( {"_id": ObjectId(hcdata['adminuser_id'])}) if user_data: hcdata['admin'] = user_data['username'] else: logger.error("Admin user not found: {0}".format( hcdata['adminuser_id'])) else: hcdata['admin'] = '' # Translate status info hcdata['status'] = _('Unknown status') if hcdata['action'] == 'request': hcdata['status'] = _('User is requesting support') elif hcdata['action'] == 'accepted': hcdata['status'] = _('User is requesting support') elif hcdata['action'] == 'finished user': hcdata['status'] = _('Terminated by user') elif hcdata['action'] == 'finished tech': hcdata['status'] = _('Terminated by technician') elif hcdata['action'] == 'finished error': hcdata['status'] = _( 'Terminated because of a communication error') elif hcdata['action'] == 'giving support': hcdata['status'] = _( 'The technician is giving support to the user') hcdata['_id'] = str(hcdata['_id']) if (c == 0 and hcdata['action'] == 'accepted'): helpchannel['current'] = hcdata else: helpchannel['last'].append(hcdata) c = c + 1 result.update({ 'ohai': ohai, 'users': users, # Users related with this computer 'users_inheritance': users_inheritance, # Users related with this computer that provides at least one user policy 'uptime': ohai.get('uptime', ''), #'gcc_link': ohai.get('gcc_link',True), 'ipaddress': ohai.get('ipaddress', ''), 'cpu': '%s %s' % (cpu.get('vendor_id', ''), cpu.get('model_name', '')), 'product_name': dmi.get('system', {}).get('product_name', ''), 'manufacturer': dmi.get('system', {}).get('manufacturer', ''), 'ram': ohai.get('memory', {}).get('total', ''), 'lsb': ohai.get('lsb', {}), 'kernel': ohai.get('kernel', {}), 'filesystem': ohai.get('filesystem', {}), 'debug_mode': debug_mode, 'logs': logs, 'helpchannel': helpchannel, 'help_channel_enabled': help_channel_enabled }) except (urllib2.URLError, ChefError, ChefServerError): logger.error( "/api/computers/: error getting data: node_chef_id: %s " % (str(result.get('node_chef_id', None)))) logger.error(traceback.format_exc()) return result
def save_node_and_free(node, api=None, refresh=False): if refresh and api: node = ChefNode(node.name, api) node.attributes.set_dotted(USE_NODE, {}) node.save()
def command(self): # Initialization logger.info("MIGRATION SCRIPT FOR USER_APPS_AUTOSTART POLICY") logger.info("###############################################") # Disabling InsecureRequestWarning Unverified HTTPS request requests.packages.urllib3.disable_warnings() sanitized = False ous = [] groups = [] users = [] 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.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_users (Users) policy logger.info('Getting policy schema (user_apps_autostart_res) ...') policy = self.db.policies.find_one({'slug': 'user_apps_autostart_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s' % str(schema)) logger.debug('policyId = %s' % str(policyId)) # Searching nodes with the Local Administrators policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching for nodes with applied policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info("node = %s" % str(node)) logger.info('-----------------------------------------------') logger.info('Node name = %s, mongo_id = %s' % (node['name'], str(node['_id']))) logger.info('Instance of the policy on the node: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warn('Validation error on instance = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info( 'Sanitized instance of the policy on the node AFTER calling the validate method: %s' % str(instance)) # Update mongo logger.info('Updating instance in database (mongo) ...') self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) logger.info('Recalculating policies in the node.') # Affected nodes if node['type'] == 'ou': ous.append(node) elif node['type'] == 'group': groups.append(node) elif node['type'] == 'user': users.append(node) # We only go through the highest level OUs. # Therefore, we eliminate intermediate OUs and # then do not recalculate the policies # for the same node several times. for ou in ous: parents = [ ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root' ] if any(o['_id'] in parents for o in ous): ous.remove(ou) # Users that are not under an OU or GROUP that have the migrated policy for user in users: parents = [ ObjectId(oid) for oid in user['path'].split(',') if oid != 'root' ] if any(o['_id'] in parents for o in ous): users.remove(user) elif any(user['_id'] in group['members'] for group in groups): users.remove(user) # Recalculating policies for OU for ou in ous: old = deepcopy(ou) del old["policies"][str(policyId)] object_changed(self.auth_user, 'ou', ou, old) # Recalculating policies for GROUP for group in groups: old = deepcopy(group) del old["policies"][str(policyId)] object_changed(self.auth_user, 'group', group, old) # Recalculating policies for USER for user in users: old = deepcopy(user) del old["policies"][str(policyId)] object_changed(self.auth_user, 'user', user, old) # Removing unused desktops_to_remove attribute in chef nodes logger.info('\n') logger.info( 'Removing unused desktops_to_remove attribute in chef nodes ...') for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) field_chef = '%s.users' % policy['path'] users = node.attributes.get_dotted( field_chef) if node.attributes.has_dotted(field_chef) else [] for user in users: logger.debug("user = %s" % (user)) attr_delete_path = '%s.%s.desktops_to_remove' % (field_chef, user) logger.debug('Atttribute dotted path: %s' % (attr_delete_path)) if node.attributes.has_dotted(attr_delete_path): logger.warn( "Remove 'desktops_to_remove' attribute! for user %s" % (user)) try: delete_dotted(node.attributes, attr_delete_path) node.save() except: logger.warn( "Problem deleting desktops_to_remove value from node: %s" % (node_id)) logger.warn( "You may be trying to delete a default attribute instead normal attribute: %s" % (node_id)) logger.info('Finished.')
def post(self): logger.debug('/help-channel-client/login START') # Default known message known_message = 'En un lugar de la Mancha, de cuyo nombre no quiero'\ ' acordarme, no ha mucho tiempo que vivía un hidalgo de los de'\ ' lanza en astillero, adarga antigua, rocín flaco y galgo corredor.' # Check the parameters node_id = self.request.POST.get('node_id') if not node_id: logger.error('/help-channel-client/login - No node ID') return {'ok': False, 'message': 'Please set a node id'} username = self.request.POST.get('username') if not username: logger.error('/help-channel-client/login - No username') return {'ok': False, 'message': 'Please set a username'} secret = self.request.POST.get('secret') if not secret: logger.error('/help-channel-client/login - No secret') return {'ok': False, 'message': 'Please set a secret'} hc_server = self.request.POST.get('hc_server') if not hc_server: logger.error('/help-channel-client/login - No server') return {'ok': False, 'message': 'Please set a Help Channel Server'} gcc_username = self.request.POST.get('gcc_username') if not gcc_username: logger.error('/help-channel-client/login - No admin username') return { 'ok': False, 'message': 'Please set a GCC administrator username' } self.request.user = self.request.db.adminusers.find_one( {'username': gcc_username}) if not self.request.user: return { 'ok': False, 'message': 'The admin user %s does not exists' % gcc_username } logger.debug('/help-channel-client/login node_id=%s' % (node_id)) logger.debug('/help-channel-client/login username=%s' % (username)) logger.debug('/help-channel-client/login secret=%s' % (secret)) logger.debug('/help-channel-client/login hc_server=%s' % (hc_server)) logger.debug('/help-channel-client/login gccusername=%s' % (gcc_username)) gcc_node = self.request.db.nodes.find_one({'node_chef_id': node_id}) if not gcc_node: logger.error('/help-channel-client/login - Node not found') return {'ok': False, 'message': 'Node not found in database'} can_access_to_this_path(self.request, self.request.db.nodes, gcc_node, ou_type='ou_remote') # Remote OUs gcc_user = self.request.db.nodes.find_one({ 'type': 'user', 'name': username }) if not gcc_user: logger.error('/help-channel-client/login - User not found') return {'ok': False, 'message': 'User not found in database'} try: # Check the secret message api = get_chef_api(self.request.registry.settings, self.request.user) chef_client = ChefClient(node_id, api) if not chef_client.exists: logger.error('/help-channel-client/login - Client not found') return {'ok': False, 'message': 'This client does not exists'} chef_node = ChefNode(node_id, api) if not chef_node.exists: logger.error( '/help-channel-client/login - Chef node not found') return { 'ok': False, 'message': 'This chef node does not exists' } client_certificate = chef_client.certificate public_key = RSA.importKey(client_certificate) decrypted = public_key.encrypt(bytes.fromhex(secret), 0)[0] decrypted = decrypted.decode("utf-8") known_message_setting = self.request.registry.settings.get( 'helpchannel.known_message') if known_message_setting is not None: known_message = known_message_setting if decrypted != known_message: logger.error('/help-channel-client/login - Bad secret') return {'ok': False, 'message': 'Bad secret'} # Login successful, generate the token! server_address = self.request.registry.settings.get( 'server_address', 'UNKNOWN') if server_address == 'UNKNOWN': server_address = os.getenv('HOSTNAME', 'UNKNOWN') # - Token generation min_char = 8 max_char = 12 allchar = string.ascii_letters + string.digits token = ''.join( choice(allchar) for _ in range(randint(min_char, max_char))) self.request.db.helpchannel.insert_one({ 'last_modified': datetime.datetime.utcnow(), 'action': 'request', 'computer_node_id': node_id, 'computer_node_path': gcc_node['path'], 'user_node_id': str(gcc_user['_id']), 'user_node_path': gcc_user['path'], 'adminuser_id': False, 'adminuser_ou_managed': False, 'adminuser_is_superuser': False, 'gecos_cc_server': server_address, 'helpchannel_server': hc_server, 'token': token }) logger.info('/help-channel-client/login - token: %s' % (token)) return {'ok': True, 'token': token} except (urllib.error.URLError, ChefError, ChefServerError): pass logger.error('/help-channel-client/login - UNKNOWN') return {'ok': False, 'message': 'Unknown error'}
def command(self): # Initialization sanitized = False computers = set() 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.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_admin_users_res (Local Administrators) policy logger.info( 'Getting Local Administrators (local_admin_users_res) policy ...') policy = self.db.policies.find_one({'slug': 'local_admin_users_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s' % str(schema)) logger.info('Id.policy = %s' % str(policyId)) # Searching nodes with the Local Administrators policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching nodes with the Local Administrators policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info('Node name = %s, _id = %s' % (node['name'], str(node['_id']))) logger.info('Instance before validate method: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warning('Validation error on instance = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance: %s' % str(instance)) # Update mongo self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) # Affected nodes if node['type'] == 'ou': result = list( self.db.nodes.find( { 'path': get_filter_nodes_belonging_ou( node['_id']), 'type': 'computer' }, {'_id': 1})) logger.info('OU computers = %s' % str(result)) elif node['type'] == 'group': result = list( self.db.nodes.find( { '_id': { '$in': node['members'] }, 'type': 'computer' }, {'_id': 1})) logger.info('GROUP computers = %s' % str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s' % str(result)) [computers.add(str(n['_id'])) for n in result] # Removing unused local_admin_remove_list attribute in chef nodes for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) attr_dotted = policy['path'] + '.local_admin_remove_list' logger.info('Atttribute dotted path: %s' % (attr_dotted)) if node.attributes.has_dotted(attr_dotted): logger.info("Remove 'local_admin_remove_list' attribute!") try: logger.info( "node.attributes = %s" % str(node.attributes['gecos_ws_mgmt']['misc_mgmt'] ['local_admin_users_res'].to_dict())) delete_dotted(node.attributes, attr_dotted) node.save() except: logger.warn( "Problem deleting local_admin_remove_list value from node: %s" % (node_id)) logger.warn( "You may be trying to delete a default attribute instead normal attribute: %s" % (node_id)) for computer in computers: logger.info('computer = %s' % str(computer)) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) logger.info('Finished.')
def command(self): db = self.pyramid.db ou = db.nodes.find_one({'_id': ObjectId(self.options.ou_id)}) if not ou: print 'Error OU does not exists' return comp = db.nodes.find_one({'_id': ObjectId(self.options.comp_id)}) if not comp: print 'Error computer does not exists' return node_id = comp.get('node_chef_id', None) if not comp: print 'Error this computer has not node_chef_id' return policies = comp.get('policies', None) if policies != {}: print 'Error this computer should not have any policies' return admin = db.adminusers.find_one({'username': self.options.gcc_username}) if not admin: print 'Error this admin does not exists' return elif not admin.get('is_superuser', None): print 'You need a super admin' return number_nodes = int(self.options.number) api = get_chef_api(self.settings, admin) node = ChefNode(node_id, api) for i in range(number_nodes): new_node_name = '%s-%s' % (self.options.prefix, i) new_node = ChefNode(new_node_name, api) for attr in node.to_dict().keys(): if hasattr(node, attr) and attr != 'name': if attr == 'automatic': automatic_dict = node.automatic.to_dict() automatic_dict['ohai_gecos']['pclabel'] = new_node_name user1 = 'user.name-%s-1' % new_node_name user2 = 'user.name-%s-2' % new_node_name automatic_dict['ohai_gecos']['users'] = [{'username': user1, 'home': '/home/%s' % user1, 'gid': 1000, 'sudo': False, 'uid': 1000}, {'username': user2, 'home': '/home/%s' % user2, 'gid': 1000, 'sudo': False, 'uid': 1001}] automatic = NodeAttributes(automatic_dict) setattr(new_node, attr, automatic) elif attr == 'normal': node.normal.set_dotted('ohai_gecos', {}) else: setattr(new_node, attr, getattr(node, attr)) new_node.save() print 'Created %s at chef' % new_node_name res = requests.post('%s/register/computer/' % self.options.gcc_url, {'ou_id': self.options.ou_id, 'node_id': new_node_name}, auth=(self.options.gcc_username, self.options.gcc_password)) if res.ok and res.json()['ok']: print 'Created %s at gcc' % new_node_name elif res.ok and not res.json()['ok']: print 'Error %s at gcc' % new_node_name print '\t %s' % res.json()['message'] else: print 'Unknow error %s at gcc' % new_node_name res = requests.put('%s/chef/status/' % self.options.gcc_url, {'node_id': new_node_name, 'gcc_username': self.options.gcc_username}) if res.ok and res.json()['ok']: print 'Chef client %s' % new_node_name elif res.ok and not res.json()['ok']: print 'Error %s at chef client' % new_node_name print '\t %s' % res.json()['message'] else: print 'Unknow error %s at chef client' % new_node_name waiting_to_celery(db)
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 check_user_data(self, user): if user['type'] != 'user': raise ValueError('user must be an user') if ((not 'email' in user or user['email'] == '') and (not 'first_name' in user or user['first_name'] == '') and (not 'last_name' in user or user['last_name'] == '')): # Nothing to do return computers = self.db.nodes.find_one({"_id": ObjectId(user['_id']) })['computers'] for computer_id in computers: computer = self.db.nodes.find_one({"_id": ObjectId(computer_id)}) if "node_chef_id" in computer: # Check Chef node node = ChefNode(computer['node_chef_id'], self.api) logger.info("Computer: %s Chef ID: %s" % (computer['name'], computer['node_chef_id'])) if not node.exists: logger.error("No Chef node with ID %s!" % (computer['node_chef_id'])) else: if not node.normal.has_dotted('gecos_info'): node.normal.set_dotted('gecos_info', {}) if not node.normal.has_dotted('gecos_info.users'): node.normal.set_dotted('gecos_info.users', {}) username = get_username_chef_format(user) if not node.normal.has_dotted('gecos_info.users.%s' % (username)): node.normal.set_dotted( 'gecos_info.users.%s' % (username), {}) updated = False if (not node.normal.has_dotted( 'gecos_info.users.%s.email' % (username)) or node.normal.get_dotted( 'gecos_info.users.%s.email' % (username)) != user['email']): node.normal.set_dotted( 'gecos_info.users.%s.email' % (username), user['email']) updated = True if (not node.normal.has_dotted( 'gecos_info.users.%s.firstName' % (username)) or node.normal.get_dotted( 'gecos_info.users.%s.firstName' % (username)) != user['first_name']): node.normal.set_dotted( 'gecos_info.users.%s.firstName' % (username), user['first_name']) updated = True if (not node.normal.has_dotted( 'gecos_info.users.%s.lastName' % (username)) or node.normal.get_dotted( 'gecos_info.users.%s.lastName' % (username)) != user['last_name']): node.normal.set_dotted( 'gecos_info.users.%s.lastName' % (username), user['last_name']) updated = True if updated: logger.info( "Updating user %s data in computer: %s Chef ID: %s" % (user['name'], computer['name'], computer['node_chef_id'])) node.save() else: logger.error("No Chef ID in '%s' computer!" % (computer['name']))
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.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') return self.db = self.pyramid.db ous = [] groups = [] computers = [] # Get packages policy ID packages_policy = self.db.policies.find_one({"slug": "package_res"}) if packages_policy is None: logger.error('Can\'t detect "package_res" policy!') return if 'pkgs_to_remove' in packages_policy["schema"]["properties"]: logger.error( "The 'package_res' policy in the system is deprecated, please update to new package policy!" ) return logger.info('Packages policy ID: %s' % (str(packages_policy['_id']))) # Get all nodes with old package policy data logger.info('Getting all nodes with old package policy data...') path_to_find = "policies.%s.pkgs_to_remove" % (str( packages_policy['_id'])) old_policy_nodes = self.db.nodes.find({ '$query': { path_to_find: { '$exists': True } }, '$orderby': { "path": 1 } }) updated_nodes = [] for node in old_policy_nodes: logger.info('Updating node %s ...' % (str(node['_id']))) updated_nodes.append(str(node['_id'])) logger.debug('Packages to add: %s' % (str(node['policies'][str( packages_policy['_id'])]['package_list']))) logger.debug('Packages to remove: %s' % (str(node['policies'][str( packages_policy['_id'])]['pkgs_to_remove']))) # Join the lists package_list = [] for package_name in node['policies'][str( packages_policy['_id'])]['package_list']: package_list.append({ 'name': package_name, 'version': 'current', 'action': 'add' }) for package_name in node['policies'][str( packages_policy['_id'])]['pkgs_to_remove']: package_list.append({ 'name': package_name, 'version': 'current', 'action': 'remove' }) if 'pkgs_to_remove' in node['policies'][str( packages_policy['_id'])]: del node['policies'][str( packages_policy['_id'])]['pkgs_to_remove'] node['policies'][str( packages_policy['_id'])]['package_list'] = package_list # Update policies self.db.nodes.update({'_id': node['_id']}, {'$set': { 'policies': node['policies'] }}) logger.debug('Joined list: %s' % (str(node['policies'][str( packages_policy['_id'])]['package_list']))) if node['type'] == 'ou': ous.append(node) elif node['type'] == 'group': groups.append(node) elif node['type'] == 'computer': computers.append(node) logger.info('%s nodes were updated!' % (len(updated_nodes))) # We only go through the highest level OUs. # Therefore, we eliminate intermediate OUs and # then do not recalculate the policies # for the same node several times. for ou in ous: parents = [ ObjectId(oid) for oid in ou['path'].split(',') if oid != 'root' ] if any(o['_id'] in parents for o in ous): ous.remove(ou) # Users that are not under an OU or GROUP that have the migrated policy for computer in computers: parents = [ ObjectId(oid) for oid in computer['path'].split(',') if oid != 'root' ] if any(o['_id'] in parents for o in ous): computers.remove(computer) elif any(computer['_id'] in group['members'] for group in groups): computers.remove(computer) # Recalculating policies for OU for ou in ous: old = deepcopy(ou) del old["policies"][str(packages_policy['_id'])] object_changed(self.auth_user, 'ou', ou, old) # Recalculating policies for GROUP for group in groups: old = deepcopy(group) del old["policies"][str(packages_policy['_id'])] object_changed(self.auth_user, 'group', group, old) # Recalculating policies for USER for computer in computers: old = deepcopy(computer) del old["policies"][str(packages_policy['_id'])] object_changed(self.auth_user, 'computer', computer, old) # Recalculate policies for Chef nodes for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) if ("gecos_ws_mgmt" in node.attributes) and ( "software_mgmt" in node.attributes["gecos_ws_mgmt"]) and ( "package_res" in node.attributes["gecos_ws_mgmt"]["software_mgmt"]): if "pkgs_to_remove" in node.attributes["gecos_ws_mgmt"][ "software_mgmt"]["package_res"]: logger.debug( "Chef node %s contains a pkgs_to_remove value!" % (node_id)) # Remove pkgs_to_remove from mongodb node logger.info("Remove 'pkgs_to_remove' attribute!") try: del node.attributes["gecos_ws_mgmt"]["software_mgmt"][ "package_res"]["pkgs_to_remove"] node.save() except: logger.warn( "Problem deleting pkgs_to_remove value from node: %s" % (node_id)) if not "package_list" in node.attributes["gecos_ws_mgmt"][ "software_mgmt"]["package_res"]: logger.error( "Chef node %s doesn\'t contains a package_list value!" % (node_id)) continue package_list = node.attributes["gecos_ws_mgmt"][ "software_mgmt"]["package_res"]["package_list"] for element in package_list: if not 'action' in element: logger.debug( 'Chef node: %s doesn\'t have an action value in package_res! (package_list:%s)' % (node_id, str(package_list))) break # Final check bad_nodes = Search('node', "pkgs_to_remove:*", rows=1000, start=0, api=self.api) for node in bad_nodes: logger.warn('Detected bad node: %s' % (node.object.name)) gecos_node = self.db.nodes.find_one( {"node_chef_id": node.object.name}) if gecos_node is None: logger.warn('Can\'t find node in MongoDB for: %s' % (node.object.name)) else: logger.warn( 'For an unknown reason a computer called %s wasn\'t updated!' % (gecos_node['name'])) logger.info('END ;)')
def command(self): # Initialization logger.info("MIGRATION SCRIPT FOR FILES LIST POLICY") logger.info("######################################") # Disabling InsecureRequestWarning Unverified HTTPS request requests.packages.urllib3.disable_warnings() sanitized = False computers = set() 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.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_file (File list) policy logger.info('Getting policy schema (local_file_res) ...') policy = self.db.policies.find_one({'slug': 'local_file_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s' % str(schema)) logger.debug('policyId = %s' % str(policyId)) # Searching nodes with the File List policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching for nodes with applied policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.debug("node = %s" % str(node)) logger.info('-----------------------------------------------') logger.info('Node name = %s, mongo_id = %s' % (node['name'], str(node['_id']))) logger.info('Instance of the policy on the node: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warn('Validation error on instance: instance = %s' % str(instance)) logger.warn( 'Validation error on instance: message error = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info( 'Sanitized instance of the policy on the node AFTER calling the validate method: %s' % str(instance)) # Update mongo logger.info('Updating instance in database (mongo) ...') self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) logger.info('Recalculating policies in the node.') # Affected nodes if node['type'] == 'ou': result = list( self.db.nodes.find( { 'path': get_filter_nodes_belonging_ou( node['_id']), 'type': 'computer' }, {'_id': 1})) logger.info('OU computers = %s' % str(result)) elif node['type'] == 'group': result = list( self.db.nodes.find( { '_id': { '$in': node['members'] }, 'type': 'computer' }, {'_id': 1})) logger.info('GROUP computers = %s' % str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s' % str(result)) [computers.add(str(n['_id'])) for n in result] for computer in computers: logger.info( 'Applying policies to COMPUTER. For more information, see "gecosccui-celery.log" file' ) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=True) # Removing unused attributes (copy_files, delete_files) in chef nodes logger.info('\n') attrs = [ "%s.copy_files" % (policy['path']), "%s.delete_files" % (policy['path']) ] logger.info('Removing unused attributes %s in chef nodes ...' % attrs) logger.info('\n') for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) for attr in attrs: try: if node.attributes.has_dotted(attr): logger.warn("Remove %s attribute!" % attr) delete_dotted(node.attributes, attr) node.save() except: logger.warn( "Problem deleting attribute %s value from node: %s" % (attr, node_id)) logger.warn( "You may be trying to delete a default attribute instead normal attribute: %s" % (node_id)) logger.info('Finished.')
def command(self): from gecoscc.api.chef_status import USERS_OLD, USERS_OHAI # 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 # Check administrator user auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) # Recorriendo todos los nodos for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) try: if node.attributes.get_dotted(USERS_OLD): delete_dotted(node.attributes, USERS_OLD) node.save() except KeyError: logger.warn("Not found attribute: %s" % (USERS_OLD)) except: logger.warn( "Problem deleting users_old attribute from node: %s" % (node_id)) # Updating users list computer = self.db.nodes.find_one({ 'node_chef_id': node_id, 'type': 'computer' }) if not computer: logger.error('This node does not exist (mongodb)') continue chef_node_usernames = set([ d['username'] for d in node.attributes.get_dotted(USERS_OHAI) ]) gcc_node_usernames = set([ d['name'] for d in self.db.nodes.find( { 'type': 'user', 'computers': { '$in': [computer['_id']] } }, { '_id': 0, 'name': 1 }) ]) users_recalculate_policies = [] users_remove_policies = [] # Users added/removed ? if set.symmetric_difference(chef_node_usernames, gcc_node_usernames): logger.info("Users added/removed found.") # Add users or vinculate user to computer if already exists addusers = set.difference(chef_node_usernames, gcc_node_usernames) for add in addusers: logger.info("Added user: %s" % (add)) user = self.db.nodes.find_one({ 'name': add, 'type': 'user', 'path': get_filter_in_domain(computer) }) if not user: user_model = User() user = user_model.serialize({ 'name': add, 'path': computer.get('path', ''), 'type': 'user', 'lock': computer.get('lock', ''), 'source': computer.get('source', '') }) user = update_computers_of_user( self.db, user, self.api) del user['_id'] user_id = self.db.nodes.insert(user) user = self.db.nodes.find_one({'_id': user_id}) users_recalculate_policies.append(user) else: computers = user.get('computers', []) if computer['_id'] not in computers: computers.append(computer['_id']) self.db.nodes.update( {'_id': user['_id']}, {'$set': { 'computers': computers }}) users_recalculate_policies.append(user) add_computer_to_user(computer['_id'], user['_id']) # Removed users delusers = set.difference(gcc_node_usernames, chef_node_usernames) for delete in delusers: logger.info("Deleted user: %s" % (delete)) user = self.db.nodes.find_one({ 'name': delete, 'type': 'user', 'path': get_filter_in_domain(computer) }) computers = user['computers'] if user else [] if computer['_id'] in computers: users_remove_policies.append(deepcopy(user)) computers.remove(computer['_id']) self.db.nodes.update( {'_id': user['_id']}, {'$set': { 'computers': computers }}) for user in users_recalculate_policies: apply_policies_to_user(self.db.nodes, user, auth_user) for user in users_remove_policies: remove_policies_of_computer(user, computer, auth_user)