def get(self): result = super(ComputerResource, self).get() node_collection = self.request.db.nodes 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) 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', {}) 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', {}), }) except (urllib2.URLError, ChefError, ChefServerError): pass return result
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 object_moved(self, user, objnew, objold): api = get_chef_api(self.app.conf, user) try: func = globals()['apply_policies_to_%s' % objnew['type']] except KeyError: raise NotImplementedError func(self.db.nodes, objnew, user, api, initialize=True)
def post(self): ou_id = self.request.POST.get('ou_id') node_id = self.request.POST.get('node_id') ou = None if ou_id: ou = self.collection.find_one({'_id': ObjectId(ou_id), 'type': 'ou'}) else: ou_availables = self.request.user.get('ou_availables') if isinstance(ou_availables, list) and len(ou_availables) > 0: ou = self.collection.find_one({'_id': {'$in': [ObjectId(ou_ava_id) for ou_ava_id in ou_availables]}, 'type': 'ou', 'path': {'$ne': 'root'}}) if not ou: return {'ok': False, 'message': 'Ou does not exists'} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) computer_id = register_node(api, node_id, ou, self.collection) if not computer_id: return {'ok': False, 'message': 'Node does not exist (in chef)'} elif computer_id == 'duplicated': return {'ok': False, 'message': 'There is another node with this name (in gcc)'} elif computer_id == 'duplicated-node-id': return {'ok': False, 'message': 'There is another node with this node chef id (in gcc)'} computer = self.collection.find_one({'_id': computer_id}) apply_policies_to_computer(self.collection, computer, self.request.user) update_tree(computer['path']) return {'ok': True}
def put(self): """ Reserve the Chef node before running the Chef client """ # Check the parameters node_id = self.request.POST.get('node_id') username = self.request.POST.get('gcc_username') if not node_id: return {'ok': False, 'message': 'Please set a node id (node_id)'} if not username: return {'ok': False, 'message': 'Please set a admin username (gcc_username)'} self.request.user = self.request.db.adminusers.find_one({'username': username}) if not self.request.user: return {'ok': False, 'message': 'The admin user %s does not exists' % username} logger.info("/chef-client/run/: Reserve chef node %s" % (str(node_id))) # Saving last agent run time self.request.db.nodes.update({'node_chef_id': node_id},{'$set': {'last_agent_run_time': int(time.time())}}) # Reserve the node settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) node, is_busy = is_node_busy_and_reserve_it(node_id, api, 'client', attempts=3) if not node.attributes.to_dict(): return {'ok': False, 'message': 'The node does not exists (in chef)'} if is_busy: return {'ok': False, 'message': 'The node is busy'} return {'ok': True}
def __call__(self, node, value): from iscompatible import iscompatible, string_to_tuple super(UpdateControlFileValidator, self).__call__(node,value) request = pyramid.threadlocal.get_current_request() controlfile = self.decompress + os.sep + 'control' settings = get_current_registry().settings api = get_chef_api(settings, request.user) cookbook = get_cookbook(api, settings.get('chef.cookbook_name')) if os.path.exists(controlfile): gecoscc_require = cookbook_require = None with open(controlfile,'r') as f: for line in f: if line.startswith('gecoscc'): gecoscc_require = line elif line.startswith('cookbook'): cookbook_require = line if gecoscc_require and not iscompatible(gecoscc_require, string_to_tuple(request.VERSION)): node.raise_invalid(gettext(self.err_msg)) if cookbook_require and not iscompatible(cookbook_require, string_to_tuple(cookbook['version'])): node.raise_invalid(gettext(self.err_msg))
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, str(chef_client.private_key), 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 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 computer_deleted(self, user, obj, computers=None): node_chef_id = obj.get('node_chef_id', None) if node_chef_id: api = get_chef_api(self.app.conf, user) node = Node(node_chef_id, api) node.delete() client = Client(node_chef_id, api=api) client.delete() self.log_action('deleted', 'Computer', obj)
def command(self): ''' This command recalculate the policies of the selected nodes These nodes are receiving as command arguments ''' db = self.pyramid.db computers = self.get_computers() admin_user = db.adminusers.find_one({'username': self.options.administrator}) if not admin_user: sys.stdout.write('Administrator does not exists\n') sys.exit(1) elif not admin_user.get('is_superuser', None): sys.stdout.write('Administrator should be super user\n') sys.exit(1) api = get_chef_api(self.settings, admin_user) cookbook_name = self.settings['chef.cookbook_name'] num_computers = computers.count() # It is not really the max dots, because the integer division. max_optimal_dots = 80 total_dots = min(num_computers, max_optimal_dots) if total_dots == num_computers: step = 1 else: step = num_computers / total_dots total_dots = int(math.ceil(float(num_computers) / step)) sys.stdout.write('%s 100%%\n' % ('.' * total_dots)) sys.stdout.flush() results_error = {} results_succes = {} for i, comp in enumerate(computers): if i % step == 0: sys.stdout.write('.') sys.stdout.flush() recalculated, reason = recalc_node_policies(db.nodes, db.jobs, comp, admin_user, cookbook_name, api) if recalculated: results_succes[comp['name']] = reason else: results_error[comp['name']] = reason sys.stdout.write('\n\n\n*********** Success ********** \n') for name, reason in results_succes.items(): sys.stdout.write('%s: %s \n' % (name, reason)) sys.stdout.write('\n\n\n*********** Errors ********** \n') for name, reason in results_error.items(): sys.stdout.write('%s: %s \n' % (name, reason)) sys.stdout.flush()
def post(self): ou_id = self.request.POST.get('ou_id') node_id = self.request.POST.get('node_id') ou = None if ou_id: ou = self.collection.find_one({ '_id': ObjectId(ou_id), 'type': 'ou' }) else: ou_availables = self.request.user.get('ou_availables') if isinstance(ou_availables, list) and len(ou_availables) > 0: ou = self.collection.find_one({ '_id': { '$in': [ObjectId(ou_ava_id) for ou_ava_id in ou_availables] }, 'type': 'ou', 'path': { '$ne': 'root' } }) if not ou: return {'ok': False, 'message': 'Ou does not exists'} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) computer_id = register_node(api, node_id, ou, self.collection) if not computer_id: return {'ok': False, 'message': 'Node does not exist (in chef)'} elif computer_id == 'duplicated': return { 'ok': False, 'message': 'There is another node with this name (in gcc)' } elif computer_id == 'duplicated-node-id': return { 'ok': False, 'message': 'There is another node with this node chef id (in gcc)' } elif computer_id == 'path-err': return { 'ok': False, 'message': 'Unable to add gecos path ids and names to chef node' } computer = self.collection.find_one({'_id': computer_id}) apply_policies_to_computer(self.collection, computer, self.request.user) update_tree(computer['path']) return {'ok': True}
def _check_if_user_belongs_to_admin_group(request, organization, username): chefusername = toChefUsername(username) settings = get_current_registry().settings api = get_chef_api(settings, request.user) admins_group = api['/organizations/%s/groups/admins' % (organization)] if not chefusername in admins_group: # Check if exists an association request for this user assoc_requests = None try: assoc_requests = api['/organizations/%s/association_requests' % (organization)] except ChefServerNotFoundError: pass association_id = None for req in assoc_requests: if req["username"] == chefusername: association_id = req["id"] if association_id is None: # Set an association request for the user in that organization try: data = {"user": chefusername} response = api.api_request( 'POST', '/organizations/%s/association_requests' % (organization), data=data) association_id = response["uri"].split("/")[-1] except ChefServerError: # Association already exists? pass if association_id is not None: # Accept the association request logger.info('Adding %s user to default organization' % (username)) api.api_request('PUT', '/users/%s/association_requests/%s' % (chefusername, association_id), data={"response": 'accept'}) # Add the user to the group logger.info('Adding %s user to admins group' % (username)) admins_group['users'].append(chefusername) api.api_request('PUT', '/organizations/%s/groups/admins' % (organization), data={ "groupname": admins_group["groupname"], "actors": { "users": admins_group['users'], "groups": admins_group["groups"] } })
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 admin_delete(context, request): if request.method != 'DELETE': raise HTTPMethodNotAllowed("Only delete method is accepted") username = request.GET.get('username') if request.session['auth.userid'] == username: forget(request) settings = get_current_registry().settings api = get_chef_api(settings, request.user) success_remove_chef = delete_chef_admin_user(api, username) if not success_remove_chef: messages.created_msg(request, _('User deleted unsuccessfully from chef'), 'danger') request.userdb.delete_users({'username': username}) messages.created_msg(request, _('User deleted successfully'), 'success') return {'ok': 'ok'}
def put(self): node_id = self.request.POST.get('node_id') username = self.request.POST.get('gcc_username') if not node_id: return {'ok': False, 'message': 'Please set a node id (node_id)'} if not username: return {'ok': False, 'message': 'Please set a admin username (gcc_username)'} self.request.user = self.request.db.adminusers.find_one({'username': username}) if not self.request.user: return {'ok': False, 'message': 'The admin user %s does not exists' % username} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) node = Node(node_id, api) job_status = node.attributes.get('job_status') reserve_node = False if job_status: node = reserve_node_or_raise(node_id, api, 'gcc-chef-status-%s' % random.random(), attempts=3) reserve_node = True chef_client_error = False for job_id, job_status in job_status.to_dict().items(): job = self.collection.find_one({'_id': ObjectId(job_id)}) if not job: continue if job_status['status'] == 0: self.collection.update({'_id': job['_id']}, {'$set': {'status': 'finished', 'last_update': datetime.datetime.utcnow()}}) else: chef_client_error = True self.collection.update({'_id': job['_id']}, {'$set': {'status': 'errors', 'message': job_status.get('message', 'Error'), 'last_update': datetime.datetime.utcnow()}}) self.request.db.nodes.update({'node_chef_id': node_id}, {'$set': {'error_last_chef_client': chef_client_error}}) invalidate_jobs(self.request) node.attributes.set_dotted('job_status', {}) users_old = self.get_attr(node, USERS_OLD) users = self.get_attr(node, USERS_OHAI) if not users_old or users_old != users: if not reserve_node: node = reserve_node_or_raise(node_id, api, 'gcc-chef-status-%s' % random.random(), attempts=3) return self.check_users(node) if job_status: save_node_and_free(node) return {'ok': True}
def save(self, admin_user): self.collection.insert(admin_user) admin_user['plain_password'] = self.cstruct['password'] settings = get_current_registry().settings user = self.request.user api = get_chef_api(settings, user) try: create_chef_admin_user(api, settings, admin_user['username']) self.created_msg(_('User created successfully')) return True except ChefServerError as e: self.created_msg(e.message, 'danger') self.collection.remove({'username': admin_user['username']}) raise e
def object_action(self, user, obj, objold=None, action=None, computers=None): api = get_chef_api(self.app.conf, user) cookbook = get_cookbook(api, self.app.conf.get('chef.cookbook_name')) computers = computers or self.get_related_computers(obj) are_new_jobs = False for computer in computers: try: job_ids_by_computer = [] node_chef_id = computer.get('node_chef_id', None) node = reserve_node_or_raise(node_chef_id, api, 'gcc-tasks-%s-%s' % (obj['_id'], random.random()), 10) if not node.get(self.app.conf.get('chef.cookbook_name')): raise NodeNotLinked("Node %s is not linked" % node_chef_id) error_last_saved = computer.get('error_last_saved', False) error_last_chef_client = computer.get('error_last_chef_client', False) force_update = error_last_saved or error_last_chef_client node, updated = self.update_node(user, computer, obj, objold, node, action, job_ids_by_computer, force_update) if not updated: save_node_and_free(node) continue are_new_jobs = True self.validate_data(node, cookbook, api) save_node_and_free(node) if error_last_saved: self.db.nodes.update({'_id': computer['_id']}, {'$set': {'error_last_saved': False}}) except NodeNotLinked as e: self.report_node_not_linked(computer, user, obj, action) are_new_jobs = True save_node_and_free(node, api, refresh=True) except NodeBusyException as e: self.report_node_busy(computer, user, obj, action) are_new_jobs = True except ValidationError as e: if not job_ids_by_computer: self.report_unknown_error(e, user, obj, action, computer) self.report_error(e, job_ids_by_computer, computer, 'Validation error: ') save_node_and_free(node, api, refresh=True) are_new_jobs = True except Exception as e: if not job_ids_by_computer: self.report_unknown_error(e, user, obj, action, computer) self.report_error(e, job_ids_by_computer, computer) try: save_node_and_free(node, api, refresh=True) except: pass are_new_jobs = True if are_new_jobs: invalidate_jobs(self.request, user)
def admin_delete(context, request): if request.method != 'DELETE': raise HTTPMethodNotAllowed("Only delete method is accepted") username = request.GET.get('username') if request.session['auth.userid'] == username: forget(request) settings = get_current_registry().settings api = get_chef_api(settings, request.user) success_remove_chef = delete_chef_admin_user(api, username) if not success_remove_chef: messages.created_msg(request, _('User deleted unsuccessfully from chef'), 'danger') request.userdb.delete_user({'username': username}) messages.created_msg(request, _('User deleted successfully'), 'success') return {'ok': 'ok'}
def put(self): """ Reserve the Chef node before running the Chef client """ # Check the parameters node_id = self.request.POST.get('node_id') username = self.request.POST.get('gcc_username') if not node_id: return {'ok': False, 'message': 'Please set a node id (node_id)'} if not username: return { 'ok': False, 'message': 'Please set a admin username (gcc_username)' } self.request.user = self.request.db.adminusers.find_one( {'username': username}) if not self.request.user: return { 'ok': False, 'message': 'The admin user %s does not exists' % username } logger.info("/chef-client/run/: Reserve chef node %s" % (str(node_id))) # Saving last agent run time self.request.db.nodes.update( {'node_chef_id': node_id}, {'$set': { 'last_agent_run_time': int(time.time()) }}) # Reserve the node settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) node, is_busy = is_node_busy_and_reserve_it(node_id, api, 'client', attempts=3) if not node.attributes.to_dict(): return { 'ok': False, 'message': 'The node does not exists (in chef)' } if is_busy: return {'ok': False, 'message': 'The node is busy'} return {'ok': True}
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 put(self): # implements "knife client reregister" 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) # remove current node's client chef_client = ChefClient(node_id, api) if not chef_client.exists: return {'ok': False, 'message': 'This client does not exists'} chef_client.rekey(api) return {'ok': True, 'message': "Chef node's client has been update", 'client_private_key': chef_client.private_key}
def _check_if_user_belongs_to_admin_group(request, organization, username): chefusername = toChefUsername(username) settings = get_current_registry().settings api = get_chef_api(settings, request.user) admins_group = api['/organizations/%s/groups/admins'%(organization)] if not chefusername in admins_group: # Check if exists an association request for this user assoc_requests = None try: assoc_requests = api['/organizations/%s/association_requests'%(organization)] except ChefServerNotFoundError: pass association_id = None for req in assoc_requests: if req["username"] == chefusername: association_id = req["id"] if association_id is None: # Set an association request for the user in that organization try: data = {"user": chefusername} response = api.api_request('POST', '/organizations/%s/association_requests'%(organization), data=data) association_id = response["uri"].split("/")[-1] except ChefServerError: # Association already exists? pass if association_id is not None: # Accept the association request logger.info('Adding %s user to default organization'%(username)) api.api_request('PUT', '/users/%s/association_requests/%s'%(chefusername, association_id), data={ "response": 'accept' }) # Add the user to the group logger.info('Adding %s user to admins group'%(username)) admins_group['users'].append(chefusername) api.api_request('PUT', '/organizations/%s/groups/admins'%(organization), data={ "groupname": admins_group["groupname"], "actors": { "users": admins_group['users'], "groups": admins_group["groups"] } })
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 put(self): node_id = self.request.POST.get('node_id') username = self.request.POST.get('gcc_username') if not node_id: return {'ok': False, 'message': 'Please set a node id (node_id)'} if not username: return {'ok': False, 'message': 'Please set a admin username (gcc_username)'} self.request.user = self.request.db.adminusers.find_one({'username': username}) if not self.request.user: return {'ok': False, 'message': 'The admin user %s does not exists' % username} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) node, is_busy = is_node_busy_and_reserve_it(node_id, api, 'client', attempts=3) if not node.attributes.to_dict(): return {'ok': False, 'message': 'The node does not exists (in chef)'} if is_busy: return {'ok': False, 'message': 'The node is busy'} return {'ok': True}
def server_status(context, request): # Delete a non existent server? server_name = request.GET.get('delete', None) if server_name: request.db.servers.delete_one({"name": server_name}) # Calculate server status list server_list = request.db.servers.find().sort('name') server_status = [] # Get status of each server for server in server_list: status = getServerStatus(server['address']) if status is None: status = {} status['cpu'] = {} status['cpu']['load'] = 0 status['cpu']['name'] = 'UNKNOWN' status['cpu']['ncores'] = 0 status['ram'] = {} status['ram']['total'] = 0 status['ram']['used'] = 0 status['disk'] = {} status['disk']['mountpoints'] = [] status['disk']['total'] = 0 status['disk']['used'] = 0 else: for mpt in status['disk']['mountpoints']: factor = 1 factor_text = 'byte' if int(mpt['size']) > 1024: factor = 1024 factor_text = 'Kbyte' if int(mpt['size']) > (1024*1024): factor = (1024*1024) factor_text = 'Mbyte' if int(mpt['size']) > (1024*1024*1024): factor = (1024*1024*1024) factor_text = 'Gbyte' if int(mpt['size']) > (1024*1024*1024*1024): factor = (1024*1024*1024*1024) factor_text = 'Tbyte' mpt['factor'] = factor mpt['factor_text'] = factor_text status['name'] = server['name'] status['address'] = server['address'] # Check if the address is actually an IP address if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", status['address']): try: # Try to resolve the IP address status['address'] = socket.gethostbyname(status['address']) except Exception as e: logger.warning("server_status: Couldn't resolve IP address from hostname: %s: %s"%(status['address'], str(e))) status['address'] = 'X.X.X.X' server_status.append(status) # Get cookbook info settings = get_current_registry().settings api = get_chef_api(settings, request.user) organization = 'default' cookbook_info = [] try: cookbook_info = api['/organizations/%s/cookbooks'%(organization)] except Exception as e: logger.error("server_status: error getting cookbook info: %s"%(str(e))) return {'server_status': server_status, 'cookbook_info': cookbook_info}
def post(self): try: # Initialize report report = {'inserted': 0, 'updated': 0, 'total': 0, 'warnings': {}} objects_apply_policy = {'computer': [], 'user': []} db = self.request.db # Read GZIP data postedfile = self.request.POST['media'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() # Read XML data xmldoc = minidom.parseString(xmldata) # Get the root domain xmlDomain = xmldoc.getElementsByTagName('Domain')[0] is_ad_master = self.request.POST['master'] == 'True' domain = self._get_domain(self.importSchema[0], xmlDomain, is_ad_master, report) # Convert from AD objects to MongoDB objects mongoObjects = {} mongoObjectsPath = {} for objSchema in self.importSchema: objs = xmldoc.getElementsByTagName(objSchema['adName']) for adObj in objs: if not adObj.hasAttribute('ObjectGUID'): raise Exception('An Active Directory object must has "ObjectGUID" attrib.') mongoObject, is_saving = self._convertADObjectToMongoObject(domain, mongoObjects, objSchema, adObj, is_ad_master, report, objects_apply_policy) report['total'] += 1 if is_saving: mongoObjects[mongoObject['adDistinguishedName']] = mongoObject mongoObjectsPath[mongoObject['adDistinguishedName']] = mongoObject # Order mongoObjects by dependences if mongoObjects: mongoObjects[domain['adDistinguishedName']] = domain mongoObjectsPath[domain['adDistinguishedName']] = domain mongoObjects = self._orderByDependencesMongoObjects(mongoObjects, domain) # Save each MongoDB objects properRootDomainADDN = domain['adDistinguishedName'] for index, mongoObject in mongoObjects.items(): if index == properRootDomainADDN: continue # Get the proper path ("root,{0}._id,{1}._id,{2}._id...") listPath = re.findall(ur'([^, ]+=(?:(?:\\,)|[^,])+)', index) nodePath = ','.join(listPath[1:]) # Find parent mongoObjectParent = mongoObjectsPath[nodePath] mongoObjectParent = self.collection.find_one({'_id': mongoObjectParent['_id']}) path = '{0},{1}'.format(mongoObjectParent['path'], str(mongoObjectParent['_id'])) mongoObject['path'] = path # Save mongoObject self._saveMongoObject(mongoObject) # AD Fixes admin_user = self.request.user chef_server_api = get_chef_api(get_current_registry().settings, admin_user) if is_ad_master: for index, mongoObject in mongoObjects.items(): if mongoObject['type'] == 'group': if mongoObject['members'] != []: mongoObject['members'] = [] self._saveMongoObject(mongoObject) for index, mongoObject in mongoObjects.items(): updateMongoObject = False # MemberOf if mongoObject['type'] in ('user', 'computer'): if 'memberof' not in mongoObject or is_ad_master: mongoObject['memberof'] = [] if 'adPrimaryGroup' in mongoObject and mongoObject['adPrimaryGroup']: group = mongoObjects[mongoObject['adPrimaryGroup']] if is_visible_group(db, group['_id'], mongoObject): if not mongoObject['_id'] in group['members']: group['members'].append(mongoObject['_id']) self._saveMongoObject(group) if mongoObjects[mongoObject['adPrimaryGroup']]['_id'] not in mongoObject['memberof']: mongoObject['memberof'].append(mongoObjects[mongoObject['adPrimaryGroup']]['_id']) else: self._warningGroup(group, mongoObject, report) updateMongoObject = True del mongoObject['adPrimaryGroup'] if 'adMemberOf' in mongoObject and mongoObject['adMemberOf']: for group_id in mongoObject['adMemberOf']: group = mongoObjects[group_id] if is_visible_group(db, group['_id'], mongoObject): if not mongoObject['_id'] in group['members']: group['members'].append(mongoObject['_id']) self._saveMongoObject(group) if mongoObjects[group_id]['_id'] not in mongoObject['memberof']: mongoObject['memberof'].append(mongoObjects[group_id]['_id']) else: self._warningGroup(group, mongoObject, report) updateMongoObject = True del mongoObject['adMemberOf'] # Create Chef-Server Nodes if mongoObject['type'] == 'computer': chef_server_node = reserve_node_or_raise(mongoObject['name'], chef_server_api, 'gcc-ad-import-%s' % random.random(), attempts=3) ohai_gecos_in_runlist = self.RECIPE_NAME_OHAI_GECOS in chef_server_node.run_list gecos_ws_mgmt_in_runlist = self.RECIPE_NAME_GECOS_WS_MGMT in chef_server_node.run_list if not ohai_gecos_in_runlist and not gecos_ws_mgmt_in_runlist: chef_server_node.run_list.append(self.RECIPE_NAME_OHAI_GECOS) chef_server_node.run_list.append(self.RECIPE_NAME_GECOS_WS_MGMT) elif not ohai_gecos_in_runlist and gecos_ws_mgmt_in_runlist: chef_server_node.run_list.insert(chef_server_node.run_list.index(self.RECIPE_NAME_GECOS_WS_MGMT), self.RECIPE_NAME_OHAI_GECOS) elif ohai_gecos_in_runlist and not gecos_ws_mgmt_in_runlist: chef_server_node.run_list.insert(chef_server_node.run_list.index(self.RECIPE_NAME_OHAI_GECOS) + 1, self.RECIPE_NAME_GECOS_WS_MGMT) save_node_and_free(chef_server_node) chef_server_client = Client(mongoObject['name'], api=chef_server_api) if not chef_server_client.exists: chef_server_client.save() mongoObject['node_chef_id'] = mongoObject['name'] updateMongoObject = True # Save changes if updateMongoObject: self._saveMongoObject(mongoObject) # apply policies to new objects for node_type, node_names in objects_apply_policy.items(): nodes = self.collection.find({'name': {'$in': node_names}, 'path': get_filter_this_domain(domain), 'type': node_type}) for node in nodes: apply_policies_function = globals()['apply_policies_to_%s' % node['type']] apply_policies_function(self.collection, node, admin_user, api=chef_server_api) # Return result status = '{0} inserted, {1} updated of {2} objects imported successfully.'.format(report['inserted'], report['updated'], report['total']) response = {'status': status, 'ok': True} except Exception as e: logger.exception(e) response = {'status': u'{0}'.format(e), 'ok': False} warnings = report.get('warnings', []) if warnings: response['warnings'] = warnings return response
def object_action(self, user, obj, objold=None, action=None, computers=None): api = get_chef_api(self.app.conf, user) cookbook = get_cookbook(api, self.app.conf.get('chef.cookbook_name')) computers = computers or self.get_related_computers(obj) are_new_jobs = False for computer in computers: try: job_ids_by_computer = [] node_chef_id = computer.get('node_chef_id', None) node = reserve_node_or_raise( node_chef_id, api, 'gcc-tasks-%s-%s' % (obj['_id'], random.random()), 10) if not node.get(self.app.conf.get('chef.cookbook_name')): raise NodeNotLinked("Node %s is not linked" % node_chef_id) error_last_saved = computer.get('error_last_saved', False) error_last_chef_client = computer.get('error_last_chef_client', False) force_update = error_last_saved or error_last_chef_client node, updated = self.update_node(user, computer, obj, objold, node, action, job_ids_by_computer, force_update) if not updated: save_node_and_free(node) continue are_new_jobs = True self.validate_data(node, cookbook, api) save_node_and_free(node) if error_last_saved: self.db.nodes.update({'_id': computer['_id']}, {'$set': { 'error_last_saved': False }}) except NodeNotLinked as e: self.report_node_not_linked(computer, user, obj, action) are_new_jobs = True save_node_and_free(node, api, refresh=True) except NodeBusyException as e: self.report_node_busy(computer, user, obj, action) are_new_jobs = True except ValidationError as e: if not job_ids_by_computer: self.report_unknown_error(e, user, obj, action, computer) self.report_error(e, job_ids_by_computer, computer, 'Validation error: ') save_node_and_free(node, api, refresh=True) are_new_jobs = True except Exception as e: if not job_ids_by_computer: self.report_unknown_error(e, user, obj, action, computer) self.report_error(e, job_ids_by_computer, computer) try: save_node_and_free(node, api, refresh=True) except: pass are_new_jobs = True if are_new_jobs: invalidate_jobs(self.request, user)
def post(self): try: # Initialize report report = {'inserted': 0, 'updated': 0, 'total': 0, 'warnings': {}} objects_apply_policy = {'computer': [], 'user': []} db = self.request.db # Read GZIP data postedfile = self.request.POST['media'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() # Read XML data xmldoc = minidom.parseString(xmldata) # Get the root domain xmlDomain = xmldoc.getElementsByTagName('Domain')[0] is_ad_master = self.request.POST['master'] == 'True' domain = self._get_domain(self.importSchema[0], xmlDomain, is_ad_master, report) # Convert from AD objects to MongoDB objects mongoObjects = {} mongoObjectsPath = {} for objSchema in self.importSchema: objs = xmldoc.getElementsByTagName(objSchema['adName']) for adObj in objs: if not adObj.hasAttribute('ObjectGUID'): raise Exception( 'An Active Directory object must has "ObjectGUID" attrib.' ) mongoObject, is_saving = self._convertADObjectToMongoObject( domain, mongoObjects, objSchema, adObj, is_ad_master, report, objects_apply_policy) report['total'] += 1 if is_saving: mongoObjects[ mongoObject['adDistinguishedName']] = mongoObject mongoObjectsPath[ mongoObject['adDistinguishedName']] = mongoObject # Order mongoObjects by dependences if mongoObjects: mongoObjects[domain['adDistinguishedName']] = domain mongoObjectsPath[domain['adDistinguishedName']] = domain mongoObjects = self._orderByDependencesMongoObjects( mongoObjects, domain) # Save each MongoDB objects properRootDomainADDN = domain['adDistinguishedName'] for index, mongoObject in mongoObjects.items(): if index == properRootDomainADDN: continue # Get the proper path ("root,{0}._id,{1}._id,{2}._id...") listPath = re.findall(ur'([^, ]+=(?:(?:\\,)|[^,])+)', index) nodePath = ','.join(listPath[1:]) # Find parent mongoObjectParent = mongoObjectsPath[nodePath] mongoObjectParent = self.collection.find_one( {'_id': mongoObjectParent['_id']}) path = '{0},{1}'.format(mongoObjectParent['path'], str(mongoObjectParent['_id'])) mongoObject['path'] = path # Save mongoObject self._saveMongoObject(mongoObject) # AD Fixes admin_user = self.request.user chef_server_api = get_chef_api(get_current_registry().settings, admin_user) if is_ad_master: for index, mongoObject in mongoObjects.items(): if mongoObject['type'] == 'group': if mongoObject['members'] != []: mongoObject['members'] = [] self._saveMongoObject(mongoObject) for index, mongoObject in mongoObjects.items(): updateMongoObject = False # MemberOf if mongoObject['type'] in ('user', 'computer'): if 'memberof' not in mongoObject or is_ad_master: mongoObject['memberof'] = [] if 'adPrimaryGroup' in mongoObject and mongoObject[ 'adPrimaryGroup']: group = mongoObjects[mongoObject['adPrimaryGroup']] if is_visible_group(db, group['_id'], mongoObject): if not mongoObject['_id'] in group['members']: group['members'].append(mongoObject['_id']) self._saveMongoObject(group) if mongoObjects[mongoObject['adPrimaryGroup']][ '_id'] not in mongoObject['memberof']: mongoObject['memberof'].append(mongoObjects[ mongoObject['adPrimaryGroup']]['_id']) else: self._warningGroup(group, mongoObject, report) updateMongoObject = True del mongoObject['adPrimaryGroup'] if 'adMemberOf' in mongoObject and mongoObject[ 'adMemberOf']: for group_id in mongoObject['adMemberOf']: group = mongoObjects[group_id] if is_visible_group(db, group['_id'], mongoObject): if not mongoObject['_id'] in group['members']: group['members'].append(mongoObject['_id']) self._saveMongoObject(group) if mongoObjects[group_id][ '_id'] not in mongoObject['memberof']: mongoObject['memberof'].append( mongoObjects[group_id]['_id']) else: self._warningGroup(group, mongoObject, report) updateMongoObject = True del mongoObject['adMemberOf'] # Create Chef-Server Nodes if mongoObject['type'] == 'computer': chef_server_node = reserve_node_or_raise( mongoObject['name'], chef_server_api, 'gcc-ad-import-%s' % random.random(), attempts=3) ohai_gecos_in_runlist = self.RECIPE_NAME_OHAI_GECOS in chef_server_node.run_list gecos_ws_mgmt_in_runlist = self.RECIPE_NAME_GECOS_WS_MGMT in chef_server_node.run_list if not ohai_gecos_in_runlist and not gecos_ws_mgmt_in_runlist: chef_server_node.run_list.append( self.RECIPE_NAME_OHAI_GECOS) chef_server_node.run_list.append( self.RECIPE_NAME_GECOS_WS_MGMT) elif not ohai_gecos_in_runlist and gecos_ws_mgmt_in_runlist: chef_server_node.run_list.insert( chef_server_node.run_list.index( self.RECIPE_NAME_GECOS_WS_MGMT), self.RECIPE_NAME_OHAI_GECOS) elif ohai_gecos_in_runlist and not gecos_ws_mgmt_in_runlist: chef_server_node.run_list.insert( chef_server_node.run_list.index( self.RECIPE_NAME_OHAI_GECOS) + 1, self.RECIPE_NAME_GECOS_WS_MGMT) save_node_and_free(chef_server_node) chef_server_client = Client(mongoObject['name'], api=chef_server_api) if not chef_server_client.exists: chef_server_client.save() mongoObject['node_chef_id'] = mongoObject['name'] updateMongoObject = True # Save changes if updateMongoObject: self._saveMongoObject(mongoObject) # apply policies to new objects for node_type, node_names in objects_apply_policy.items(): nodes = self.collection.find({ 'name': { '$in': node_names }, 'path': get_filter_this_domain(domain), 'type': node_type }) for node in nodes: apply_policies_function = globals()['apply_policies_to_%s' % node['type']] apply_policies_function(self.collection, node, admin_user, api=chef_server_api) # Return result status = '{0} inserted, {1} updated of {2} objects imported successfully.'.format( report['inserted'], report['updated'], report['total']) response = {'status': status, 'ok': True} except Exception as e: logger.exception(e) response = {'status': u'{0}'.format(e), 'ok': False} warnings = report.get('warnings', []) if warnings: response['warnings'] = warnings return response
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 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): pass return result
def command(self): ''' This command recalculate the policies of the selected nodes These nodes are receiving as command arguments ''' db = self.pyramid.db computers, num_computers = self.get_computers() admin_user = db.adminusers.find_one( {'username': self.options.administrator}) if not admin_user: sys.stdout.write('Administrator does not exists\n') sys.exit(1) elif not admin_user.get('is_superuser', None): sys.stdout.write('Administrator should be super user\n') sys.exit(1) api = get_chef_api(self.settings, admin_user) cookbook_name = self.settings['chef.cookbook_name'] # It is not really the max dots, because the integer division. max_optimal_dots = 80 total_dots = min(num_computers, max_optimal_dots) if total_dots == num_computers: step = 1 else: step = old_div(num_computers, total_dots) total_dots = int(math.ceil(float(num_computers) / step)) sys.stdout.write('%s 100%%\n' % ('.' * total_dots)) sys.stdout.flush() results_error = {} results_succes = {} # Get the cookbook cookbook = get_cookbook(api, cookbook_name) schema = cookbook['metadata']['attributes']['json_schema']['object'] # Validate the cookbook schema validator = validator_for(schema) validator.check_schema(schema) for i, comp in enumerate(list(computers)): if i % step == 0: sys.stdout.write('.') sys.stdout.flush() recalculated, reason = recalc_node_policies( db.nodes, db.jobs, comp, admin_user, cookbook_name, api, cookbook, validator) if recalculated: results_succes[comp['name']] = reason else: results_error[comp['name']] = reason sys.stdout.write('\n\n\n*********** Success ********** \n') for name, reason in list(results_succes.items()): sys.stdout.write('%s: %s \n' % (name, reason)) sys.stdout.write('\n\n\n*********** Errors ********** \n') for name, reason in list(results_error.items()): sys.stdout.write('%s: %s \n' % (name, reason)) sys.stdout.flush()
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 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 server_status(context, request): # Delete a non existent server? server_name = request.GET.get('delete', None) if server_name: request.db.servers.remove({"name": server_name}) # Calculate server status list server_list = request.db.servers.find().sort('name') server_status = [] # Get status of each server for server in server_list: status = getServerStatus(server['address']) if status is None: status = {} status['cpu'] = {} status['cpu']['load'] = 0 status['cpu']['name'] = 'UNKNOWN' status['cpu']['ncores'] = 0 status['ram'] = {} status['ram']['total'] = 0 status['ram']['used'] = 0 status['disk'] = {} status['disk']['mountpoints'] = [] status['disk']['total'] = 0 status['disk']['used'] = 0 else: for mpt in status['disk']['mountpoints']: factor = 1 factor_text = 'byte' if int(mpt['size']) > 1024: factor = 1024 factor_text = 'Kbyte' if int(mpt['size']) > (1024*1024): factor = (1024*1024) factor_text = 'Mbyte' if int(mpt['size']) > (1024*1024*1024): factor = (1024*1024*1024) factor_text = 'Gbyte' if int(mpt['size']) > (1024*1024*1024*1024): factor = (1024*1024*1024*1024) factor_text = 'Tbyte' mpt['factor'] = factor mpt['factor_text'] = factor_text status['name'] = server['name'] status['address'] = server['address'] # Check if the address is actually an IP address if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", status['address']): # Try to resolve the IP address status['address'] = socket.gethostbyname(status['address']) server_status.append(status) # Get cookbook info settings = get_current_registry().settings api = get_chef_api(settings, request.user) organization = 'default' cookbook_info = [] try: cookbook_info = api['/organizations/%s/cookbooks'%(organization)] except Exception as e: logger.error("server_status: error getting cookbook info: %s"%(str(e))) return {'server_status': server_status, 'cookbook_info': cookbook_info}
def put(self): node_id = self.request.POST.get('node_id') username = self.request.POST.get('gcc_username') if not node_id: return {'ok': False, 'message': 'Please set a node id (node_id)'} if not username: return {'ok': False, 'message': 'Please set a admin username (gcc_username)'} self.request.user = self.request.db.adminusers.find_one({'username': username}) if not self.request.user: return {'ok': False, 'message': 'The admin user %s does not exists' % username} settings = get_current_registry().settings api = get_chef_api(settings, self.request.user) node = Node(node_id, api) job_status = node.attributes.get('job_status') # After chef-client run, a report handler calls /api/chef_status # Previously, gcc_link attribute of chef node is updated by network policies gcc_link = node.attributes.get('gcc_link') self.request.db.nodes.update({'node_chef_id':node_id},{'$set': {'gcc_link':gcc_link}}) reserve_node = False if job_status: node = reserve_node_or_raise(node_id, api, 'gcc-chef-status-%s' % random.random(), attempts=3) reserve_node = True chef_client_error = False for job_id, job_status in job_status.to_dict().items(): job = self.collection.find_one({'_id': ObjectId(job_id)}) if not job: continue # Parent macrojob = self.collection.find_one({'_id': ObjectId(job['parent'])}) if 'parent' in job else None if job_status['status'] == 0: self.collection.update({'_id': job['_id']}, {'$set': {'status': 'finished', 'last_update': datetime.datetime.utcnow()}}) # Decrement number of children in parent if macrojob and 'counter' in macrojob: macrojob['counter'] -= 1 elif job_status['status'] == 2: self.collection.update({'_id': job['_id']}, {'$set': {'status': 'warnings', 'message': job_status.get('message', 'Warning'), 'last_update': datetime.datetime.utcnow()}}) if macrojob: macrojob['status'] = 'warnings' else: chef_client_error = True self.collection.update({'_id': job['_id']}, {'$set': {'status': 'errors', 'message': job_status.get('message', 'Error'), 'last_update': datetime.datetime.utcnow()}}) if macrojob: macrojob['status'] = 'errors' # Update parent if macrojob: self.collection.update({'_id': macrojob['_id']}, {'$set': {'counter': macrojob['counter'], 'message': self._("Pending: %d") % macrojob['counter'], 'status': 'finished' if macrojob['counter'] == 0 else macrojob['status']}}) self.request.db.nodes.update({'node_chef_id': node_id}, {'$set': {'error_last_chef_client': chef_client_error}}) invalidate_jobs(self.request) node.attributes.set_dotted('job_status', {}) users_old = self.get_attr(node, USERS_OLD) users = self.get_attr(node, USERS_OHAI) if not users_old or users_old != users: if not reserve_node: node = reserve_node_or_raise(node_id, api, 'gcc-chef-status-%s' % random.random(), attempts=3) return self.check_users(node, api) if job_status: save_node_and_free(node) return {'ok': True}