Beispiel #1
0
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)
Beispiel #2
0
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'
Beispiel #3
0
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
Beispiel #4
0
    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}
Beispiel #6
0
    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'}
Beispiel #8
0
 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'}
Beispiel #10
0
 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
Beispiel #11
0
 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
Beispiel #12
0
    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
Beispiel #13
0
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.')
Beispiel #17
0
    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)
Beispiel #18
0
    def command(self):
        # Initialization
        self.api = _get_chef_api(self.settings.get('chef.url'),
                                 toChefUsername(self.options.chef_username),
                                 self.options.chef_pem, False,
                                 self.settings.get('chef.version'))

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

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

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

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

                self.slug_check[slug] = policy

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        logger.info('END ;)')
Beispiel #19
0
    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 ;)')
Beispiel #21
0
    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)