Exemple #1
0
    def process_drydock_region(self, name, data):
        """Process the data/spec section of a Region document.

        :param name: the document name attribute
        :param data: the dictionary of the data/spec section
        """
        model = objects.Site()

        # Need to add validation logic, we'll assume the input is
        # valid for now
        model.name = name
        model.status = hd_fields.SiteStatus.Unknown
        model.source = hd_fields.ModelSource.Designed

        model.tag_definitions = objects.NodeTagDefinitionList()

        tag_defs = data.get('tag_definitions', [])

        for t in tag_defs:
            tag_model = objects.NodeTagDefinition()
            tag_model.tag = t.get('tag', '')
            tag_model.type = t.get('definition_type', '')
            tag_model.definition = t.get('definition', '')

            if tag_model.type not in ['lshw_xpath']:
                raise errors.IngesterError('Unknown definition_type in '
                                           'tag_definition instance: %s' %
                                           (t.definition_type))
            model.tag_definitions.append(tag_model)

        auth_keys = data.get('authorized_keys', [])

        model.authorized_keys = [k for k in auth_keys]

        return model
Exemple #2
0
    def process_drydock_document(self, doc):
        """Process a parsed YAML document.

        :param doc: The dictionary from parsing the YAML document
        """
        kind = doc.get('kind', '')
        doc_processor = YamlIngester.v1_doc_handlers.get(kind, None)
        if doc_processor is None:
            raise errors.IngesterError("Invalid document Kind %s" % kind)
        metadata = doc.get('metadata', {})
        doc_name = metadata.get('name')
        return doc_processor(self, doc_name, doc.get('spec', {}))
Exemple #3
0
    def process_drydock_document(self, doc):
        """Process a parsed YAML document.

        :param doc: The dictionary from parsing the YAML document
        """
        (schema_ns, kind, version) = doc.get('schema', '').split('/')
        if version == 'v1':
            doc_processor = DeckhandIngester.v1_doc_handlers.get(kind, None)
        else:
            doc_processor = None

        if doc_processor is None:
            raise errors.IngesterError(
                "Invalid document - Kind %s and Version %s" % (kind, version))
        metadata = doc.get('metadata', {})
        doc_name = metadata.get('name')
        return doc_processor(self, doc_name, doc.get('data', {}))
Exemple #4
0
    def process_drydock_node(self, name, data):
        """Process the data/spec section of a BaremetalNode document.

        :param name: the document name attribute
        :param data: the dictionary of the data/spec section
        """
        model = objects.BaremetalNode()
        model.name = name
        model.source = hd_fields.ModelSource.Designed

        self.process_host_common_fields(data, model)

        node_metadata = data.get('metadata', {})
        model.boot_mac = node_metadata.get('boot_mac', None)

        addresses = data.get('addressing', [])

        if len(addresses) == 0:
            raise errors.IngesterError('BaremetalNode needs at least'
                                       ' 1 assigned address')

        model.addressing = objects.IpAddressAssignmentList()

        for a in addresses:
            assignment = objects.IpAddressAssignment()

            address = a.get('address', '')
            if address == 'dhcp':
                assignment.type = 'dhcp'
                assignment.address = None
                assignment.network = a.get('network')

                model.addressing.append(assignment)
            elif address != '':
                assignment.type = 'static'
                assignment.address = a.get('address')
                assignment.network = a.get('network')

                model.addressing.append(assignment)
            else:
                self.log.error("Invalid address assignment %s on Node %s" %
                               (address, self.name))

        return model
Exemple #5
0
    def parse_docs(self, doc_blob):
        """Translate a YAML string into the internal Drydock model.

        Returns a tuple of a objects.TaskStatus instance to summarize all
        document processing and a list of models yields by successful processing

        :param doc_blob: bytes representing a utf-8 encoded YAML string
        """
        models = []
        yaml_string = doc_blob.decode()
        self.logger.debug("yamlingester:parse_docs - Parsing YAML string.")
        try:
            parsed_data = yaml.safe_load_all(yaml_string)
        except yaml.YAMLError as err:
            if hasattr(err, 'problem_mark'):
                mark = err.problem_mark
                raise errors.IngesterError(
                    "Error parsing YAML at (l:%s, c:%s): %s" %
                    (mark.line + 1, mark.column + 1, err))
            else:
                raise errors.IngesterError("Error parsing YAML: %s" % (err))

        # tracking processing status to provide a complete summary of issues
        ps = objects.TaskStatus()
        ps.set_status(hd_fields.ActionResult.Success)
        for d in parsed_data:
            api = d.get('apiVersion', '')
            if api.startswith('drydock/'):
                try:
                    model = self.process_drydock_document(d)
                    ps.add_status_msg(
                        msg="Successfully processed Drydock document type %s."
                        % d.get('kind'),
                        error=False,
                        ctx_type='document',
                        ctx=model.get_id())
                    models.append(model)
                except errors.IngesterError as ie:
                    msg = "Error processing document: %s" % str(ie)
                    self.logger.warning(msg)
                    if d.get('metadata', {}).get('name', None) is not None:
                        ctx = d.get('metadata').get('name')
                    else:
                        ctx = 'Unknown'
                    ps.add_status_msg(msg=msg,
                                      error=True,
                                      ctx_type='document',
                                      ctx=ctx)
                    ps.set_status(hd_fields.ActionResult.Failure)
                except Exception as ex:
                    msg = "Unexpected error processing document: %s" % str(ex)
                    self.logger.error(msg, exc_info=True)
                    if d.get('metadata', {}).get('name', None) is not None:
                        ctx = d.get('metadata').get('name')
                    else:
                        ctx = 'Unknown'
                    ps.add_status_msg(msg=msg,
                                      error=True,
                                      ctx_type='document',
                                      ctx=ctx)
                    ps.set_status(hd_fields.ActionResult.Failure)
            elif api.startswith('promenade/'):
                (foo, api_version) = api.split('/')
                if api_version == 'v1':
                    kind = d.get('kind')
                    metadata = d.get('metadata', {})

                    target = metadata.get('target', 'all')
                    name = metadata.get('name', None)

                    model = objects.PromenadeConfig(
                        target=target,
                        name=name,
                        kind=kind,
                        document=base64.b64encode(
                            bytearray(yaml.dump(d),
                                      encoding='utf-8')).decode('ascii'))
                    ps.add_status_msg(
                        msg="Successfully processed Promenade document.",
                        error=False,
                        ctx_type='document',
                        ctx=name)
                    models.append(model)
        return (ps, models)
Exemple #6
0
    def parse_docs(self, doc_blob):
        """Translate a YAML string into the internal Drydock model.

        Returns a tuple of a objects.TaskStatus instance to summarize all
        document processing and a list of models yielded by successful processing

        :param doc_blob: bytes representing a utf-8 encoded YAML string
        """
        models = []
        yaml_string = doc_blob.decode()
        self.logger.debug("yamlingester:parse_docs - Parsing YAML string.")
        try:
            parsed_data = yaml.safe_load_all(yaml_string)
        except yaml.YAMLError as err:
            if hasattr(err, 'problem_mark'):
                mark = err.problem_mark
                raise errors.IngesterError(
                    "Error parsing YAML at (l:%s, c:%s): %s" %
                    (mark.line + 1, mark.column + 1, err))
            else:
                raise errors.IngesterError("Error parsing YAML: %s" % (err))

        # tracking processing status to provide a complete summary of issues
        ps = objects.TaskStatus()
        ps.set_status(hd_fields.ActionResult.Success)
        for d in parsed_data:
            try:
                (schema_ns, doc_kind, doc_version) = d.get('schema',
                                                           '').split('/')
            except ValueError as ex:
                self.logger.error(
                    "Error with document structure.", exc_info=ex)
                self.logger.debug("Error document\n%s" % yaml.dump(d))
                continue
            if schema_ns == 'drydock':
                try:
                    doc_errors = self.validate_drydock_document(d)
                    if len(doc_errors) > 0:
                        doc_ctx = d.get('metadata', {}).get('name', 'Unknown')
                        for e in doc_errors:
                            ps.add_status_msg(
                                msg="%s:%s validation error: %s" %
                                (doc_kind, doc_version, e),
                                error=True,
                                ctx_type='document',
                                ctx=doc_ctx)
                        ps.set_status(hd_fields.ActionResult.Failure)
                        continue
                    model = self.process_drydock_document(d)
                    ps.add_status_msg(
                        msg="Successfully processed Drydock document type %s."
                        % doc_kind,
                        error=False,
                        ctx_type='document',
                        ctx=model.get_id())
                    models.append(model)
                except errors.IngesterError as ie:
                    msg = "Error processing document: %s" % str(ie)
                    self.logger.warning(msg)
                    if d.get('metadata', {}).get('name', None) is not None:
                        ctx = d.get('metadata').get('name')
                    else:
                        ctx = 'Unknown'
                    ps.add_status_msg(
                        msg=msg, error=True, ctx_type='document', ctx=ctx)
                    ps.set_status(hd_fields.ActionResult.Failure)
                except Exception as ex:
                    msg = "Unexpected error processing document: %s" % str(ex)
                    self.logger.error(msg, exc_info=True)
                    if d.get('metadata', {}).get('name', None) is not None:
                        ctx = d.get('metadata').get('name')
                    else:
                        ctx = 'Unknown'
                    ps.add_status_msg(
                        msg=msg, error=True, ctx_type='document', ctx=ctx)
                    ps.set_status(hd_fields.ActionResult.Failure)
        return (ps, models)
Exemple #7
0
    def parse_docs(self, doc_blob):
        """Translate a YAML string into the internal Drydock model.

        Returns a tuple of a objects.TaskStatus instance to summarize all
        document processing and a list of models yielded by successful processing

        :param doc_blob: bytes representing a utf-8 encoded YAML string
        """
        models = []
        yaml_string = doc_blob.decode()
        self.logger.debug("yamlingester:parse_docs - Parsing YAML string.")
        try:
            parsed_data = yaml.safe_load_all(yaml_string)
        except yaml.YAMLError as err:
            if hasattr(err, 'problem_mark'):
                mark = err.problem_mark
                raise errors.IngesterError(
                    "Error parsing YAML at (l:%s, c:%s): %s" %
                    (mark.line + 1, mark.column + 1, err))
            else:
                raise errors.IngesterError("Error parsing YAML: %s" % (err))

        # tracking processing status to provide a complete summary of issues
        ps = objects.Validation()
        ps.set_status(hd_fields.ValidationResult.Success)
        for d in parsed_data:
            try:
                (schema_ns, doc_kind, doc_version) = d.get('schema',
                                                           '').split('/')
            except ValueError as ex:
                self.logger.error("Error with document structure.",
                                  exc_info=ex)
                self.logger.debug("Error document\n%s" % yaml.dump(d))
                continue
            if schema_ns == 'drydock':
                try:
                    doc_ref = objects.DocumentReference(
                        doc_type=hd_fields.DocumentType.Deckhand,
                        doc_schema=d.get('schema'),
                        doc_name=d.get('metadata', {}).get('name', 'Unknown'))
                    doc_errors = self.validate_drydock_document(d)
                    if len(doc_errors) > 0:
                        for e in doc_errors:
                            ps.add_detail_msg(
                                objects.ValidationMessage(
                                    msg="%s:%s schema validation error: %s" %
                                    (doc_kind, doc_version, e),
                                    name="DD001",
                                    docs=[doc_ref],
                                    error=True,
                                    level=hd_fields.MessageLevels.ERROR,
                                    diagnostic=
                                    "Invalid input file - see Drydock Troubleshooting Guide for DD001"
                                ))
                        ps.set_status(hd_fields.ActionResult.Failure)
                        continue
                    model = self.process_drydock_document(d)
                    model.doc_ref = doc_ref
                    models.append(model)
                except errors.IngesterError as ie:
                    msg = "Error processing document: %s" % str(ie)
                    self.logger.warning(msg)
                    ps.add_detail_msg(
                        objects.ValidationMessage(
                            msg=msg,
                            name="DD000",
                            error=True,
                            level=hd_fields.MessageLevels.ERROR,
                            docs=[doc_ref],
                            diagnostic="Exception during document processing "
                            "- see Drydock Troubleshooting Guide "
                            "for DD000"))
                    ps.set_status(hd_fields.ActionResult.Failure)
                except Exception as ex:
                    msg = "Unexpected error processing document: %s" % str(ex)
                    self.logger.error(msg, exc_info=True)
                    ps.add_detail_msg(
                        objects.ValidationMessage(
                            msg=msg,
                            name="DD000",
                            error=True,
                            level=hd_fields.MessageLevels.ERROR,
                            docs=[doc_ref],
                            diagnostic="Unexpected exception during document "
                            "processing - see Drydock Troubleshooting "
                            "Guide for DD000"))
                    ps.set_status(hd_fields.ActionResult.Failure)
        return (ps, models)