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
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', {}))
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', {}))
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
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)
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)
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)