def get_summary_yaml(self, params): """Return the node summary YAML formatted.""" node = self.get_object(params) # Produce a "clean" composite details document. details_template = dict.fromkeys(script_output_nsmap.values()) for script_result in ( ScriptResult.objects.filter( script_name__in=script_output_nsmap.keys(), status=SCRIPT_STATUS.PASSED, script_set__node=node, ) .only( "status", "script_name", "updated", "stdout", "script__id", "script_set__node", ) .order_by("script_name", "-updated") .distinct("script_name") ): namespace = script_output_nsmap[script_result.name] details_template[namespace] = script_result.stdout probed_details = merge_details_cleanly(details_template) # We check here if there's something to show instead of after # the call to get_single_probed_details() because here the # details will be guaranteed well-formed. if len(probed_details.xpath("/*/*")) == 0: return "" else: return XMLToYAML( etree.tostring(probed_details, encoding=str, pretty_print=True) ).convert()
def get_summary_xml(self, params): """Return the node summary XML formatted.""" node = self.get_object(params) # Produce a "clean" composite details document. details_template = dict.fromkeys(script_output_nsmap.values()) for script_result in node.get_latest_script_results.filter( script_name__in=script_output_nsmap.keys(), status=SCRIPT_STATUS.PASSED, script_set__node=node).only( 'script_name', 'updated', 'stdout', 'script__id', 'script_set__node').order_by( 'script_name', '-updated').distinct('script_name'): namespace = script_output_nsmap[script_result.name] details_template[namespace] = script_result.stdout probed_details = merge_details_cleanly(details_template) # We check here if there's something to show instead of after # the call to get_single_probed_details() because here the # details will be guaranteed well-formed. if len(probed_details.xpath('/*/*')) == 0: return '' else: return etree.tostring(probed_details, encoding=str, pretty_print=True)
def dehydrate(self, obj, data, for_list=False): """Add extra fields to `data`.""" data["fqdn"] = obj.fqdn data["actions"] = list(compile_node_actions(obj, self.user).keys()) data["node_type_display"] = obj.get_node_type_display() data["link_type"] = NODE_TYPE_TO_LINK_TYPE[obj.node_type] data["tags"] = [tag.name for tag in obj.tags.all()] if obj.node_type == NODE_TYPE.MACHINE or ( obj.is_controller and not for_list ): # Disk count and storage amount is shown on the machine listing # page and the machine and controllers details page. blockdevices = self.get_blockdevices_for(obj) physical_blockdevices = [ blockdevice for blockdevice in blockdevices if isinstance(blockdevice, PhysicalBlockDevice) ] data["physical_disk_count"] = len(physical_blockdevices) data["storage"] = round( sum(blockdevice.size for blockdevice in physical_blockdevices) / (1000 ** 3), 1, ) data["storage_tags"] = self.get_all_storage_tags(blockdevices) commissioning_script_results = [] testing_script_results = [] log_results = set() for hw_type in self._script_results.get(obj.id, {}).values(): for script_result in hw_type: if ( script_result.script_set.result_type == RESULT_TYPE.INSTALLATION ): # Don't include installation results in the health # status. continue elif script_result.status == SCRIPT_STATUS.ABORTED: # LP: #1724235 - Ignore aborted scripts. continue elif ( script_result.script_set.result_type == RESULT_TYPE.COMMISSIONING ): commissioning_script_results.append(script_result) if ( script_result.name in script_output_nsmap and script_result.status == SCRIPT_STATUS.PASSED ): log_results.add(script_result.name) elif ( script_result.script_set.result_type == RESULT_TYPE.TESTING ): testing_script_results.append(script_result) data["commissioning_status"] = self.dehydrate_test_statuses( commissioning_script_results ) data["testing_status"] = self.dehydrate_test_statuses( testing_script_results ) data["has_logs"] = ( log_results.difference(script_output_nsmap.keys()) == set() ) else: blockdevices = [] if obj.node_type != NODE_TYPE.DEVICE: # These values are not defined on a device. data["architecture"] = obj.architecture data["osystem"] = obj.osystem data["distro_series"] = obj.distro_series data["memory"] = obj.display_memory() data["status"] = obj.display_status() data["description"] = obj.description data["status_code"] = obj.status if for_list: for attr in ("numa_nodes_count", "sriov_support"): value = getattr(obj, attr, None) if value is not None: data[attr] = value # Filters are only available on machines and devices. if not obj.is_controller: # For filters subnets = self.get_all_subnets(obj) data["subnets"] = [subnet.cidr for subnet in subnets] data["fabrics"] = self.get_all_fabric_names(obj, subnets) data["spaces"] = self.get_all_space_names(subnets) data["extra_macs"] = [ "%s" % mac_address for mac_address in obj.get_extra_macs() ] data["link_speeds"] = sorted( set( [ interface.link_speed for interface in obj.interface_set.all() if interface.link_speed > 0 ] ) ) if not for_list: data["on_network"] = obj.on_network() if obj.node_type != NODE_TYPE.DEVICE: data["numa_nodes"] = [ self.dehydrate_numanode(numa_node) for numa_node in obj.numanode_set.all().order_by("index") ] # XXX lamont 2017-02-15 Much of this should be split out into # individual methods, rather than having this huge block of # dense code here. # Status of the commissioning, testing, and logs tabs data["metadata"] = { metadata.key: metadata.value for metadata in obj.nodemetadata_set.all() } # Network data["interfaces"] = [ self.dehydrate_interface(interface, obj) for interface in obj.interface_set.all().order_by("name") ] data["dhcp_on"] = self.get_providing_dhcp(obj) data["hwe_kernel"] = make_hwe_kernel_ui_text(obj.hwe_kernel) data["power_type"] = obj.power_type data["power_parameters"] = self.dehydrate_power_parameters( obj.power_parameters ) data["power_bmc_node_count"] = ( obj.bmc.node_set.count() if (obj.bmc is not None) else 0 ) # Storage data["disks"] = sorted( chain( ( self.dehydrate_blockdevice(blockdevice, obj) for blockdevice in blockdevices ), ( self.dehydrate_volume_group(volume_group) for volume_group in VolumeGroup.objects.filter_by_node( obj ) ), ( self.dehydrate_cache_set(cache_set) for cache_set in CacheSet.objects.get_cache_sets_for_node( obj ) ), ), key=itemgetter("name"), ) data["supported_filesystems"] = [ {"key": key, "ui": ui} for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES ] data["storage_layout_issues"] = obj.storage_layout_issues() data["special_filesystems"] = [ self.dehydrate_filesystem(filesystem) for filesystem in obj.get_effective_special_filesystems() ] data["grouped_storages"] = self.get_grouped_storages( physical_blockdevices ) ( layout_bd, detected_layout, ) = get_applied_storage_layout_for_node(obj) data["detected_storage_layout"] = detected_layout # The UI knows that a partition is in use when it has a mounted # partition. VMware ESXi does not directly mount the partitions # used. As MAAS can't model that inject a place holder so the # UI knows that these partitions are in use. if detected_layout == "vmfs6": for disk in data["disks"]: if disk["id"] == layout_bd.id: for partition in disk["partitions"]: if partition["name"].endswith("-part3"): # Partition 3 is for the default datastore. # This partition may be modified by the # user. continue partition[ "used_for" ] = "VMware ESXi OS partition" partition["filesystem"] = { "id": -1, "label": "RESERVED", "mount_point": "RESERVED", "mount_options": None, "fstype": None, "is_format_fstype": False, } # Events data["events"] = self.dehydrate_events(obj) # Machine logs data["installation_status"] = self.dehydrate_script_set_status( obj.current_installation_script_set ) # Third party drivers if Config.objects.get_config("enable_third_party_drivers"): # Pull modaliases from the cache modaliases = [] for script_result in commissioning_script_results: if script_result.name == LIST_MODALIASES_OUTPUT_NAME: if script_result.status == SCRIPT_STATUS.PASSED: # STDOUT is deferred in the cache so load it. script_result = ( ScriptResult.objects.filter( id=script_result.id ) .only("id", "status", "stdout") .first() ) modaliases = script_result.stdout.decode( "utf-8" ).splitlines() driver = get_third_party_driver( obj, detected_aliases=modaliases, series=obj.distro_series, ) if "module" in driver and "comment" in driver: data["third_party_driver"] = { "module": driver["module"], "comment": driver["comment"], } return data
def dehydrate(self, obj, data, for_list=False): """Add extra fields to `data`.""" data["fqdn"] = obj.fqdn data["actions"] = list(compile_node_actions(obj, self.user).keys()) data["node_type_display"] = obj.get_node_type_display() data["link_type"] = NODE_TYPE_TO_LINK_TYPE[obj.node_type] data["extra_macs"] = [ "%s" % mac_address for mac_address in obj.get_extra_macs() ] subnets = self.get_all_subnets(obj) data["subnets"] = [subnet.cidr for subnet in subnets] data["fabrics"] = self.get_all_fabric_names(obj, subnets) data["spaces"] = self.get_all_space_names(subnets) data["tags"] = [tag.name for tag in obj.tags.all()] data["metadata"] = { metadata.key: metadata.value for metadata in obj.nodemetadata_set.all() } if obj.node_type != NODE_TYPE.DEVICE: data["architecture"] = obj.architecture data["memory"] = obj.display_memory() data["status"] = obj.display_status() data["status_code"] = obj.status boot_interface = obj.get_boot_interface() if boot_interface is not None: data["pxe_mac"] = "%s" % boot_interface.mac_address data["pxe_mac_vendor"] = obj.get_pxe_mac_vendor() else: data["pxe_mac"] = data["pxe_mac_vendor"] = "" blockdevices = self.get_blockdevices_for(obj) physical_blockdevices = [ blockdevice for blockdevice in blockdevices if isinstance(blockdevice, PhysicalBlockDevice) ] data["physical_disk_count"] = len(physical_blockdevices) data["storage"] = "%3.1f" % ( sum(blockdevice.size for blockdevice in physical_blockdevices) / (1000**3)) data["storage_tags"] = self.get_all_storage_tags(blockdevices) data["grouped_storages"] = self.get_grouped_storages( physical_blockdevices) data["osystem"] = obj.get_osystem(default=self.default_osystem) data["distro_series"] = obj.get_distro_series( default=self.default_distro_series) data["dhcp_on"] = self.get_providing_dhcp(obj) if obj.node_type != NODE_TYPE.DEVICE: commissioning_script_results = [] testing_script_results = [] log_results = set() for hw_type in self._script_results.get(obj.id, {}).values(): for script_result in hw_type: if (script_result.script_set.result_type == RESULT_TYPE.INSTALLATION): # Don't include installation results in the health # status. continue elif script_result.status == SCRIPT_STATUS.ABORTED: # LP: #1724235 - Ignore aborted scripts. continue elif (script_result.script_set.result_type == RESULT_TYPE.COMMISSIONING): commissioning_script_results.append(script_result) if (script_result.name in script_output_nsmap and script_result.status == SCRIPT_STATUS.PASSED): log_results.add(script_result.name) elif (script_result.script_set.result_type == RESULT_TYPE.TESTING): testing_script_results.append(script_result) data["commissioning_script_count"] = len( commissioning_script_results) data["commissioning_status"] = get_status_from_qs( commissioning_script_results) data["commissioning_status_tooltip"] = ( self.dehydrate_hardware_status_tooltip( commissioning_script_results).replace( 'test', 'commissioning script')) data["testing_script_count"] = len(testing_script_results) data["testing_status"] = get_status_from_qs(testing_script_results) data["testing_status_tooltip"] = ( self.dehydrate_hardware_status_tooltip(testing_script_results)) data["has_logs"] = (log_results.difference( script_output_nsmap.keys()) == set()) if not for_list: data["on_network"] = obj.on_network() if obj.node_type != NODE_TYPE.DEVICE: # XXX lamont 2017-02-15 Much of this should be split out into # individual methods, rather than having this huge block of # dense code here. # Network data["interfaces"] = [ self.dehydrate_interface(interface, obj) for interface in obj.interface_set.all().order_by('name') ] data["hwe_kernel"] = make_hwe_kernel_ui_text(obj.hwe_kernel) data["power_type"] = obj.power_type data["power_parameters"] = self.dehydrate_power_parameters( obj.power_parameters) data["power_bmc_node_count"] = obj.bmc.node_set.count() if ( obj.bmc is not None) else 0 # Storage data["disks"] = sorted(chain( (self.dehydrate_blockdevice(blockdevice, obj) for blockdevice in blockdevices), (self.dehydrate_volume_group(volume_group) for volume_group in VolumeGroup.objects.filter_by_node(obj)), (self.dehydrate_cache_set(cache_set) for cache_set in CacheSet.objects.get_cache_sets_for_node(obj)), ), key=itemgetter("name")) data["supported_filesystems"] = [{ 'key': key, 'ui': ui } for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES] data["storage_layout_issues"] = obj.storage_layout_issues() data["special_filesystems"] = [ self.dehydrate_filesystem(filesystem) for filesystem in obj.special_filesystems.order_by("id") ] # Events data["events"] = self.dehydrate_events(obj) # Machine logs data["installation_status"] = self.dehydrate_script_set_status( obj.current_installation_script_set) # Third party drivers if Config.objects.get_config('enable_third_party_drivers'): driver = get_third_party_driver(obj) if "module" in driver and "comment" in driver: data["third_party_driver"] = { "module": driver["module"], "comment": driver["comment"], } return data