Use Absl Log in g3 code rather than BMCWEB_LOG
In g3, we mainly rely on absl logs, keeping the same convention
Also a lot of these logs should not be logged ALWAYS.
PiperOrigin-RevId: 781729044
Change-Id: Iedc087534599c10eae1a236556688a23cd8c4b96
diff --git a/g3/managed_store.cpp b/g3/managed_store.cpp
index b19b951..85f4dcf 100644
--- a/g3/managed_store.cpp
+++ b/g3/managed_store.cpp
@@ -583,7 +583,7 @@
std::chrono::duration_cast<std::chrono::milliseconds>(
clockNow() - valueType->lastRefreshAt)
.count());
- BMCWEB_LOG_ALWAYS << "MAX AGE AT THIS POINT: " << age_in_ms;
+ LOG(INFO) << "MAX AGE AT THIS POINT: " << age_in_ms;
std::move(callback)(valueType->errorCode,
valueType->managedProperty.value(), age_in_ms);
});
@@ -628,7 +628,7 @@
const std::string& match_expression,
ecclesia::EventSourceId event_source_id) {
if (match_expression.empty()) {
- BMCWEB_LOG_ALWAYS
+ LOG(WARNING)
<< "D-Bus match expression is empty. Invalid call to subscribe!";
return;
}
@@ -636,7 +636,7 @@
if (requestContext.eventSourceIds == nullptr ||
requestContext.request_type ==
ManagedObjectStoreContext::RequestType::kQuery) {
- BMCWEB_LOG_ALWAYS << "eventSourceIds is null. Invalid call to subscribe!";
+ LOG(WARNING) << "eventSourceIds is null. Invalid call to subscribe!";
return;
}
@@ -649,12 +649,12 @@
ManagedObjectStoreContext::RequestType::kCancelSubscription) {
// Erase the monitor
signal_monitors_.erase(find_monitor);
- BMCWEB_LOG_ALWAYS << "Erased D-Bus monitor for id: "
+ LOG(WARNING) << "Erased D-Bus monitor for id: "
<< event_source_id.ToString();
return;
}
- BMCWEB_LOG_ALWAYS << "D-Bus monitor already created for id: "
+ LOG(WARNING) << "D-Bus monitor already created for id: "
<< event_source_id.ToString();
// Record monitor id regardless of an existing subscription since
@@ -671,23 +671,23 @@
sdbusplus::bus::match_t>(
*system_bus_, match_expression,
[event_source_id, this](sdbusplus::message_t&) {
- BMCWEB_LOG_ALWAYS
+ LOG(INFO)
<< "Received dbus signal. Notifying Subscription service now!";
auto status =
subscription_service_->Notify(event_source_id, absl::OkStatus());
if (status.ok()) {
- BMCWEB_LOG_ALWAYS << "Notified successfully!";
+ LOG(INFO) << "Notified successfully!";
return;
}
- BMCWEB_LOG_ALWAYS << "Error while sending notification: " << status;
+ LOG(WARNING) << "Error while sending notification: " << status;
if (status.code() == absl::StatusCode::kNotFound) {
absl::MutexLock lock(&signal_monitor_mutex_);
signal_monitors_.erase(event_source_id);
- BMCWEB_LOG_ALWAYS << "Erased D-Bus monitor for id: "
+ LOG(INFO) << "Erased D-Bus monitor for id: "
<< event_source_id.ToString();
}
});
- BMCWEB_LOG_ALWAYS << "D-Bus monitor created. Event Source id: "
+ LOG(INFO) << "D-Bus monitor created. Event Source id: "
<< event_source_id.ToString();
});
@@ -1025,7 +1025,7 @@
cached_object->lastUsedAges->pop_front();
}
- BMCWEB_LOG_ALWAYS << "Object found in store. " << " Key: " << key_id
+ LOG(INFO) << "Object found in store. " << " Key: " << key_id
<< " CurrentAge: "
<< clockDurationMilliseconds(current_age)
<< " Context: " << requestContext.toString()
@@ -1042,7 +1042,7 @@
// Evict the object from store as it has become stale.
if (is_object_stale) {
- BMCWEB_LOG_ALWAYS << "Object has become stale! "
+ LOG(INFO) << "Object has become stale! "
<< " service: " << keyType.serviceName
<< " path: " << keyType.objectPath.str
<< " interface: " << keyType.interface << " property: "
diff --git a/tlbmc/g3doc/debug/sensor_debug_guide.md b/tlbmc/g3doc/debug/sensor_debug_guide.md
new file mode 100644
index 0000000..00f03c8
--- /dev/null
+++ b/tlbmc/g3doc/debug/sensor_debug_guide.md
@@ -0,0 +1,209 @@
+# Sensor Debug Guide
+
+go/tlbmc-sensor-debug
+
+<!--*
+# Document freshness: For more information, see go/fresh-source.
+freshness: { owner: 'tlbmc-dev' reviewed: '2025-07-08' }
+*-->
+
+By default, tlBMC store will fail to create when sensor creation fails. Note
+that with traditional dbus-sensors daemons, sensor creation failures are silent
+and will only result in the objects not being created. This results in partial
+data being reported and hides missing sensors in the redfish tree unless they
+are directly queried by a client. tlBMC's behavior allows for verification that
+all TlbmcOwned sensors declared in Entity Manager Config files are successfully
+created and served by tlBMC.
+
+You can verify that tlBMC has failed to initialize by querying the tlBMC root,
+which may result in the following output:
+
+```
+root@HOSTNAME:~# curl localhost/redfish/tlbmc
+{
+ "error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "The requested resource of type named 'tlbmc' was not found.",
+ "MessageArgs": [
+ "",
+ "tlbmc"
+ ],
+ "MessageId": "Base.1.13.0.ResourceNotFound",
+ "MessageSeverity": "Critical",
+ "Resolution": "Provide a valid resource identifier and resubmit the request."
+ }
+ ],
+ "code": "Base.1.13.0.ResourceNotFound",
+ "message": "The requested resource of type named 'tlbmc' was not found."
+ }
+}
+```
+
+This output indicates that tlBMC is currently disabled and will result in a
+fallback to traditional bmcweb. Note that sensor readings may not be present in
+this case if `SkipDbusRead` is configured in EM config files per sensor. This
+guide will describe some common methods for how to debug which sensors fail to
+be created in this situation.
+
+[TOC]
+
+## Check tlBMC Store Creation Failure Logs
+
+To verify that tlBMC has failed during creation of a sensor, we can check the
+bmcweb logs. To check logs, use the following command and expect similar output:
+
+```
+root@HOSTNAME:~# journalctl -u bmcweb | grep -i tlbmc
+...
+Jul 06 09:09:54 {HOSTNAME} bmcweb[1955026]: E0706 09:09:54.072554 1955026 webserver_main_setup.hpp:232] Cannot create tlBMC store!! Error: INTERNAL: Failed to find hwmon under /sys/bus/i2c/devices/i2c-1/1-001a - Disabling tlBMC
+```
+
+This log indicates a failure to create a sensor object in tlBMC, likely due to a
+failure to initialize a sensor which may indicate a real hardware failure.
+
+To find additional information about the exact sensor that is failing, you can
+utilize the bus and address information derived from the log at
+`/sys/bus/i2c/devices/i2c-{BUS}/{BUS}-00{ADDRESS}`. By checking the EM config
+files associated with this platform, you can find the sensor configuration
+associated with the given bus/address. Verifying that the bus/address is correct
+for the intended sensor is an important first step for debug.
+
+## Verify hwmon File Presence and Value
+
+Checking that the expected hwmon file is present on the machine is necessary to
+verify that sensor readings are working as intended. To do so, use the following
+commands and you should expect to see similar output:
+
+```
+root@HOSTNAME:~# ls /sys/bus/i2c/devices/i2c-{BUS}/{BUS}-00{ADDRESS}
+driver hwmon modalias name of_node pec subsystem uevent
+```
+
+Failure to find the hwmon directory shown above could indicate a larger issue,
+such as a real hardware failure (see below).
+
+If the hwmon directory is present, you can verify the intended value of the
+sensor by checking the following:
+
+```
+root@HOSTNAME:~# ls /sys/bus/i2c/devices/i2c-{BUS}/{BUS}-00{ADDRESS}/hwmon/hwmon{*}/
+curr1_crit curr3_input in1_label in3_lcrit_alarm power2_label temp2_crit_alarm
+curr1_crit_alarm curr3_label in1_lcrit in4_crit power3_input temp2_input
+curr1_input curr3_max in1_lcrit_alarm in4_crit_alarm power3_label temp2_lcrit
+curr1_label curr3_max_alarm in1_max in4_input power4_input temp2_lcrit_alarm
+curr1_max curr4_crit in1_max_alarm in4_label power4_label temp2_max
+curr1_max_alarm curr4_crit_alarm in1_min in4_lcrit subsystem temp2_max_alarm
+curr2_crit curr4_input in1_min_alarm in4_lcrit_alarm temp1_crit temp3_crit
+curr2_crit_alarm curr4_label in2_input name temp1_crit_alarm temp3_crit_alarm
+curr2_input curr4_max in2_label of_node temp1_input temp3_input
+curr2_label curr4_max_alarm in3_crit power1_alarm temp1_lcrit temp3_lcrit
+curr2_max device in3_crit_alarm power1_input temp1_lcrit_alarm temp3_lcrit_alarm
+curr2_max_alarm in1_crit in3_input power1_label temp1_max temp3_max
+curr3_crit in1_crit_alarm in3_label power2_alarm temp1_max_alarm temp3_max_alarm
+curr3_crit_alarm in1_input in3_lcrit power2_input temp2_crit uevent
+```
+
+To find the file that corresponds to the sensor you are interested in, you can
+`cat` the value of the `{sensor_type}{*}_label` files to find one that matches
+the label in the EM config. For instance, if the sensor name in the EM config is
+`vout1_Name`, the value `vout1` will be present in one of `in1_label`,
+`in2_label`, `in3_label`, or `in4_label`. The sensor reading will be in the
+corresponding `in{*}_input` file. Verify that this is a well-formed sensor
+reading value as expected.
+
+## Enable allow_sensor_creation_failure in tlBMC Configuration
+
+The method described above has the disadvantage of only being able to diagnose a
+single sensor at a time. tlBMC conveniently provides an option to configure
+bypassing sensor creation failures while still providing useful information for
+debugging. We provide a setting in the tlBMC central configuration to
+`allow_sensor_creation_failure`.
+
+This setting allows tlBMC store to be created regardless of sensor creation
+failures. Valid sensors will still be served by tlBMC and debug information can
+be obtained from tlBMC debug paths such as:
+
+```
+root@HOSTNAME:~# curl localhost/redfish/tlbmc/AllSensors
+{
+...
+"error": {
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "Sensor temperature_{SENSOR_NAME} is not ready in tlBMC Store: Failed to read from input device: No such device or address; input device path: /sys/bus/i2c/devices/i2c-{BUS}/{BUS}-00{ADDRESS}/hwmon/hwmon{*}/temp{*}_input",
+ "MessageId": "Base.1.13.0.InternalError"
+ },
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "Sensor voltage_{SENSOR_NAME} is not ready in tlBMC Store: Read data can't be converted to a number: Invalid argument",
+ "MessageId": "Base.1.13.0.InternalError"
+ },
+ ...
+ ],
+ "code": "Base.1.8.GeneralError",
+ "message": "A general error has occurred. See Resolution for information on how to resolve the error."
+ }
+}
+```
+
+All sensor creation errors encountered during tlBMC store creation are combined
+in the AllSensors response following the
+[Redfish error message spec](https://redfish.dmtf.org/schemas/DSP0266_1.19.0.html#error-responses).
+
+To enable the `allow_sensor_creation_failure` feature, a change must be made
+similar to:
+https://gbmc-private-review.git.corp.google.com/c/meta-google-private/+/35823.
+Add/modify the entry corresponding with the desired platform to include:
+
+```
+sensor_collector_module { enabled: true allow_sensor_creation_failure: true }
+```
+
+Build and flash a bmcweb binary including this change to have the central config
+take effect.
+
+## Verify Real Hardware Failures
+
+For additional information to diagnose sensor failures, it may be helpful to
+check logs using `dmesg`. Consider using the following command and look for logs
+similar to the following:
+
+```
+root@HOSTNAME:~# dmesg | grep "Failed to register"
+[ 92.520183] i2c i2c-{BUS}: Failed to register i2c client {DRIVER} at 0x{ADDRESS} (-16)
+```
+
+This indicates a failure to set up the device which could indicate a real
+failure or the device could have been occupied by another script or service
+during boot.
+
+Potential *short term* solutions in this case could be to:
+
+- Manually bind the device using:
+
+ ```
+ root@HOSTNAME:~# echo "{BUS}-00{ADDRESS}" >
+ /sys/bus/i2c/drivers/{DRIVER}/bind
+ ```
+
+ If the device was temporarily occupied during boot, this may correctly set
+ up the device.
+
+- Powercycle the machine: rebooting has fixed sensor instantiation in some
+ cases
+
+ If either approach above is used, a bug should still be filed and the issue
+ should be reproduced. This flakiness in sensor creation could mask
+ underlying problems e.g. b/428930642.
+
+Note: In some cases, it may be expected to see some `Failed to register i2c
+client` logs, for instance in the case of having sensors configured in the EM
+config for second-source boards. These sensors may be expected to fail to create
+if the FRU on the machine does not correspond with the second-source FRU. Also
+note that expected dmesg error logs are only possible when these sensors are not
+supported by tlBMC. If tlBMC were to support the second source board sensors, a
+separate config would have to be made to logically separate these sensors and
+probe accordingly.
diff --git a/tlbmc/g3doc/general/redfish_resource_ownership_model.md b/tlbmc/g3doc/general/redfish_resource_ownership_model.md
new file mode 100644
index 0000000..eff23fe
--- /dev/null
+++ b/tlbmc/g3doc/general/redfish_resource_ownership_model.md
@@ -0,0 +1,364 @@
+# tlBMC Redfish Resource Ownership Model
+
+go/tlbmc-redfish-resource-ownership
+
+<!--*
+# Document freshness: For more information, see go/fresh-source.
+freshness: { owner: 'tlbmc-dev' reviewed: '2025-05-13' }
+*-->
+
+[TOC]
+
+Note: This is an evolving document and definitions may shift as the scope of
+tlBMC increases.
+
+tlBMC ownership of a redfish resource happens when a redfish URL is sent to the
+tlBMC app rather than the traditional gBMCweb app. As described in
+go/tlbmc-smart-routing, an incoming redfish query may be routed to traditional
+bmcweb or to the tlBMC app depending on if the resource is "owned" by tlBMC,
+this is called smart routing. In the case of tlBMC ownership, a query being sent
+to tlBMC means that tlBMC is providing the query response based on the internal
+representation of the requested object after tlBMC has parsed the EM config.
+There are no dbus calls being made or interactions with other daemons to return
+this response.
+
+There are three possible models for a redfish resource to be "owned" by tlBMC
+today. This document describes the extent to which tlBMC may have ownership over
+a resource.
+
+## Fully Owned
+
+### Chassis
+
+Chassis resources onboarded to tlBMC are detected and fully owned. In this case,
+FRUs are detected by tlBMC over I2C scan and the Redfish response is provided by
+the tlBMC backend. Every part of the Chassis response comes from tlBMC,
+including Fru info received from the eeprom of the device and links to
+associated Chassis, Cables, Processors, or Drives which are configured in the EM
+config.
+
+An example can be seen from this config:
+
+```json
+{
+ "Name": "foo",
+ "ProbeV2": {
+ "IpmiFru": {
+ "BOARD_PRODUCT_NAME": "Foo"
+ }
+ },
+ "ResourceType": "RESOURCE_TYPE_BOARD",
+ "Exposes":[
+ {
+ "Name": "Foo Downstream Port",
+ "Label": "PE0",
+ "Type": "PortDownstream"
+ },
+ {
+ "Type": "MAX31725",
+ "Bus": 1,
+ "Address": "0x4c",
+ "Name": "max31725_0",
+ "Name1": "max31725_1",
+ "TlbmcOwned":true
+ }
+ ],
+ "Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+}
+```
+
+The above config might produce the following redfish response, which contains
+fields fully populated by tlBMC, requiring no additional dbus calls or
+interactions with other daemons.
+
+```json
+{
+ "@odata.id": "/redfish/v1/Chassis/Foo",
+ "@odata.type": "#Chassis.v1_17_0.Chassis",
+ "Assembly": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Assembly"
+ },
+ "Certificates": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Certificates"
+ },
+ "ChassisType": "Module",
+ "Drives": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Drives"
+ },
+ "EnvironmentMetrics": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/EnvironmentMetrics"
+ },
+ "Id": "Foo",
+ "Links": {
+ "ComputerSystems": [
+ {
+ "@odata.id": "/redfish/v1/Systems/system"
+ }
+ ],
+ "Contains": {
+ "@odata.id": "/redfish/v1/Chassis/Bar"
+ },
+ "ManagedBy": [
+ {
+ "@odata.id": "/redfish/v1/Managers/bmc"
+ }
+ ]
+ },
+ "Manufacturer": "Foo_Manufacturer",
+ "Memory": {
+ "@odata.id": "/redfish/v1/Systems/system/Memory"
+ },
+ "Model": "Foo_Model",
+ "Name": "Foo",
+ "PCIeDevices": {
+ "@odata.id": "/redfish/v1/Systems/system/PCIeDevices"
+ },
+ "PCIeSlots": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/PCIeSlots"
+ },
+ "PartNumber": "1111111-11",
+ "Power": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Power"
+ },
+ "PowerState": "On",
+ "PowerSubsystem": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/PowerSubsystem"
+ },
+ "Sensors": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Sensors"
+ },
+ "SerialNumber": "AAAAA-11111111",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ },
+ "Thermal": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/Thermal"
+ },
+ "ThermalSubsystem": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/ThermalSubsystem"
+ },
+ "TrustedComponents": {
+ "@odata.id": "/redfish/v1/Chassis/Foo/TrustedComponents"
+ }
+}
+```
+
+### Sensors
+
+Sensors supported by tlBMC are fully owned. Sensor configurations are parsed
+from EM configs and readings are polled directly from hwmon files. There are no
+dbus calls being made to supply sensor readings in tlBMC.
+
+Note: Since tlBMC does not support all sensor types yet (only Hwmon Temp, PSU,
+and I2CFan sensors for now), tlBMC does not own sensor collection. The response
+at `/redfish/v1/Chassis/{ChassisId}/Sensors` is routed to bmcweb but a query for
+individual sensor will be routed to tlBMC if supported.
+
+An example can be seen from this config:
+
+```json
+"Exposes": [
+ {
+ "Name": "foo_external_sensor",
+ "Units": "Watts",
+ "MinValue": 6500,
+ "MaxValue": 7500,
+ "Type": "ExternalSensor"
+ },
+ {
+ "Name": "foo_psu_sensor",
+ "Address": "0x44",
+ "Bus": "11",
+ "Labels": [
+ "vout1",
+ "vout2",
+ "vout3",
+ "vout4"
+ ],
+ "vout1_Name": "foo_psu_sensor_0",
+ "vout2_Name": "foo_psu_sensor_1",
+ "vout3_Name": "foo_psu_sensor_2",
+ "vout4_Name": "foo_psu_sensor_3",
+ "Type": "ADM1266",
+ "TlbmcOwned": true
+ },
+ ...
+]
+```
+
+Since the `foo_psu_sensor` has the field `"TlbmcOwned"` and is of the supported
+type `ADM1266`, the response when any of these individual sensors is queried
+will be provided by tlBMC.
+
+## Linked Resources Not Owned
+
+For some configurations, tlBMC may detect and own the Chassis resource, but
+there may be resources configured in the EM config file that are not owned by
+tlBMC.
+
+Since the scope of tlBMC is limited to only the Chassis path at the moment it is
+possible for some Chassis to not own the resources linked in its "Links", even
+when configured in the EM config. When these properties are queried, the
+response will be populated from the traditional bmcweb path.
+
+These associated resources that are linked in response but not yet owned by
+tlBMC include:
+
+- Storages
+- Processors
+- Cables
+
+An example can be seen in this config:
+
+```json
+# Assume there are two other Chassis EM configs connecting to the ports
+# Assume there is another Cable EM config with CableUpstreamConnection to Foo Cable Downstream
+{
+...
+ "Exposes": [
+ {
+ "Label": "IO0",
+ "Name": "foo Port 1",
+ "Type": "PortDownstream",
+ "User": "tlbmc"
+ },
+ {
+ "Label": "IO1",
+ "Name": "foo Port 2",
+ "Type": "PortDownstream",
+ "User": "tlbmc"
+ },
+ {
+ "Name": "Foo Cable Downstream",
+ "CableId": "foo_cable",
+ "Type": "CableDownstreamConnection",
+ "User": "tlbmc"
+ },
+ ...
+ {
+ "Name": "cpu0",
+ "Type": "Processor",
+ "User": "tlbmc"
+ },
+ {
+ "Name": "cpu1",
+ "Type": "Processor",
+ "User": "tlbmc"
+ },
+ ],
+ ...
+ "Storage":
+ {
+ "Id": "foo_storage",
+ "User": "tlbmc"
+ }
+...
+}
+```
+
+A snippet of the `Links` field resulting from querying this chassis is provided
+below. This has been annotated to show the resources that are tlBMC owned and
+not. As seen from the EM config above, several fields are configured for tlBMC
+to produce these links but tlBMC does not have ownership of the resource paths
+when queried.
+
+<pre><code class="lang-json">
+ {
+ ...
+ "Links": {
+ "Cables": [
+ {
+ "@odata.id": <del>"/redfish/v1/Cables/foo_cable"</del>
+ }
+ ],
+ "Cables@odata.count": 1,
+ "ComputerSystems": [
+ {
+ "@odata.id": "/redfish/v1/Systems/system"
+ }
+ ],
+ "Contains": [
+ {
+ "@odata.id":<ins>"/redfish/v1/Chassis/bar"</ins>
+ },
+ {
+ "@odata.id":<ins>"/redfish/v1/Chassis/baz"</ins>
+ }
+ ],
+ "Contains@odata.count": 2,
+ "ManagedBy": [
+ {
+ "@odata.id": "/redfish/v1/Managers/bmc"
+ }
+ ],
+ "Processors": [
+ {
+ "@odata.id": <del>"/redfish/v1/Systems/system/Processors/cpu0"</del>
+ },
+ {
+ "@odata.id":<del> "/redfish/v1/Systems/system/Processors/cpu1"</del>
+ }
+ ],
+ "Processors@odata.count": 2,
+ "Storage": [
+ {
+ "@odata.id": <del>"/redfish/v1/Systems/system/Storage/foo_storage"</del>
+ }
+ ],
+ "Storage@odata.count": 1
+ },
+ ...
+}
+</code></pre>
+
+## FRUs Not Detected by tlBMC but Modeled
+
+For some configurations, tlBMC does not detect the existence of the resource but
+may model it. tlBMC would have a TRUE probe for the resource i.e. Cables. In
+this case, the existence of the cable is implied by the successful detection of
+the surrounding Chassis resource and will be populated in the Cables Links of
+the associated Chassis.
+
+Here, tlBMC does not own the resource and querying the `/redfish/v1/Cables` path
+will return the traditional bmcweb response. tlBMC properties in this case exist
+only to correctly populate the associations (Links) to the `/redfish/v1/Cables`
+path in the associated resources that tlBMC does own i.e. upstream and
+downstream chassis to the cable. This is necessary for tlBMC to correctly fully
+own Chassis. In the future, when tlBMC fully owns these resources, the probe
+will become a real probe.
+
+An example can be seen from this cable config:
+
+```json
+{
+ "Exposes": [
+ {
+ "Name": "Foo Cable Downstream",
+ "CableId": "FooCable",
+ "Type": "CableUpstreamConnection",
+ "User": "tlbmc"
+ },
+ {
+ "Name": "Foo Cable Upstream",
+ "CableId": "FooCable",
+ "Type": "CableDownstreamConnection",
+ "User": "tlbmc"
+ }
+ ],
+ "Name": "NcsiCable",
+ "ProbeV2": "TRUE",
+ "ResourceType": "RESOURCE_TYPE_CABLE",
+ "Type": "Cable",
+}
+```
+
+Although tlBMC fields are required in this EM config to create the correct
+relationships when queried, tlBMC does not own `/redfish/v1/Cables/FooCable` and
+this will be served from traditional Bmcweb.