Skip to content

Commit da60908

Browse files
committed
review bulk-identity-mgmt; remove metadata from twin example
1 parent 19044b5 commit da60908

File tree

1 file changed

+35
-64
lines changed

1 file changed

+35
-64
lines changed

articles/iot-hub/iot-hub-bulk-identity-mgmt.md

Lines changed: 35 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
11
---
2-
title: Import and export Azure IoT Hub device identities
3-
description: How to use the Azure IoT service SDK to run bulk operations against the identity registry to import and export device identities. Import operations enable you to create, update, and delete device identities in bulk.
2+
title: Import and export device identities
3+
titleSuffix: Azure IoT Hub
4+
description: Use the Azure IoT service SDK to import and export device identities so that you can create, update, and delete device identities in bulk.
45
author: kgremban
56

67
ms.author: kgremban
78
ms.service: iot-hub
89
ms.topic: how-to
9-
ms.date: 06/16/2023
10+
ms.date: 01/25/2024
1011
ms.custom: devx-track-csharp, references_regions
1112
---
1213

1314
# Import and export IoT Hub device identities in bulk
1415

15-
Each IoT hub has an identity registry you can use to create per-device resources in the service. The identity registry also enables you to control access to the device-facing endpoints. This article describes how to import and export device identities in bulk to and from an identity registry, using the ImportExportDeviceSample sample included with the [Microsoft Azure IoT SDK for .NET](https://github.com/Azure/azure-iot-sdk-csharp/tree/main). For more information about how you can use this capability when migrating an IoT hub to a different region, see [How to manually migrate an Azure IoT hub using an Azure Resource Manager template](migrate-hub-arm.md).
16+
Each IoT hub has an identity registry that you can use to create device resources in the service. The identity registry also enables you to control access to the device-facing endpoints. This article describes how to import and export device identities in bulk to and from an identity registry, using the ImportExportDeviceSample sample included with the [Microsoft Azure IoT SDK for .NET](https://github.com/Azure/azure-iot-sdk-csharp/tree/main). For more information about how you can use this capability when migrating an IoT hub to a different region, see [How to manually migrate an Azure IoT hub using an Azure Resource Manager template](migrate-hub-arm.md).
1617

1718
> [!NOTE]
18-
> IoT Hub has recently added virtual network support in a limited number of regions. This feature secures import and export operations and eliminates the need to pass keys for authentication. Initially, virtual network support is available only in these regions: *WestUS2*, *EastUS*, and *SouthCentralUS*. To learn more about virtual network support and the API calls to implement it, see [IoT Hub Support for virtual networks](virtual-network-support.md).
19+
> IoT Hub recently added virtual network support in a limited number of regions. This feature secures import and export operations and eliminates the need to pass keys for authentication. Currently, virtual network support is available only in these regions: *WestUS2*, *EastUS*, and *SouthCentralUS*. To learn more about virtual network support and the API calls to implement it, see [IoT Hub Support for virtual networks](virtual-network-support.md).
1920
20-
Import and export operations take place in the context of *Jobs* that enable you to execute bulk service operations against an IoT hub.
21+
Import and export operations take place in the context of *jobs* that enable you to execute bulk service operations against an IoT hub.
2122

2223
The **RegistryManager** class in the SDK includes the **ExportDevicesAsync** and **ImportDevicesAsync** methods that use the **Job** framework. These methods enable you to export, import, and synchronize the entirety of an IoT hub identity registry.
2324

24-
This topic discusses using the **RegistryManager** class and **Job** system to perform bulk imports and exports of devices to and from an IoT hub's identity registry. You can also use the Azure IoT Hub Device Provisioning Service to enable zero-touch, just-in-time provisioning to one or more IoT hubs without requiring human intervention. To learn more, see the [provisioning service documentation](../iot-dps/index.yml).
25+
This article discusses using the **RegistryManager** class and **Job** system to perform bulk imports and exports of devices to and from an IoT hub's identity registry. You can also use the Azure IoT Hub Device Provisioning Service to enable zero-touch, just-in-time provisioning to one or more IoT hubs. To learn more, see the [provisioning service documentation](../iot-dps/index.yml).
2526

2627
> [!NOTE]
2728
> Some of the code snippets in this article are included from the ImportExportDevicesSample service sample provided with the [Microsoft Azure IoT SDK for .NET](https://github.com/Azure/azure-iot-sdk-csharp/tree/main). The sample is located in the `/iothub/service/samples/how to guides/ImportExportDevicesSample` folder of the SDK and, where specified, code snippets are included from the `ImportExportDevicesSample.cs` file for that SDK sample. For more information about the ImportExportDevicesSample sample and other service samples included in the Azure IoT SDK for.NET, see [Azure IoT hub service samples for C#](https://github.com/Azure/azure-iot-sdk-csharp/tree/main/iothub/service/samples/how%20to%20guides).
2829
2930
## What are jobs?
3031

31-
Identity registry operations use the **Job** system when the operation:
32+
Identity registry operations use the job system when the operation:
3233

3334
* Has a potentially long execution time compared to standard run-time operations.
3435

3536
* Returns a large amount of data to the user.
3637

37-
Instead of a single API call waiting or blocking on the result of the operation, the operation asynchronously creates a **Job** for that IoT hub. The operation then immediately returns a **JobProperties** object.
38+
Instead of a single API call waiting or blocking on the result of the operation, the operation asynchronously creates a job for that IoT hub. The operation then immediately returns a **JobProperties** object.
3839

3940
The following C# code snippet shows how to create an export job:
4041

4142
```csharp
42-
// Call an export job on the IoT Hub to retrieve all devices
43+
// Call an export job on the IoT hub to retrieve all devices
4344
JobProperties exportJob = await
4445
registryManager.ExportDevicesAsync(containerSasUri, false);
4546
```
@@ -56,13 +57,13 @@ RegistryManager registryManager =
5657

5758
To find the connection string for your IoT hub, in the Azure portal:
5859

59-
- Navigate to your IoT hub.
60+
1. Navigate to your IoT hub.
6061

61-
- Select **Shared access policies**.
62+
1. Select **Shared access policies**.
6263

63-
- Select a policy, taking into account the permissions you need.
64+
1. Select a policy, taking into account the permissions you need.
6465

65-
- Copy the connection string from the panel on the right-hand side of the screen.
66+
1. Copy the connection string for that policy.
6667

6768
The following C# code snippet, from the **WaitForJobAsync** method in the SDK sample, shows how to poll every five seconds to see if the job has finished executing:
6869

@@ -93,9 +94,7 @@ Only one active device import or export job is allowed at a time for all IoT Hub
9394

9495
## Export devices
9596

96-
Use the **ExportDevicesAsync** method to export the entirety of an IoT hub identity registry to an Azure Storage blob container using a shared access signature (SAS). For more information about shared access signatures, see [Grant limited access to Azure Storage resources using shared access signatures (SAS)](../storage/common/storage-sas-overview.md).
97-
98-
This method enables you to create reliable backups of your device information in a blob container that you control.
97+
Use the **ExportDevicesAsync** method to export the entirety of an IoT hub identity registry to an Azure Storage blob container using a shared access signature (SAS). This method enables you to create reliable backups of your device information in a blob container that you control.
9998

10099
The **ExportDevicesAsync** method requires two parameters:
101100

@@ -150,7 +149,6 @@ If a device has twin data, then the twin data is also exported together with the
150149
"id":"export-6d84f075-0",
151150
"eTag":"MQ==",
152151
"status":"enabled",
153-
"statusReason":"firstUpdate",
154152
"authentication":null,
155153
"twinETag":"AAAAAAAAAAI=",
156154
"tags":{
@@ -162,35 +160,13 @@ If a device has twin data, then the twin data is also exported together with the
162160
"Temperature":75.1,
163161
"Unit":"F"
164162
},
165-
"$metadata":{
166-
"$lastUpdated":"2017-03-09T18:30:52.3167248Z",
167-
"$lastUpdatedVersion":2,
168-
"Thermostat":{
169-
"$lastUpdated":"2017-03-09T18:30:52.3167248Z",
170-
"$lastUpdatedVersion":2,
171-
"Temperature":{
172-
"$lastUpdated":"2017-03-09T18:30:52.3167248Z",
173-
"$lastUpdatedVersion":2
174-
},
175-
"Unit":{
176-
"$lastUpdated":"2017-03-09T18:30:52.3167248Z",
177-
"$lastUpdatedVersion":2
178-
}
179-
}
180-
},
181-
"$version":2
182163
},
183-
"reported":{
184-
"$metadata":{
185-
"$lastUpdated":"2017-03-09T18:30:51.1309437Z"
186-
},
187-
"$version":1
188-
}
164+
"reported":{}
189165
}
190166
}
191167
```
192168

193-
If you need access to this data in code, you can easily deserialize this data using the **ExportImportDevice** class. The following C# code snippet, from the **ReadFromBlobAsync** method in the SDK sample, shows how to read device information that was previously exported from **ExportImportDevice** into a **BlobClient** instance:
169+
If you need access to this data in code, you can deserialize this data using the **ExportImportDevice** class. The following C# code snippet, from the **ReadFromBlobAsync** method in the SDK sample, shows how to read device information that was previously exported from **ExportImportDevice** into a **BlobClient** instance:
194170

195171
```csharp
196172
private static async Task<List<string>> ReadFromBlobAsync(BlobClient blobClient)
@@ -221,13 +197,13 @@ Take care using the **ImportDevicesAsync** method because in addition to provisi
221197
222198
The **ImportDevicesAsync** method takes two parameters:
223199

224-
* A *string* that contains a URI of an [Azure Storage](../storage/index.yml) blob container to use as *input* to the job. This URI must contain a SAS token that grants read access to the container. This container must contain a blob with the name **devices.txt** that contains the serialized device data to import into your identity registry. The import data must contain device information in the same JSON format that the **ExportImportDevice** job uses when it creates a **devices.txt** blob. The SAS token must include these permissions:
200+
* A *string* that contains a URI of an Azure Storage blob container to use as *input* to the job. This URI must contain a SAS token that grants read access to the container. This container must contain a blob with the name **devices.txt** that contains the serialized device data to import into your identity registry. The import data must contain device information in the same JSON format that the **ExportImportDevice** job uses when it creates a **devices.txt** blob. The SAS token must include these permissions:
225201

226202
```csharp
227203
SharedAccessBlobPermissions.Read
228204
```
229205

230-
* A *string* that contains a URI of an [Azure Storage](../storage/index.yml) blob container to use as *output* from the job. The job creates a block blob in this container to store any error information from the completed import **Job**. The SAS token must include these permissions:
206+
* A *string* that contains a URI of an Azure Storage blob container to use as *output* from the job. The job creates a block blob in this container to store any error information from the completed import job. The SAS token must include these permissions:
231207

232208
```csharp
233209
SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read
@@ -244,7 +220,7 @@ JobProperties importJob =
244220
await registryManager.ImportDevicesAsync(containerSasUri, containerSasUri);
245221
```
246222

247-
This method can also be used to import the data for the device twin. The format for the data input is the same as the format shown in the **ExportDevicesAsync** section. In this way, you can reimport the exported data. The **$metadata** is optional.
223+
This method can also be used to import the data for the device twin. The format for the data input is the same as the format shown in the **ExportDevicesAsync** section. In this way, you can reimport the exported data.
248224

249225
## Import behavior
250226

@@ -259,28 +235,23 @@ You can use the **ImportDevicesAsync** method to perform the following bulk oper
259235

260236
You can perform any combination of the preceding operations within a single **ImportDevicesAsync** call. For example, you can register new devices and delete or update existing devices at the same time. When used along with the **ExportDevicesAsync** method, you can completely migrate all your devices from one IoT hub to another.
261237

262-
If the import file includes twin metadata, then this metadata overwrites the existing twin metadata. If the import file doesn't include twin metadata, then only the `lastUpdateTime` metadata is updated using the current time.
263-
264238
Use the optional **importMode** property in the import serialization data for each device to control the import process per-device. The **importMode** property has the following options:
265239

266-
| importMode | Description |
267-
| --- | --- |
268-
| **Create** |If a device doesn't exist with the specified **ID**, it's newly registered. If the device already exists, an error is written to the log file. |
269-
| **CreateOrUpdate** |If a device doesn't exist with the specified **ID**, it's newly registered. If the device already exists, existing information is overwritten with the provided input data without regard to the **ETag** value. |
270-
| **CreateOrUpdateIfMatchETag** |If a device doesn't exist with the specified **ID**, it's newly registered. If the device already exists, existing information is overwritten with the provided input data only if there's an **ETag** match. If there's an **ETag** mismatch, an error is written to the log file. |
271-
| **Delete** |If a device already exists with the specified **ID**, it's deleted without regard to the **ETag** value. If the device doesn't exist, an error is written to the log file. |
272-
| **DeleteIfMatchETag** |If a device already exists with the specified **ID**, it's deleted only if there's an **ETag** match. If the device doesn't exist, an error is written to the log file. If there's an ETag mismatch, an error is written to the log file. |
273-
| **Update** |If a device already exists with the specified **ID**, existing information is overwritten with the provided input data without regard to the **ETag** value. If the device doesn't exist, an error is written to the log file. |
274-
| **UpdateIfMatchETag** |If a device already exists with the specified **ID**, existing information is overwritten with the provided input data only if there's an **ETag** match. If the device doesn't exist or there's an **ETag** mismatch, an error is written to the log file. |
275-
| **UpdateTwin** |If a twin already exists with the specified **ID**, existing information is overwritten with the provided input data without regard to the twin's **ETag** value. |
276-
| **UpdateTwinIfMatchETag** |If a twin already exists with the specified **ID**, existing information is overwritten with the provided input data only if there's a match on the twin's **ETag** value. The twin's **ETag** is processed independently from the device's **ETag**. If there's a mismatch with the existing twin's **ETag**, an error is written to the log file. |
240+
* **Create**
241+
* **CreateOrUpdate** (default)
242+
* **CreateOrUpdateIfMatchETag**
243+
* **Delete**
244+
* **DeleteIfMatchETag**
245+
* **Update**
246+
* **UpdateIfMatchETag**
247+
* **UpdateTwin**
248+
* **UpdateTwinIfMatchETag**
277249

278-
> [!NOTE]
279-
> If the serialization data doesn't explicitly define an **importMode** flag for a device, it defaults to **createOrUpdate** during the import operation.
250+
For details about each of these import mode options, see [ImportMode](/dotnet/api/microsoft.azure.devices.importmode)
280251

281-
## Import troubleshooting
252+
## Troubleshoot import jobs
282253

283-
Using an import job to create devices may fail with a quota issue when it's close to the device count limit of the IoT hub. This failure can happen even if the total device count is still lower than the quota limit. The **IotHubQuotaExceeded (403002)** error is returned with the following error message: "Total number of devices on IotHub exceeded the allocated quota.”
254+
Using an import job to create devices might fail with a quota issue when it's close to the device count limit of the IoT hub. This failure can happen even if the total device count is still lower than the quota limit. The **IotHubQuotaExceeded (403002)** error is returned with the following error message: "Total number of devices on IotHub exceeded the allocated quota.”
284255

285256
If you get this error, you can use the following query to return the total number of devices registered on your IoT hub:
286257

@@ -290,7 +261,7 @@ SELECT COUNT() as totalNumberOfDevices FROM devices
290261

291262
For information about the total number of devices that can be registered to an IoT hub, see [IoT Hub limits](iot-hub-devguide-quotas-throttling.md#other-limits).
292263

293-
If there's still quota available, you can examine the job output blob for devices that failed with the **IotHubQuotaExceeded (403002)** error. You can then try adding these devices individually to the IoT hub. For example, you can use the **AddDeviceAsync** or **AddDeviceWithTwinAsync** methods. Don't try to add the devices using another job as you may likely encounter the same error.
264+
If there's still quota available, you can examine the job output blob for devices that failed with the **IotHubQuotaExceeded (403002)** error. You can then try adding these devices individually to the IoT hub. For example, you can use the **AddDeviceAsync** or **AddDeviceWithTwinAsync** methods. Don't try to add the devices using another job as you might encounter the same error.
294265

295266
## Import devices example – bulk device provisioning
296267

@@ -402,7 +373,7 @@ private async Task GenerateDevicesAsync(RegistryManager registryManager, int num
402373
Console.WriteLine($"GenerateDevices, time elapsed = {stopwatch.Elapsed}.");
403374
}
404375
```
405-
376+
406377
## Import devices example – bulk deletion
407378

408379
The following C# code snippet, from the **DeleteFromHubAsync** method in the SDK sample, shows you how to delete all of the devices from an IoT hub:

0 commit comments

Comments
 (0)